aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt69
-rw-r--r--CMakePresets.json17
-rw-r--r--include/client/web_socket_client.hpp4
-rw-r--r--include/client/websocketpp_client.hpp44
-rw-r--r--include/data/data.hpp3
-rw-r--r--include/nostr.hpp153
-rw-r--r--include/nostr_service_base.hpp104
-rw-r--r--include/signer/noscrypt_signer.hpp55
-rw-r--r--include/signer/signer.hpp7
-rw-r--r--src/client/websocketpp_client.cpp193
-rw-r--r--src/data/event.cpp6
-rw-r--r--src/nostr_service_base.cpp (renamed from src/nostr_service.cpp)119
-rw-r--r--src/signer/noscrypt_signer.cpp274
-rw-r--r--test/nostr_service_base_test.cpp (renamed from test/nostr_service_test.cpp)185
14 files changed, 622 insertions, 611 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8be787..461fbcc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -75,9 +75,12 @@ include_directories(${SIGNER_INCLUDE_DIR})
set(HEADERS
${INCLUDE_DIR}/nostr.hpp
+ ${INCLUDE_DIR}/nostr_service_base.hpp
${CLIENT_INCLUDE_DIR}/web_socket_client.hpp
+ ${CLIENT_INCLUDE_DIR}/websocketpp_client.hpp
${DATA_INCLUDE_DIR}/data.hpp
${SIGNER_INCLUDE_DIR}/signer.hpp
+ ${SIGNER_INCLUDE_DIR}/noscrypt_signer.hpp
)
set(SOURCE_DIR ./src)
@@ -85,7 +88,7 @@ set(CLIENT_SOURCE_DIR ./src/client)
set(DATA_SOURCE_DIR ./src/data)
set(SIGNER_SOURCE_DIR ./src/signer)
set(SOURCES
- ${SOURCE_DIR}/nostr_service.cpp
+ ${SOURCE_DIR}/nostr_service_base.cpp
${CLIENT_SOURCE_DIR}/websocketpp_client.cpp
${DATA_SOURCE_DIR}/event.cpp
${DATA_SOURCE_DIR}/filters.cpp
@@ -104,33 +107,37 @@ target_link_libraries(aedile PRIVATE
set_target_properties(aedile PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS YES)
#======== Build the tests ========#
-enable_testing()
-include(GoogleTest)
-
-FetchContent_Declare(
- googletest
- URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
-)
-
-set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
-FetchContent_MakeAvailable(googletest)
-
-enable_testing()
-
-set(TEST_DIR ./test)
-set(TEST_SOURCES
- ${TEST_DIR}/nostr_service_test.cpp
-)
-
-add_executable(aedile_test ${TEST_SOURCES} ${HEADERS})
-target_link_libraries(aedile_test PRIVATE
- GTest::gmock
- GTest::gtest
- GTest::gtest_main
- plog::plog
- websocketpp::websocketpp
- aedile
-)
-set_target_properties(aedile_test PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS YES)
-
-gtest_add_tests(TARGET aedile_test)
+if(AEDILE_INCLUDE_TESTS)
+ message(STATUS "Building unit tests.")
+
+ enable_testing()
+ include(GoogleTest)
+
+ FetchContent_Declare(
+ googletest
+ URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
+ )
+
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+ FetchContent_MakeAvailable(googletest)
+
+ enable_testing()
+
+ set(TEST_DIR ./test)
+ set(TEST_SOURCES
+ ${TEST_DIR}/nostr_service_base_test.cpp
+ )
+
+ add_executable(aedile_test ${TEST_SOURCES} ${HEADERS})
+ target_link_libraries(aedile_test PRIVATE
+ GTest::gmock
+ GTest::gtest
+ GTest::gtest_main
+ plog::plog
+ websocketpp::websocketpp
+ aedile
+ )
+ set_target_properties(aedile_test PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS YES)
+
+ gtest_add_tests(TARGET aedile_test)
+endif()
diff --git a/CMakePresets.json b/CMakePresets.json
index 208a085..84c0aff 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -9,6 +9,16 @@
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
+ },
+ {
+ "name": "linux tests",
+ "generator": "Unix Makefiles",
+ "binaryDir": "${sourceDir}/build/linux",
+ "cacheVariables": {
+ "CMAKE_BUILD_TYPE": "Release",
+ "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
+ "AEDILE_INCLUDE_TESTS": "ON"
+ }
}
],
"buildPresets": [
@@ -16,12 +26,17 @@
"name": "linux",
"configurePreset": "linux",
"jobs": 4
+ },
+ {
+ "name": "linux tests",
+ "configurePreset": "linux tests",
+ "jobs": 4
}
],
"testPresets": [
{
"name": "linux",
- "configurePreset": "linux"
+ "configurePreset": "linux tests"
}
]
}
diff --git a/include/client/web_socket_client.hpp b/include/client/web_socket_client.hpp
index eca8e24..19fc949 100644
--- a/include/client/web_socket_client.hpp
+++ b/include/client/web_socket_client.hpp
@@ -10,14 +10,14 @@ namespace nostr
{
namespace client
{
-class IWebSocketClient;
-
/**
* @brief An interface for a WebSocket client singleton.
*/
class IWebSocketClient
{
public:
+ virtual ~IWebSocketClient() = default;
+
/**
* @brief Starts the client.
* @remark This method must be called before any other client methods.
diff --git a/include/client/websocketpp_client.hpp b/include/client/websocketpp_client.hpp
new file mode 100644
index 0000000..becf4fa
--- /dev/null
+++ b/include/client/websocketpp_client.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "web_socket_client.hpp"
+
+namespace nostr
+{
+namespace client
+{
+/**
+ * @brief An implementation of the `IWebSocketClient` interface that uses the WebSocket++ library.
+ */
+class WebsocketppClient : public IWebSocketClient
+{
+public:
+ void start() override;
+
+ void stop() override;
+
+ void openConnection(std::string uri) override;
+
+ bool isConnected(std::string uri) override;
+
+ std::tuple<std::string, bool> send(std::string message, std::string uri) override;
+
+ std::tuple<std::string, bool> send(
+ std::string message,
+ std::string uri,
+ std::function<void(const std::string&)> messageHandler) override;
+
+ void receive(std::string uri, std::function<void(const std::string&)> messageHandler) override;
+
+ void closeConnection(std::string uri) override;
+
+private:
+ typedef websocketpp::client<websocketpp::config::asio_client> websocketpp_client;
+ typedef std::unordered_map<std::string, websocketpp::connection_hdl>::iterator connection_hdl_iterator;
+
+ websocketpp_client _client;
+ std::unordered_map<std::string, websocketpp::connection_hdl> _connectionHandles;
+ std::mutex _propertyMutex;
+};
+} // namespace client
+} // namespace nostr
+
diff --git a/include/data/data.hpp b/include/data/data.hpp
index 78c17c4..46156cd 100644
--- a/include/data/data.hpp
+++ b/include/data/data.hpp
@@ -13,9 +13,6 @@ namespace nostr
{
namespace data
{
-class Event;
-class Filters;
-
/**
* @brief A Nostr event.
* @remark All data transmitted over the Nostr protocol is encoded in JSON blobs. This struct
diff --git a/include/nostr.hpp b/include/nostr.hpp
index d21a86d..c555bbe 100644
--- a/include/nostr.hpp
+++ b/include/nostr.hpp
@@ -21,52 +21,35 @@
namespace nostr
{
-class NostrService;
-
// TODO: Create custom exception types for the nostr namespace.
-class NostrService
+class INostrServiceBase
{
public:
- NostrService(
- std::shared_ptr<plog::IAppender> appender,
- std::shared_ptr<client::IWebSocketClient> client,
- std::shared_ptr<signer::ISigner> signer);
- NostrService(
- std::shared_ptr<plog::IAppender> appender,
- std::shared_ptr<client::IWebSocketClient> client,
- std::shared_ptr<signer::ISigner> signer,
- std::vector<std::string> relays);
- ~NostrService();
-
- std::vector<std::string> defaultRelays() const;
-
- std::vector<std::string> activeRelays() const;
-
- std::unordered_map<std::string, std::vector<std::string>> subscriptions() const;
+ virtual ~INostrServiceBase() = default;
/**
* @brief Opens connections to the default Nostr relays of the instance, as specified in
* the constructor.
* @return A list of the relay URLs to which connections were successfully opened.
*/
- std::vector<std::string> openRelayConnections();
+ virtual std::vector<std::string> openRelayConnections() = 0;
/**
* @brief Opens connections to the specified Nostr relays.
* @returns A list of the relay URLs to which connections were successfully opened.
*/
- std::vector<std::string> openRelayConnections(std::vector<std::string> relays);
+ virtual std::vector<std::string> openRelayConnections(std::vector<std::string> relays) = 0;
/**
* @brief Closes all open relay connections.
*/
- void closeRelayConnections();
+ virtual void closeRelayConnections() = 0;
/**
* @brief Closes any open connections to the specified Nostr relays.
*/
- void closeRelayConnections(std::vector<std::string> relays);
+ virtual void closeRelayConnections(std::vector<std::string> relays) = 0;
/**
* @brief Publishes a Nostr event to all open relay connections.
@@ -74,7 +57,8 @@ public:
* to which relays the event was published successfully, and to which relays the event failed
* to publish.
*/
- std::tuple<std::vector<std::string>, std::vector<std::string>> publishEvent(std::shared_ptr<data::Event> event);
+ virtual std::tuple<std::vector<std::string>, std::vector<std::string>> publishEvent(
+ std::shared_ptr<data::Event> event) = 0;
/**
* @brief Queries all open relay connections for events matching the given set of filters, and
@@ -88,7 +72,8 @@ public:
* set on the filters in the range 1-64, inclusive. If no valid limit is given, it will be
* defaulted to 16.
*/
- std::vector<std::shared_ptr<data::Event>> queryRelays(std::shared_ptr<data::Filters> filters);
+ virtual std::vector<std::shared_ptr<data::Event>> queryRelays(
+ std::shared_ptr<data::Filters> filters) = 0;
/**
* @brief Queries all open relay connections for events matching the given set of filters.
@@ -104,11 +89,11 @@ public:
* events returned from the relay for the given filters. The service will not store the
* events, and they will not be accessible via `getNewEvents`.
*/
- std::string queryRelays(
+ virtual std::string queryRelays(
std::shared_ptr<data::Filters> filters,
std::function<void(const std::string&, std::shared_ptr<data::Event>)> eventHandler,
std::function<void(const std::string&)> eoseHandler,
- std::function<void(const std::string&, const std::string&)> closeHandler);
+ std::function<void(const std::string&, const std::string&)> closeHandler) = 0;
/**
* @brief Closes the subscription with the given ID on all open relay connections.
@@ -116,7 +101,8 @@ public:
* to which relays the message was sent successfully, and which relays failed to receive the
* message.
*/
- std::tuple<std::vector<std::string>, std::vector<std::string>> closeSubscription(std::string subscriptionId);
+ virtual std::tuple<std::vector<std::string>, std::vector<std::string>> closeSubscription(
+ std::string subscriptionId) = 0;
/**
* @brief Closes the subscription with the given ID on the given relay.
@@ -124,119 +110,12 @@ public:
* @remark If the subscription does not exist on the given relay, or if the relay is not
* connected, the method will do nothing and return false.
*/
- bool closeSubscription(std::string subscriptionId, std::string relay);
+ virtual bool closeSubscription(std::string subscriptionId, std::string relay) = 0;
/**
* @brief Closes all open subscriptions on all open relay connections.
* @returns A list of any subscription IDs that failed to close.
*/
- std::vector<std::string> closeSubscriptions();
-
- /**
- * @brief Closes all open subscriptions on the given relays.
- * @returns A list of any subscription IDs that failed to close.
- */
- std::vector<std::string> closeSubscriptions(std::vector<std::string> relays);
-
-private:
- ///< The maximum number of events the service will store for each subscription.
- const int MAX_EVENTS_PER_SUBSCRIPTION = 128;
-
- ///< The WebSocket client used to communicate with relays.
- std::shared_ptr<client::IWebSocketClient> _client;
- ///< The signer used to sign Nostr events.
- std::shared_ptr<signer::ISigner> _signer;
-
- ///< A mutex to protect the instance properties.
- std::mutex _propertyMutex;
- ///< The default set of Nostr relays to which the service will attempt to connect.
- std::vector<std::string> _defaultRelays;
- ///< The set of Nostr relays to which the service is currently connected.
- std::vector<std::string> _activeRelays;
- ///< A map from subscription IDs to the relays on which each subscription is open.
- std::unordered_map<std::string, std::vector<std::string>> _subscriptions;
-
- /**
- * @brief Determines which of the given relays are currently connected.
- * @returns A list of the URIs of currently-open relay connections from the given list.
- */
- std::vector<std::string> getConnectedRelays(std::vector<std::string> relays);
-
- /**
- * @brief Determines which of the given relays are not currently connected.
- * @returns A list of the URIs of currently-unconnected relays from the given list.
- */
- std::vector<std::string> getUnconnectedRelays(std::vector<std::string> relays);
-
- /**
- * @brief Determines whether the given relay is currently connected.
- * @returns True if the relay is connected, false otherwise.
- */
- bool isConnected(std::string relay);
-
- /**
- * @brief Removes the given relay from the instance's list of active relays.
- */
- void eraseActiveRelay(std::string relay);
-
- /**
- * @brief Opens a connection from the client to the given relay.
- */
- void connect(std::string relay);
-
- /**
- * @brief Closes the connection from the client to the given relay.
- */
- void disconnect(std::string relay);
-
- /**
- * @brief Generates a unique subscription ID that may be used to identify event requests.
- * @returns A stringified UUID.
- */
- std::string generateSubscriptionId();
-
- /**
- * @brief Generates a message requesting a relay to close the subscription with the given ID.
- * @returns A stringified JSON object representing the close request.
- */
- std::string generateCloseRequest(std::string subscriptionId);
-
- /**
- * @brief Indicates whether the the service has an open subscription with the given ID.
- * @returns True if the service has the subscription, false otherwise.
- */
- bool hasSubscription(std::string subscriptionId);
-
- /**
- * @brief Indicates whether the service has an open subscription with the given ID on the given
- * relay.
- * @returns True if the subscription exists on the relay, false otherwise.
- */
- bool hasSubscription(std::string subscriptionId, std::string relay);
-
- /**
- * @brief Parses EVENT messages received from the relay and invokes the given event handler.
- * @param message The raw message received from the relay.
- * @param eventHandler A callable object that will be invoked with the subscription ID and the
- * payload of the event.
- * @param eoseHandler A callable object that will be invoked with the subscription ID when the
- * relay sends an EOSE message, indicating it has reached the end of stored events for the
- * given query.
- * @param closeHandler A callable object that will be invoked with the subscription ID and the
- * message sent by the relay if the subscription is ended by the relay.
- */
- void onSubscriptionMessage(
- std::string message,
- std::function<void(const std::string&, std::shared_ptr<data::Event>)> eventHandler,
- std::function<void(const std::string&)> eoseHandler,
- std::function<void(const std::string&, const std::string&)> closeHandler);
-
- /**
- * @brief Parses OK messages received from the relay and invokes the given acceptance handler.
- * @remark The OK message type is sent to indicate whether the relay has accepted an event sent
- * by the client. Note that this is distinct from whether the message was successfully sent to
- * the relay over the WebSocket connection.
- */
- void onAcceptance(std::string message, std::function<void(const bool)> acceptanceHandler);
+ virtual std::vector<std::string> closeSubscriptions() = 0;
};
} // namespace nostr
diff --git a/include/nostr_service_base.hpp b/include/nostr_service_base.hpp
new file mode 100644
index 0000000..6abfedc
--- /dev/null
+++ b/include/nostr_service_base.hpp
@@ -0,0 +1,104 @@
+#pragma once
+
+#include "nostr.hpp"
+
+namespace nostr
+{
+class NostrServiceBase : public INostrServiceBase
+{
+public:
+ NostrServiceBase(
+ std::shared_ptr<plog::IAppender> appender,
+ std::shared_ptr<client::IWebSocketClient> client);
+
+ NostrServiceBase(
+ std::shared_ptr<plog::IAppender> appender,
+ std::shared_ptr<client::IWebSocketClient> client,
+ std::vector<std::string> relays);
+
+ ~NostrServiceBase() override;
+
+ std::vector<std::string> defaultRelays() const;
+
+ std::vector<std::string> activeRelays() const;
+
+ std::unordered_map<std::string, std::vector<std::string>> subscriptions() const;
+
+ std::vector<std::string> openRelayConnections() override;
+
+ std::vector<std::string> openRelayConnections(std::vector<std::string> relays) override;
+
+ void closeRelayConnections() override;
+
+ void closeRelayConnections(std::vector<std::string> relays) override;
+
+ // TODO: Make this method return a promise.
+ std::tuple<std::vector<std::string>, std::vector<std::string>> publishEvent(
+ std::shared_ptr<data::Event> event) override;
+
+ // TODO: Make this method return a promise.
+ // TODO: Add a timeout to this method to prevent hanging while waiting for the relay.
+ std::vector<std::shared_ptr<data::Event>> queryRelays(
+ std::shared_ptr<data::Filters> filters) override;
+
+ std::string queryRelays(
+ std::shared_ptr<data::Filters> filters,
+ std::function<void(const std::string&, std::shared_ptr<data::Event>)> eventHandler,
+ std::function<void(const std::string&)> eoseHandler,
+ std::function<void(const std::string&, const std::string&)> closeHandler) override;
+
+ std::tuple<std::vector<std::string>, std::vector<std::string>> closeSubscription(
+ std::string subscriptionId) override;
+
+ bool closeSubscription(std::string subscriptionId, std::string relay) override;
+
+ std::vector<std::string> closeSubscriptions() override;
+
+private:
+ ///< The maximum number of events the service will store for each subscription.
+ const int MAX_EVENTS_PER_SUBSCRIPTION = 128;
+
+ ///< The WebSocket client used to communicate with relays.
+ std::shared_ptr<client::IWebSocketClient> _client;
+
+ ///< A mutex to protect the instance properties.
+ std::mutex _propertyMutex;
+
+ ///< The default set of Nostr relays to which the service will attempt to connect.
+ std::vector<std::string> _defaultRelays;
+
+ ///< The set of Nostr relays to which the service is currently connected.
+ std::vector<std::string> _activeRelays;
+
+ ///< A map from subscription IDs to the relays on which each subscription is open.
+ std::unordered_map<std::string, std::vector<std::string>> _subscriptions;
+
+ std::vector<std::string> _getConnectedRelays(std::vector<std::string> relays);
+
+ std::vector<std::string> _getUnconnectedRelays(std::vector<std::string> relays);
+
+ bool _isConnected(std::string relay);
+
+ void _eraseActiveRelay(std::string relay);
+
+ void _connect(std::string relay);
+
+ void _disconnect(std::string relay);
+
+ std::string _generateSubscriptionId();
+
+ std::string _generateCloseRequest(std::string subscriptionId);
+
+ bool _hasSubscription(std::string subscriptionId);
+
+ bool _hasSubscription(std::string subscriptionId, std::string relay);
+
+ void _onSubscriptionMessage(
+ std::string message,
+ std::function<void(const std::string&, std::shared_ptr<data::Event>)> eventHandler,
+ std::function<void(const std::string&)> eoseHandler,
+ std::function<void(const std::string&, const std::string&)> closeHandler);
+
+ void _onAcceptance(std::string message, std::function<void(const bool)> acceptanceHandler);
+};
+} // namespace nostr
diff --git a/include/signer/noscrypt_signer.hpp b/include/signer/noscrypt_signer.hpp
new file mode 100644
index 0000000..1476303
--- /dev/null
+++ b/include/signer/noscrypt_signer.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+extern "C"
+{
+#include <noscrypt.h>
+}
+
+#include "signer.hpp"
+
+namespace nostr
+{
+namespace signer
+{
+class NoscryptSigner : public INostrConnectSigner
+{
+public:
+ NoscryptSigner(std::shared_ptr<plog::IAppender> appender);
+
+ ~NoscryptSigner();
+
+ void receiveConnection(std::string connectionToken) override;
+
+ void initiateConnection(
+ std::string relay,
+ std::string name,
+ std::string url,
+ std::string description) override;
+
+ void sign(std::shared_ptr<data::Event> event) override;
+
+private:
+ std::shared_ptr<NCContext> noscryptContext;
+
+ std::string localPrivateKey;
+ std::string localPublicKey;
+
+ /**
+ * @brief Initializes the noscrypt library context into the class's `context` property.
+ * @returns `true` if successful, `false` otherwise.
+ */
+ std::shared_ptr<NCContext> _initNoscryptContext();
+
+ void _logNoscryptResult(NCResult result);
+
+ /**
+ * @brief Generates a private/public key pair for local use.
+ * @returns The generated keypair of the form `[privateKey, publicKey]`, or a pair of empty
+ * strings if the function failed.
+ * @remarks This keypair is intended for temporary use, and should not be saved or used outside
+ * of this class.
+ */
+ std::tuple<std::string, std::string> _createLocalKeypair();
+};
+} // namespace signer
+} // namespace nostr
diff --git a/include/signer/signer.hpp b/include/signer/signer.hpp
index cc4fd03..e16aa38 100644
--- a/include/signer/signer.hpp
+++ b/include/signer/signer.hpp
@@ -14,15 +14,14 @@ namespace nostr
{
namespace signer
{
-class ISigner;
-class INostrConnectSigner;
-
/**
* @brief An interface for Nostr event signing that implements NIP-46.
*/
class ISigner
{
public:
+ virtual ~ISigner() = default;
+
/**
* @brief Signs the given Nostr event.
* @param event The event to sign.
@@ -34,6 +33,8 @@ public:
class INostrConnectSigner : public ISigner
{
public:
+ virtual ~INostrConnectSigner() = default;
+
virtual void receiveConnection(std::string connectionToken) = 0;
virtual void initiateConnection(
diff --git a/src/client/websocketpp_client.cpp b/src/client/websocketpp_client.cpp
index 9967d74..3cc6c99 100644
--- a/src/client/websocketpp_client.cpp
+++ b/src/client/websocketpp_client.cpp
@@ -1,132 +1,105 @@
-#include "web_socket_client.hpp"
-
-using std::error_code;
-using std::function;
-using std::lock_guard;
-using std::make_tuple;
-using std::mutex;
-using std::string;
-using std::tuple;
-using std::unordered_map;
-
-namespace nostr
-{
-namespace client
-{
-/**
- * @brief An implementation of the `IWebSocketClient` interface that uses the WebSocket++ library.
- */
-class WebsocketppClient : public IWebSocketClient
-{
-public:
- void start() override
- {
- this->_client.init_asio();
- this->_client.start_perpetual();
- };
-
- void stop() override
- {
- this->_client.stop_perpetual();
- this->_client.stop();
- };
+#include "websocketpp_client.hpp"
- void openConnection(string uri) override
- {
- error_code error;
- websocketpp_client::connection_ptr connection = this->_client.get_connection(uri, error);
-
- if (error.value() == -1)
- {
- // PLOG_ERROR << "Error connecting to relay " << relay << ": " << error.message();
- }
+using namespace std;
- // Configure the connection here via the connection pointer.
- connection->set_fail_handler([this, uri](auto handle) {
- // PLOG_ERROR << "Error connecting to relay " << relay << ": Handshake failed.";
- lock_guard<mutex> lock(this->_propertyMutex);
- if (this->isConnected(uri))
- {
- this->_connectionHandles.erase(uri);
- }
- });
+void nostr::client::WebsocketppClient::start()
+{
+ this->_client.init_asio();
+ this->_client.start_perpetual();
+};
- lock_guard<mutex> lock(this->_propertyMutex);
- this->_connectionHandles[uri] = connection->get_handle();
- this->_client.connect(connection);
- };
+void nostr::client::WebsocketppClient::stop()
+{
+ this->_client.stop_perpetual();
+ this->_client.stop();
+};
- bool isConnected(string uri) override
- {
- lock_guard<mutex> lock(this->_propertyMutex);
- return this->_connectionHandles.find(uri) != this->_connectionHandles.end();
- };
+void nostr::client::WebsocketppClient::openConnection(string uri)
+{
+ error_code error;
+ websocketpp_client::connection_ptr connection = this->_client.get_connection(uri, error);
- tuple<string, bool> send(string message, string uri) override
+ if (error.value() == -1)
{
- error_code error;
+ // PLOG_ERROR << "Error connecting to relay " << relay << ": " << error.message();
+ }
- // Make sure the connection isn't closed from under us.
+ // Configure the connection here via the connection pointer.
+ connection->set_fail_handler([this, uri](auto handle) {
+ // PLOG_ERROR << "Error connecting to relay " << relay << ": Handshake failed.";
lock_guard<mutex> lock(this->_propertyMutex);
- this->_client.send(
- this->_connectionHandles[uri],
- message,
- websocketpp::frame::opcode::text,
- error);
-
- if (error.value() == -1)
+ if (this->isConnected(uri))
{
- return make_tuple(uri, false);
+ this->_connectionHandles.erase(uri);
}
+ });
- return make_tuple(uri, true);
- };
+ lock_guard<mutex> lock(this->_propertyMutex);
+ this->_connectionHandles[uri] = connection->get_handle();
+ this->_client.connect(connection);
+};
- tuple<string, bool> send(string message, string uri, function<void(const string&)> messageHandler) override
- {
- auto successes = this->send(message, uri);
- this->receive(uri, messageHandler);
- return successes;
- };
+bool nostr::client::WebsocketppClient::isConnected(string uri)
+{
+ lock_guard<mutex> lock(this->_propertyMutex);
+ return this->_connectionHandles.find(uri) != this->_connectionHandles.end();
+};
- void receive(string uri, function<void(const string&)> messageHandler) override
- {
- lock_guard<mutex> lock(this->_propertyMutex);
- auto connectionHandle = this->_connectionHandles[uri];
- auto connection = this->_client.get_con_from_hdl(connectionHandle);
+tuple<string, bool> nostr::client::WebsocketppClient::send(string message, string uri)
+{
+ error_code error;
- connection->set_message_handler([messageHandler](
- websocketpp::connection_hdl connectionHandle,
- websocketpp_client::message_ptr message)
- {
- messageHandler(message->get_payload());
- });
- };
+ // Make sure the connection isn't closed from under us.
+ lock_guard<mutex> lock(this->_propertyMutex);
+ this->_client.send(
+ this->_connectionHandles[uri],
+ message,
+ websocketpp::frame::opcode::text,
+ error);
- void closeConnection(string uri) override
+ if (error.value() == -1)
{
- lock_guard<mutex> lock(this->_propertyMutex);
+ return make_tuple(uri, false);
+ }
- websocketpp::connection_hdl handle = this->_connectionHandles[uri];
- this->_client.close(
- handle,
- websocketpp::close::status::going_away,
- "_client requested close.");
-
- this->_connectionHandles.erase(uri);
- };
+ return make_tuple(uri, true);
+};
-private:
- typedef websocketpp::client<websocketpp::config::asio_client> websocketpp_client;
- typedef unordered_map<string, websocketpp::connection_hdl>::iterator connection_hdl_iterator;
+tuple<string, bool> nostr::client::WebsocketppClient::send(
+ string message,
+ string uri,
+ function<void(const string&)> messageHandler)
+{
+ auto successes = this->send(message, uri);
+ this->receive(uri, messageHandler);
+ return successes;
+};
- websocketpp_client _client;
- unordered_map<string, websocketpp::connection_hdl> _connectionHandles;
- mutex _propertyMutex;
+void nostr::client::WebsocketppClient::receive(
+ string uri,
+ function<void(const string&)> messageHandler)
+{
+ lock_guard<mutex> lock(this->_propertyMutex);
+ auto connectionHandle = this->_connectionHandles[uri];
+ auto connection = this->_client.get_con_from_hdl(connectionHandle);
- void onMessage(websocketpp::connection_hdl handle, websocketpp_client::message_ptr message)
+ connection->set_message_handler([messageHandler](
+ websocketpp::connection_hdl connectionHandle,
+ websocketpp_client::message_ptr message)
{
- };
+ messageHandler(message->get_payload());
+ });
+};
+
+void nostr::client::WebsocketppClient::closeConnection(string uri)
+{
+ lock_guard<mutex> lock(this->_propertyMutex);
+
+ websocketpp::connection_hdl handle = this->_connectionHandles[uri];
+ this->_client.close(
+ handle,
+ websocketpp::close::status::going_away,
+ "_client requested close.");
+
+ this->_connectionHandles.erase(uri);
};
-} // namespace client
-} // namespace nostr
diff --git a/src/data/event.cpp b/src/data/event.cpp
index 620ee3f..5f611ff 100644
--- a/src/data/event.cpp
+++ b/src/data/event.cpp
@@ -88,12 +88,6 @@ void Event::validate()
{
throw std::invalid_argument("Event::validate: A valid event kind is required.");
}
-
- bool hasSignature = this->sig.length() > 0;
- if (!hasSignature)
- {
- throw std::invalid_argument("Event::validate: The event must be signed.");
- }
};
string Event::generateId(string serializedData) const
diff --git a/src/nostr_service.cpp b/src/nostr_service_base.cpp
index 9f6b8ce..bce6728 100644
--- a/src/nostr_service.cpp
+++ b/src/nostr_service_base.cpp
@@ -1,53 +1,52 @@
-#include "nostr.hpp"
+#include "nostr_service_base.hpp"
using namespace nlohmann;
using namespace std;
-namespace nostr
-{
-NostrService::NostrService(
+nostr::NostrServiceBase::NostrServiceBase(
shared_ptr<plog::IAppender> appender,
- shared_ptr<client::IWebSocketClient> client,
- shared_ptr<signer::ISigner> signer)
-: NostrService(appender, client, signer, {}) { };
+ shared_ptr<client::IWebSocketClient> client)
+: NostrServiceBase(appender, client, {}) { };
-NostrService::NostrService(
+nostr::NostrServiceBase::NostrServiceBase(
shared_ptr<plog::IAppender> appender,
shared_ptr<client::IWebSocketClient> client,
- shared_ptr<signer::ISigner> signer,
vector<string> relays)
-: _defaultRelays(relays), _client(client), _signer(signer)
+: _defaultRelays(relays), _client(client)
{
plog::init(plog::debug, appender.get());
client->start();
};
-NostrService::~NostrService()
+nostr::NostrServiceBase::~NostrServiceBase()
{
this->_client->stop();
};
-vector<string> NostrService::defaultRelays() const { return this->_defaultRelays; };
+vector<string> nostr::NostrServiceBase::defaultRelays() const
+{ return this->_defaultRelays; };
-vector<string> NostrService::activeRelays() const { return this->_activeRelays; };
+vector<string> nostr::NostrServiceBase::activeRelays() const
+{ return this->_activeRelays; };
-unordered_map<string, vector<string>> NostrService::subscriptions() const { return this->_subscriptions; };
+unordered_map<string, vector<string>> nostr::NostrServiceBase::subscriptions() const
+{ return this->_subscriptions; };
-vector<string> NostrService::openRelayConnections()
+vector<string> nostr::NostrServiceBase::openRelayConnections()
{
return this->openRelayConnections(this->_defaultRelays);
};
-vector<string> NostrService::openRelayConnections(vector<string> relays)
+vector<string> nostr::NostrServiceBase::openRelayConnections(vector<string> relays)
{
PLOG_INFO << "Attempting to connect to Nostr relays.";
- vector<string> unconnectedRelays = this->getUnconnectedRelays(relays);
+ vector<string> unconnectedRelays = this->_getUnconnectedRelays(relays);
vector<thread> connectionThreads;
for (string relay : unconnectedRelays)
{
thread connectionThread([this, relay]() {
- this->connect(relay);
+ this->_connect(relay);
});
connectionThreads.push_back(move(connectionThread));
}
@@ -65,7 +64,7 @@ vector<string> NostrService::openRelayConnections(vector<string> relays)
return this->_activeRelays;
};
-void NostrService::closeRelayConnections()
+void nostr::NostrServiceBase::closeRelayConnections()
{
if (this->_activeRelays.size() == 0)
{
@@ -76,16 +75,16 @@ void NostrService::closeRelayConnections()
this->closeRelayConnections(this->_activeRelays);
};
-void NostrService::closeRelayConnections(vector<string> relays)
+void nostr::NostrServiceBase::closeRelayConnections(vector<string> relays)
{
PLOG_INFO << "Disconnecting from Nostr relays.";
- vector<string> connectedRelays = getConnectedRelays(relays);
+ vector<string> connectedRelays = this->_getConnectedRelays(relays);
vector<thread> disconnectionThreads;
for (string relay : connectedRelays)
{
thread disconnectionThread([this, relay]() {
- this->disconnect(relay);
+ this->_disconnect(relay);
});
disconnectionThreads.push_back(move(disconnectionThread));
@@ -101,7 +100,8 @@ void NostrService::closeRelayConnections(vector<string> relays)
};
// TODO: Make this method return a promise.
-tuple<vector<string>, vector<string>> NostrService::publishEvent(shared_ptr<data::Event> event)
+tuple<vector<string>, vector<string>> nostr::NostrServiceBase::publishEvent(
+ shared_ptr<nostr::data::Event> event)
{
vector<string> successfulRelays;
vector<string> failedRelays;
@@ -111,7 +111,6 @@ tuple<vector<string>, vector<string>> NostrService::publishEvent(shared_ptr<data
json message;
try
{
- this->_signer->sign(event);
message = json::array({ "EVENT", event->serialize() });
}
catch (const std::invalid_argument& e)
@@ -138,7 +137,7 @@ tuple<vector<string>, vector<string>> NostrService::publishEvent(shared_ptr<data
relay,
[this, &relay, &event, &publishPromise](string response)
{
- this->onAcceptance(response, [this, &relay, &event, &publishPromise](bool isAccepted)
+ this->_onAcceptance(response, [this, &relay, &event, &publishPromise](bool isAccepted)
{
if (isAccepted)
{
@@ -182,7 +181,8 @@ tuple<vector<string>, vector<string>> NostrService::publishEvent(shared_ptr<data
// TODO: Make this method return a promise.
// TODO: Add a timeout to this method to prevent hanging while waiting for the relay.
-vector<shared_ptr<data::Event>> NostrService::queryRelays(shared_ptr<data::Filters> filters)
+vector<shared_ptr<nostr::data::Event>> nostr::NostrServiceBase::queryRelays(
+ shared_ptr<nostr::data::Filters> filters)
{
if (filters->limit > 64 || filters->limit < 1)
{
@@ -190,9 +190,9 @@ vector<shared_ptr<data::Event>> NostrService::queryRelays(shared_ptr<data::Filte
filters->limit = 16;
}
- vector<shared_ptr<data::Event>> events;
+ vector<shared_ptr<nostr::data::Event>> events;
- string subscriptionId = this->generateSubscriptionId();
+ string subscriptionId = this->_generateSubscriptionId();
string request;
try
@@ -226,9 +226,9 @@ vector<shared_ptr<data::Event>> NostrService::queryRelays(shared_ptr<data::Filte
relay,
[this, &relay, &events, &eosePromise](string payload)
{
- this->onSubscriptionMessage(
+ this->_onSubscriptionMessage(
payload,
- [&events](const string&, shared_ptr<data::Event> event)
+ [&events](const string&, shared_ptr<nostr::data::Event> event)
{
events.push_back(event);
},
@@ -276,16 +276,16 @@ vector<shared_ptr<data::Event>> NostrService::queryRelays(shared_ptr<data::Filte
return events;
};
-string NostrService::queryRelays(
- shared_ptr<data::Filters> filters,
- function<void(const string&, shared_ptr<data::Event>)> eventHandler,
+string nostr::NostrServiceBase::queryRelays(
+ shared_ptr<nostr::data::Filters> filters,
+ function<void(const string&, shared_ptr<nostr::data::Event>)> eventHandler,
function<void(const string&)> eoseHandler,
function<void(const string&, const string&)> closeHandler)
{
vector<string> successfulRelays;
vector<string> failedRelays;
- string subscriptionId = this->generateSubscriptionId();
+ string subscriptionId = this->_generateSubscriptionId();
string request = filters->serialize(subscriptionId);
vector<future<tuple<string, bool>>> requestFutures;
for (const string relay : this->_activeRelays)
@@ -302,7 +302,7 @@ string NostrService::queryRelays(
relay,
[this, &eventHandler, &eoseHandler, &closeHandler](string payload)
{
- this->onSubscriptionMessage(payload, eventHandler, eoseHandler, closeHandler);
+ this->_onSubscriptionMessage(payload, eventHandler, eoseHandler, closeHandler);
});
});
requestFutures.push_back(move(requestFuture));
@@ -328,7 +328,7 @@ string NostrService::queryRelays(
return subscriptionId;
};
-tuple<vector<string>, vector<string>> NostrService::closeSubscription(string subscriptionId)
+tuple<vector<string>, vector<string>> nostr::NostrServiceBase::closeSubscription(string subscriptionId)
{
vector<string> successfulRelays;
vector<string> failedRelays;
@@ -388,21 +388,21 @@ tuple<vector<string>, vector<string>> NostrService::closeSubscription(string sub
return make_tuple(successfulRelays, failedRelays);
};
-bool NostrService::closeSubscription(string subscriptionId, string relay)
+bool nostr::NostrServiceBase::closeSubscription(string subscriptionId, string relay)
{
- if (!this->hasSubscription(subscriptionId, relay))
+ if (!this->_hasSubscription(subscriptionId, relay))
{
PLOG_WARNING << "Subscription " << subscriptionId << " not found on relay " << relay;
return false;
}
- if (!this->isConnected(relay))
+ if (!this->_isConnected(relay))
{
PLOG_WARNING << "Relay " << relay << " is not connected.";
return false;
}
- string request = this->generateCloseRequest(subscriptionId);
+ string request = this->_generateCloseRequest(subscriptionId);
auto [uri, success] = this->_client->send(request, relay);
if (success)
@@ -428,7 +428,7 @@ bool NostrService::closeSubscription(string subscriptionId, string relay)
return success;
};
-vector<string> NostrService::closeSubscriptions()
+vector<string> nostr::NostrServiceBase::closeSubscriptions()
{
unique_lock<mutex> lock(this->_propertyMutex);
vector<string> subscriptionIds;
@@ -451,7 +451,7 @@ vector<string> NostrService::closeSubscriptions()
return remainingSubscriptions;
};
-vector<string> NostrService::getConnectedRelays(vector<string> relays)
+vector<string> nostr::NostrServiceBase::_getConnectedRelays(vector<string> relays)
{
PLOG_VERBOSE << "Identifying connected relays.";
vector<string> connectedRelays;
@@ -468,7 +468,7 @@ vector<string> NostrService::getConnectedRelays(vector<string> relays)
}
else if (isActive && !isConnected)
{
- this->eraseActiveRelay(relay);
+ this->_eraseActiveRelay(relay);
}
else if (!isActive && isConnected)
{
@@ -479,7 +479,7 @@ vector<string> NostrService::getConnectedRelays(vector<string> relays)
return connectedRelays;
};
-vector<string> NostrService::getUnconnectedRelays(vector<string> relays)
+vector<string> nostr::NostrServiceBase::_getUnconnectedRelays(vector<string> relays)
{
PLOG_VERBOSE << "Identifying unconnected relays.";
vector<string> unconnectedRelays;
@@ -498,7 +498,7 @@ vector<string> NostrService::getUnconnectedRelays(vector<string> relays)
else if (isActive && !isConnected)
{
PLOG_VERBOSE << "Relay " << relay << " is active but not connected. Removing from active relays list.";
- this->eraseActiveRelay(relay);
+ this->_eraseActiveRelay(relay);
unconnectedRelays.push_back(relay);
}
else if (!isActive && isConnected)
@@ -510,7 +510,7 @@ vector<string> NostrService::getUnconnectedRelays(vector<string> relays)
return unconnectedRelays;
};
-bool NostrService::isConnected(string relay)
+bool nostr::NostrServiceBase::_isConnected(string relay)
{
auto it = find(this->_activeRelays.begin(), this->_activeRelays.end(), relay);
if (it != this->_activeRelays.end()) // If the relay is in this->_activeRelays
@@ -520,7 +520,7 @@ bool NostrService::isConnected(string relay)
return false;
};
-void NostrService::eraseActiveRelay(string relay)
+void nostr::NostrServiceBase::_eraseActiveRelay(string relay)
{
auto it = find(this->_activeRelays.begin(), this->_activeRelays.end(), relay);
if (it != this->_activeRelays.end()) // If the relay is in this->_activeRelays
@@ -529,7 +529,7 @@ void NostrService::eraseActiveRelay(string relay)
}
};
-void NostrService::connect(string relay)
+void nostr::NostrServiceBase::_connect(string relay)
{
PLOG_VERBOSE << "Connecting to relay " << relay;
this->_client->openConnection(relay);
@@ -548,28 +548,28 @@ void NostrService::connect(string relay)
}
};
-void NostrService::disconnect(string relay)
+void nostr::NostrServiceBase::_disconnect(string relay)
{
this->_client->closeConnection(relay);
lock_guard<mutex> lock(this->_propertyMutex);
- this->eraseActiveRelay(relay);
+ this->_eraseActiveRelay(relay);
};
-string NostrService::generateSubscriptionId()
+string nostr::NostrServiceBase::_generateSubscriptionId()
{
UUIDv4::UUIDGenerator<std::mt19937_64> uuidGenerator;
UUIDv4::UUID uuid = uuidGenerator.getUUID();
return uuid.str();
};
-string NostrService::generateCloseRequest(string subscriptionId)
+string nostr::NostrServiceBase::_generateCloseRequest(string subscriptionId)
{
json jarr = json::array({ "CLOSE", subscriptionId });
return jarr.dump();
};
-bool NostrService::hasSubscription(string subscriptionId)
+bool nostr::NostrServiceBase::_hasSubscription(string subscriptionId)
{
lock_guard<mutex> lock(this->_propertyMutex);
auto it = this->_subscriptions.find(subscriptionId);
@@ -577,7 +577,7 @@ bool NostrService::hasSubscription(string subscriptionId)
return it != this->_subscriptions.end();
};
-bool NostrService::hasSubscription(string subscriptionId, string relay)
+bool nostr::NostrServiceBase::_hasSubscription(string subscriptionId, string relay)
{
lock_guard<mutex> lock(this->_propertyMutex);
auto subscriptionIt = this->_subscriptions.find(subscriptionId);
@@ -593,9 +593,9 @@ bool NostrService::hasSubscription(string subscriptionId, string relay)
return relayIt != relays.end();
};
-void NostrService::onSubscriptionMessage(
+void nostr::NostrServiceBase::_onSubscriptionMessage(
string message,
- function<void(const string&, shared_ptr<data::Event>)> eventHandler,
+ function<void(const string&, shared_ptr<nostr::data::Event>)> eventHandler,
function<void(const string&)> eoseHandler,
function<void(const string&, const string&)> closeHandler)
{
@@ -606,8 +606,8 @@ void NostrService::onSubscriptionMessage(
if (messageType == "EVENT")
{
string subscriptionId = jMessage.at(1);
- data::Event event = data::Event::fromString(jMessage.at(2));
- eventHandler(subscriptionId, make_shared<data::Event>(event));
+ nostr::data::Event event = nostr::data::Event::fromString(jMessage.at(2));
+ eventHandler(subscriptionId, make_shared<nostr::data::Event>(event));
}
else if (messageType == "EOSE")
{
@@ -638,7 +638,7 @@ void NostrService::onSubscriptionMessage(
}
};
-void NostrService::onAcceptance(string message, function<void(const bool)> acceptanceHandler)
+void nostr::NostrServiceBase::_onAcceptance(string message, function<void(const bool)> acceptanceHandler)
{
try
{
@@ -656,4 +656,3 @@ void NostrService::onAcceptance(string message, function<void(const bool)> accep
throw je;
}
};
-} // namespace nostr
diff --git a/src/signer/noscrypt_signer.cpp b/src/signer/noscrypt_signer.cpp
index c56070c..39bb667 100644
--- a/src/signer/noscrypt_signer.cpp
+++ b/src/signer/noscrypt_signer.cpp
@@ -1,169 +1,151 @@
-#include <noscrypt.h>
-
-#include "signer.hpp"
+#include "noscrypt_signer.hpp"
using namespace std;
-namespace nostr
+nostr::signer::NoscryptSigner::NoscryptSigner(shared_ptr<plog::IAppender> appender)
{
-namespace signer
+ plog::init(plog::debug, appender.get());
+
+ this->noscryptContext = this->_initNoscryptContext();
+ if (this->noscryptContext == nullptr)
+ {
+ return;
+ }
+
+ const auto [privateKey, publicKey] = this->_createLocalKeypair();
+ this->localPrivateKey = privateKey;
+ this->localPublicKey = publicKey;
+};
+
+nostr::signer::NoscryptSigner::~NoscryptSigner()
{
-class NoscryptSigner : public INostrConnectSigner
+ NCDestroyContext(this->noscryptContext.get());
+};
+
+void nostr::signer::NoscryptSigner::receiveConnection(string connectionToken)
{
-public:
- NoscryptSigner(shared_ptr<plog::IAppender> appender)
- {
- plog::init(plog::debug, appender.get());
+ // Receive the connection token here.
+};
- this->noscryptContext = this->initNoscryptContext();
- if (this->noscryptContext == nullptr)
- {
- return;
- }
+void nostr::signer::NoscryptSigner::initiateConnection(
+ string relay,
+ string name,
+ string url,
+ string description)
+{
+ // Initiate the connection here.
+};
- const auto [privateKey, publicKey] = this->createLocalKeypair();
- this->localPrivateKey = privateKey;
- this->localPublicKey = publicKey;
- };
+void nostr::signer::NoscryptSigner::sign(shared_ptr<data::Event> event)
+{
+ // Sign the event here.
+};
- ~NoscryptSigner()
- {
- NCDestroyContext(this->noscryptContext.get());
- };
+/**
+ * @brief Initializes the noscrypt library context into the class's `context` property.
+ * @returns `true` if successful, `false` otherwise.
+ */
+shared_ptr<NCContext> nostr::signer::NoscryptSigner::_initNoscryptContext()
+{
+ shared_ptr<NCContext> context(new NCContext);
+ auto contextStructSize = NCGetContextStructSize();
+ unique_ptr<uint8_t> randomEntropy(new uint8_t[contextStructSize]);
- void receiveConnection(string connectionToken) override
- {
- // Receive the connection token here.
- };
-
- void initiateConnection(
- string relay,
- string name,
- string url,
- string description) override
- {
- // Initiate the connection here.
- };
+ random_device rd;
+ mt19937 gen(rd());
+ uniform_int_distribution<> dist(0, contextStructSize);
+ generate_n(randomEntropy.get(), contextStructSize, [&]() { return dist(gen); });
- void sign(shared_ptr<data::Event> event) override
+ NCResult result = NCInitContext(context.get(), randomEntropy.get());
+ this->_logNoscryptResult(result);
+
+ if (result != NC_SUCCESS)
{
- // Sign the event here.
- };
+ return nullptr;
+ }
-private:
- shared_ptr<NCContext> noscryptContext;
+ return context;
+};
- string localPrivateKey;
- string localPublicKey;
+void nostr::signer::NoscryptSigner::_logNoscryptResult(NCResult result)
+{
+ switch (result) {
+ case NC_SUCCESS:
+ PLOG_INFO << "noscrypt - success";
+ break;
- /**
- * @brief Initializes the noscrypt library context into the class's `context` property.
- * @returns `true` if successful, `false` otherwise.
- */
- shared_ptr<NCContext> initNoscryptContext()
- {
- shared_ptr<NCContext> context(new NCContext);
- auto contextStructSize = NCGetContextStructSize();
- unique_ptr<uint8_t> randomEntropy(new uint8_t[contextStructSize]);
+ case E_NULL_PTR:
+ PLOG_ERROR << "noscrypt - error: A null pointer was passed to the initializer.";
+ break;
- random_device rd;
- mt19937 gen(rd());
- uniform_int_distribution<> dist(0, contextStructSize);
- generate_n(randomEntropy.get(), contextStructSize, [&]() { return dist(gen); });
+ case E_INVALID_ARG:
+ PLOG_ERROR << "noscrypt - error: An invalid argument was passed to the initializer.";
+ break;
+
+ case E_INVALID_CONTEXT:
+ PLOG_ERROR << "noscrypt - error: The NCContext struct is in an invalid state.";
+ break;
+
+ case E_ARGUMENT_OUT_OF_RANGE:
+ PLOG_ERROR << "noscrypt - error: An initializer argument was outside the range of acceptable values.";
+ break;
+
+ case E_OPERATION_FAILED:
+ PLOG_ERROR << "noscrypt - error";
+ break;
+ }
+};
- NCResult result = NCInitContext(context.get(), randomEntropy.get());
- this->logNoscryptResult(result);
+/**
+ * @brief Generates a private/public key pair for local use.
+ * @returns The generated keypair of the form `[privateKey, publicKey]`, or a pair of empty
+ * strings if the function failed.
+ * @remarks This keypair is intended for temporary use, and should not be saved or used outside
+ * of this class.
+ */
+tuple<string, string> nostr::signer::NoscryptSigner::_createLocalKeypair()
+{
+ string privateKey;
+ string publicKey;
- if (result != NC_SUCCESS)
- {
- return nullptr;
- }
+ // To generate a private key, all we need is a random 32-bit buffer.
+ unique_ptr<NCSecretKey> secretKey(new NCSecretKey);
- return context;
- };
+ random_device rd;
+ mt19937 gen(rd());
+ uniform_int_distribution<> dist(0, NC_SEC_KEY_SIZE);
+ generate_n(secretKey.get()->key, NC_SEC_KEY_SIZE, [&]() { return dist(gen); });
- void logNoscryptResult(NCResult result)
+ // Convert the buffer into a hex string for a more human-friendly representation.
+ stringstream secretKeyStream;
+ for (int i = 0; i < NC_SEC_KEY_SIZE; i++)
+ {
+ secretKeyStream << hex << setw(2) << setfill('0') << static_cast<int>(secretKey->key[i]);
+ }
+ privateKey = secretKeyStream.str();
+
+ // Use noscrypt to derive the public key from its private counterpart.
+ unique_ptr<NCPublicKey> pubkey(new NCPublicKey);
+ NCResult result = NCGetPublicKey(
+ this->noscryptContext.get(),
+ secretKey.get(),
+ pubkey.get());
+ this->_logNoscryptResult(result);
+
+ if (result != NC_SUCCESS)
{
- switch (result) {
- case NC_SUCCESS:
- PLOG_INFO << "noscrypt - success";
- break;
-
- case E_NULL_PTR:
- PLOG_ERROR << "noscrypt - error: A null pointer was passed to the initializer.";
- break;
-
- case E_INVALID_ARG:
- PLOG_ERROR << "noscrypt - error: An invalid argument was passed to the initializer.";
- break;
-
- case E_INVALID_CONTEXT:
- PLOG_ERROR << "noscrypt - error: The NCContext struct is in an invalid state.";
- break;
-
- case E_ARGUMENT_OUT_OF_RANGE:
- PLOG_ERROR << "noscrypt - error: An initializer argument was outside the range of acceptable values.";
- break;
-
- case E_OPERATION_FAILED:
- PLOG_ERROR << "noscrypt - error";
- break;
- }
- };
-
- /**
- * @brief Generates a private/public key pair for local use.
- * @returns The generated keypair of the form `[privateKey, publicKey]`, or a pair of empty
- * strings if the function failed.
- * @remarks This keypair is intended for temporary use, and should not be saved or used outside
- * of this class.
- */
- tuple<string, string> createLocalKeypair()
+ // Return empty strings if the key generation fails.
+ return make_tuple(string(), string());
+ }
+
+ // Convert the now-populated pubkey buffer into a hex string for the pubkey representation
+ // used by Nostr events.
+ stringstream pubkeyStream;
+ for (int i = 0; i < NC_SEC_KEY_SIZE; i++)
{
- string privateKey;
- string publicKey;
-
- // To generate a private key, all we need is a random 32-bit buffer.
- unique_ptr<NCSecretKey> secretKey(new NCSecretKey);
-
- random_device rd;
- mt19937 gen(rd());
- uniform_int_distribution<> dist(0, NC_SEC_KEY_SIZE);
- generate_n(secretKey.get()->key, NC_SEC_KEY_SIZE, [&]() { return dist(gen); });
-
- // Convert the buffer into a hex string for a more human-friendly representation.
- stringstream secretKeyStream;
- for (int i = 0; i < NC_SEC_KEY_SIZE; i++)
- {
- secretKeyStream << hex << setw(2) << setfill('0') << static_cast<int>(secretKey->key[i]);
- }
- privateKey = secretKeyStream.str();
-
- // Use noscrypt to derive the public key from its private counterpart.
- unique_ptr<NCPublicKey> pubkey(new NCPublicKey);
- NCResult result = NCGetPublicKey(
- this->noscryptContext.get(),
- secretKey.get(),
- pubkey.get());
- this->logNoscryptResult(result);
-
- if (result != NC_SUCCESS)
- {
- // Return empty strings if the key generation fails.
- return make_tuple(string(), string());
- }
-
- // Convert the now-populated pubkey buffer into a hex string for the pubkey representation
- // used by Nostr events.
- stringstream pubkeyStream;
- for (int i = 0; i < NC_SEC_KEY_SIZE; i++)
- {
- pubkeyStream << hex << setw(2) << setfill('0') << static_cast<int>(pubkey->key[i]);
- }
- publicKey = pubkeyStream.str();
-
- return make_tuple(privateKey, publicKey);
- };
+ pubkeyStream << hex << setw(2) << setfill('0') << static_cast<int>(pubkey->key[i]);
+ }
+ publicKey = pubkeyStream.str();
+
+ return make_tuple(privateKey, publicKey);
};
-} // namespace signer
-} // namespace nostr
diff --git a/test/nostr_service_test.cpp b/test/nostr_service_base_test.cpp
index e5375db..9116816 100644
--- a/test/nostr_service_test.cpp
+++ b/test/nostr_service_base_test.cpp
@@ -9,8 +9,8 @@
#include <websocketpp/client.hpp>
#include "nostr.hpp"
+#include "nostr_service_base.hpp"
#include "client/web_socket_client.hpp"
-#include "signer/signer.hpp"
using namespace nostr;
using namespace std;
@@ -32,16 +32,7 @@ public:
MOCK_METHOD(void, closeConnection, (string uri), (override));
};
-class FakeSigner : public signer::ISigner
-{
-public:
- void sign(shared_ptr<nostr::data::Event> event) override
- {
- event->sig = "fake_signature";
- };
-};
-
-class NostrServiceTest : public testing::Test
+class NostrServiceBaseTest : public testing::Test
{
public:
inline static const vector<string> defaultTestRelays =
@@ -127,10 +118,7 @@ public:
}
static const string getTestEventMessage(shared_ptr<nostr::data::Event> event, string subscriptionId)
- {
- auto signer = make_unique<FakeSigner>();
- signer->sign(event);
-
+ {
json jarr = json::array();
jarr.push_back("EVENT");
jarr.push_back(subscriptionId);
@@ -170,26 +158,24 @@ public:
protected:
shared_ptr<plog::ConsoleAppender<plog::TxtFormatter>> testAppender;
shared_ptr<MockWebSocketClient> mockClient;
- shared_ptr<FakeSigner> fakeSigner;
void SetUp() override
{
testAppender = make_shared<plog::ConsoleAppender<plog::TxtFormatter>>();
mockClient = make_shared<MockWebSocketClient>();
- fakeSigner = make_shared<FakeSigner>();
};
};
-TEST_F(NostrServiceTest, Constructor_StartsClient)
+TEST_F(NostrServiceBaseTest, Constructor_StartsClient)
{
EXPECT_CALL(*mockClient, start()).Times(1);
- auto nostrService = make_unique<nostr::NostrService>(testAppender, mockClient, fakeSigner);
+ auto nostrService = make_unique<nostr::NostrServiceBase>(testAppender, mockClient);
};
-TEST_F(NostrServiceTest, Constructor_InitializesService_WithNoDefaultRelays)
+TEST_F(NostrServiceBaseTest, Constructor_InitializesService_WithNoDefaultRelays)
{
- auto nostrService = make_unique<nostr::NostrService>(testAppender, mockClient, fakeSigner);
+ auto nostrService = make_unique<nostr::NostrServiceBase>(testAppender, mockClient);
auto defaultRelays = nostrService->defaultRelays();
auto activeRelays = nostrService->activeRelays();
@@ -197,12 +183,11 @@ TEST_F(NostrServiceTest, Constructor_InitializesService_WithNoDefaultRelays)
ASSERT_EQ(activeRelays.size(), 0);
};
-TEST_F(NostrServiceTest, Constructor_InitializesService_WithProvidedDefaultRelays)
+TEST_F(NostrServiceBaseTest, Constructor_InitializesService_WithProvidedDefaultRelays)
{
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
auto defaultRelays = nostrService->defaultRelays();
auto activeRelays = nostrService->activeRelays();
@@ -215,14 +200,16 @@ TEST_F(NostrServiceTest, Constructor_InitializesService_WithProvidedDefaultRelay
ASSERT_EQ(activeRelays.size(), 0);
};
-TEST_F(NostrServiceTest, Destructor_StopsClient)
+TEST_F(NostrServiceBaseTest, Destructor_StopsClient)
{
EXPECT_CALL(*mockClient, start()).Times(1);
- auto nostrService = make_unique<nostr::NostrService>(testAppender, mockClient, fakeSigner);
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
+ testAppender,
+ mockClient);
};
-TEST_F(NostrServiceTest, OpenRelayConnections_OpensConnections_ToDefaultRelays)
+TEST_F(NostrServiceBaseTest, OpenRelayConnections_OpensConnections_ToDefaultRelays)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -244,10 +231,9 @@ TEST_F(NostrServiceTest, OpenRelayConnections_OpensConnections_ToDefaultRelays)
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -259,7 +245,7 @@ TEST_F(NostrServiceTest, OpenRelayConnections_OpensConnections_ToDefaultRelays)
}
};
-TEST_F(NostrServiceTest, OpenRelayConnections_OpensConnections_ToProvidedRelays)
+TEST_F(NostrServiceBaseTest, OpenRelayConnections_OpensConnections_ToProvidedRelays)
{
vector<string> testRelays = { "wss://nos.lol" };
@@ -283,10 +269,9 @@ TEST_F(NostrServiceTest, OpenRelayConnections_OpensConnections_ToProvidedRelays)
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections(testRelays);
@@ -298,7 +283,7 @@ TEST_F(NostrServiceTest, OpenRelayConnections_OpensConnections_ToProvidedRelays)
}
};
-TEST_F(NostrServiceTest, OpenRelayConnections_AddsOpenConnections_ToActiveRelays)
+TEST_F(NostrServiceBaseTest, OpenRelayConnections_AddsOpenConnections_ToActiveRelays)
{
vector<string> testRelays = { "wss://nos.lol" };
@@ -324,10 +309,9 @@ TEST_F(NostrServiceTest, OpenRelayConnections_AddsOpenConnections_ToActiveRelays
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -352,7 +336,7 @@ TEST_F(NostrServiceTest, OpenRelayConnections_AddsOpenConnections_ToActiveRelays
}
};
-TEST_F(NostrServiceTest, CloseRelayConnections_ClosesConnections_ToActiveRelays)
+TEST_F(NostrServiceBaseTest, CloseRelayConnections_ClosesConnections_ToActiveRelays)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -371,10 +355,9 @@ TEST_F(NostrServiceTest, CloseRelayConnections_ClosesConnections_ToActiveRelays)
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -387,7 +370,7 @@ TEST_F(NostrServiceTest, CloseRelayConnections_ClosesConnections_ToActiveRelays)
ASSERT_EQ(activeRelays.size(), 0);
};
-TEST_F(NostrServiceTest, CloseRelayConnections_RemovesClosedConnections_FromActiveRelays)
+TEST_F(NostrServiceBaseTest, CloseRelayConnections_RemovesClosedConnections_FromActiveRelays)
{
vector<string> testRelays = { "wss://nos.lol" };
vector<string> allTestRelays = { defaultTestRelays[0], defaultTestRelays[1], testRelays[0] };
@@ -410,10 +393,9 @@ TEST_F(NostrServiceTest, CloseRelayConnections_RemovesClosedConnections_FromActi
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
allTestRelays);
nostrService->openRelayConnections();
@@ -433,7 +415,7 @@ TEST_F(NostrServiceTest, CloseRelayConnections_RemovesClosedConnections_FromActi
}
};
-TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllSuccesses)
+TEST_F(NostrServiceBaseTest, PublishEvent_CorrectlyIndicates_AllSuccesses)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -452,10 +434,9 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllSuccesses)
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -484,7 +465,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllSuccesses)
ASSERT_EQ(failures.size(), 0);
};
-TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllFailures)
+TEST_F(NostrServiceBaseTest, PublishEvent_CorrectlyIndicates_AllFailures)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -503,10 +484,9 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllFailures)
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -530,7 +510,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_AllFailures)
}
};
-TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailures)
+TEST_F(NostrServiceBaseTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailures)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -549,10 +529,9 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailur
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -587,7 +566,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_MixedSuccessesAndFailur
ASSERT_EQ(failures[0], defaultTestRelays[0]);
};
-TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_RejectedEvent)
+TEST_F(NostrServiceBaseTest, PublishEvent_CorrectlyIndicates_RejectedEvent)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -606,10 +585,9 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_RejectedEvent)
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -637,7 +615,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_RejectedEvent)
}
};
-TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_EventRejectedBySomeRelays)
+TEST_F(NostrServiceBaseTest, PublishEvent_CorrectlyIndicates_EventRejectedBySomeRelays)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -656,10 +634,9 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_EventRejectedBySomeRela
return status;
}));
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
@@ -700,7 +677,7 @@ TEST_F(NostrServiceTest, PublishEvent_CorrectlyIndicates_EventRejectedBySomeRela
ASSERT_EQ(failures[0], defaultTestRelays[1]);
};
-TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE)
+TEST_F(NostrServiceBaseTest, QueryRelays_ReturnsEvents_UpToEOSE)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -719,32 +696,28 @@ TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE)
return status;
}));
- auto signer = make_unique<FakeSigner>();
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
auto testEvents = getMultipleTextNoteTestEvents();
- vector<shared_ptr<nostr::data::Event>> signedTestEvents;
+ vector<shared_ptr<nostr::data::Event>> sendableTestEvents;
for (nostr::data::Event testEvent : testEvents)
{
- auto signedEvent = make_shared<nostr::data::Event>(testEvent);
- signer->sign(signedEvent);
-
- auto serializedEvent = signedEvent->serialize();
+ auto event = make_shared<nostr::data::Event>(testEvent);
+ auto serializedEvent = event->serialize();
auto deserializedEvent = nostr::data::Event::fromString(serializedEvent);
- signedEvent = make_shared<nostr::data::Event>(deserializedEvent);
- signedTestEvents.push_back(signedEvent);
+ event = make_shared<nostr::data::Event>(deserializedEvent);
+ sendableTestEvents.push_back(event);
}
// Expect the query messages.
EXPECT_CALL(*mockClient, send(HasSubstr("REQ"), _, _))
.Times(2)
- .WillRepeatedly(Invoke([&testEvents, &signer](
+ .WillRepeatedly(Invoke([&testEvents](
string message,
string uri,
function<void(const string&)> messageHandler)
@@ -755,7 +728,6 @@ TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE)
for (auto event : testEvents)
{
auto sendableEvent = make_shared<nostr::data::Event>(event);
- signer->sign(sendableEvent);
json jarr = json::array({ "EVENT", subscriptionId, sendableEvent->serialize() });
messageHandler(jarr.dump());
}
@@ -784,20 +756,20 @@ TEST_F(NostrServiceTest, QueryRelays_ReturnsEvents_UpToEOSE)
{
ASSERT_NE(
find_if(
- signedTestEvents.begin(),
- signedTestEvents.end(),
+ sendableTestEvents.begin(),
+ sendableTestEvents.end(),
[&resultEvent](shared_ptr<nostr::data::Event> testEvent)
{
return *testEvent == *resultEvent;
}),
- signedTestEvents.end());
+ sendableTestEvents.end());
}
auto subscriptions = nostrService->subscriptions();
ASSERT_TRUE(subscriptions.empty());
};
-TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents)
+TEST_F(NostrServiceBaseTest, QueryRelays_CallsHandler_WithReturnedEvents)
{
mutex connectionStatusMutex;
auto connectionStatus = make_shared<unordered_map<string, bool>>();
@@ -816,31 +788,27 @@ TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents)
return status;
}));
- auto signer = make_unique<FakeSigner>();
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
defaultTestRelays);
nostrService->openRelayConnections();
auto testEvents = getMultipleTextNoteTestEvents();
- vector<shared_ptr<nostr::data::Event>> signedTestEvents;
+ vector<shared_ptr<nostr::data::Event>> sendableTestEvents;
for (nostr::data::Event testEvent : testEvents)
{
- auto signedEvent = make_shared<nostr::data::Event>(testEvent);
- signer->sign(signedEvent);
-
- auto serializedEvent = signedEvent->serialize();
+ auto event = make_shared<nostr::data::Event>(testEvent);
+ auto serializedEvent = event->serialize();
auto deserializedEvent = nostr::data::Event::fromString(serializedEvent);
- signedEvent = make_shared<nostr::data::Event>(deserializedEvent);
- signedTestEvents.push_back(signedEvent);
+ event = make_shared<nostr::data::Event>(deserializedEvent);
+ sendableTestEvents.push_back(event);
}
EXPECT_CALL(*mockClient, send(HasSubstr("REQ"), _, _))
.Times(2)
- .WillRepeatedly(Invoke([&testEvents, &signer](
+ .WillRepeatedly(Invoke([&testEvents](
string message,
string uri,
function<void(const string&)> messageHandler)
@@ -851,7 +819,6 @@ TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents)
for (auto event : testEvents)
{
auto sendableEvent = make_shared<nostr::data::Event>(event);
- signer->sign(sendableEvent);
json jarr = json::array({ "EVENT", subscriptionId, sendableEvent->serialize() });
messageHandler(jarr.dump());
}
@@ -869,18 +836,18 @@ TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents)
string generatedSubscriptionId = nostrService->queryRelays(
filters,
- [&generatedSubscriptionId, &signedTestEvents](const string& subscriptionId, shared_ptr<nostr::data::Event> event)
+ [&generatedSubscriptionId, &sendableTestEvents](const string& subscriptionId, shared_ptr<nostr::data::Event> event)
{
ASSERT_STREQ(subscriptionId.c_str(), generatedSubscriptionId.c_str());
ASSERT_NE(
find_if(
- signedTestEvents.begin(),
- signedTestEvents.end(),
+ sendableTestEvents.begin(),
+ sendableTestEvents.end(),
[&event](shared_ptr<nostr::data::Event> testEvent)
{
return *testEvent == *event;
}),
- signedTestEvents.end());
+ sendableTestEvents.end());
},
[&generatedSubscriptionId, &eoseReceivedPromise, &eoseCount]
(const string& subscriptionId)
@@ -917,7 +884,7 @@ TEST_F(NostrServiceTest, QueryRelays_CallsHandler_WithReturnedEvents)
ASSERT_TRUE(subscriptions.empty());
};
-TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
+TEST_F(NostrServiceBaseTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
{
// Mock connections.
mutex connectionStatusMutex;
@@ -937,33 +904,29 @@ TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
return status;
}));
- auto signer = make_unique<FakeSigner>();
- auto nostrService = make_unique<nostr::NostrService>(
+ auto nostrService = make_unique<nostr::NostrServiceBase>(
testAppender,
mockClient,
- fakeSigner,
testRelays);
nostrService->openRelayConnections();
// Mock relay responses.
auto testEvents = getMultipleTextNoteTestEvents();
- vector<shared_ptr<nostr::data::Event>> signedTestEvents;
+ vector<shared_ptr<nostr::data::Event>> sendableTestEvents;
for (nostr::data::Event testEvent : testEvents)
{
- auto signedEvent = make_shared<nostr::data::Event>(testEvent);
- signer->sign(signedEvent);
-
- auto serializedEvent = signedEvent->serialize();
+ auto event = make_shared<nostr::data::Event>(testEvent);
+ auto serializedEvent = event->serialize();
auto deserializedEvent = nostr::data::Event::fromString(serializedEvent);
- signedEvent = make_shared<nostr::data::Event>(deserializedEvent);
- signedTestEvents.push_back(signedEvent);
+ event = make_shared<nostr::data::Event>(deserializedEvent);
+ sendableTestEvents.push_back(event);
}
vector<string> subscriptionIds;
EXPECT_CALL(*mockClient, send(HasSubstr("REQ"), _, _))
.Times(2)
- .WillOnce(Invoke([&testEvents, &signer, &subscriptionIds](
+ .WillOnce(Invoke([&testEvents, &subscriptionIds](
string message,
string uri,
function<void(const string&)> messageHandler)
@@ -974,7 +937,6 @@ TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
for (auto event : testEvents)
{
auto sendableEvent = make_shared<nostr::data::Event>(event);
- signer->sign(sendableEvent);
json jarr = json::array({ "EVENT", subscriptionIds.at(0), sendableEvent->serialize() });
messageHandler(jarr.dump());
}
@@ -984,7 +946,7 @@ TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
return make_tuple(uri, true);
}))
- .WillOnce(Invoke([&testEvents, &signer, &subscriptionIds](
+ .WillOnce(Invoke([&testEvents, &subscriptionIds](
string message,
string uri,
function<void(const string&)> messageHandler)
@@ -995,7 +957,6 @@ TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
for (auto event : testEvents)
{
auto sendableEvent = make_shared<nostr::data::Event>(event);
- signer->sign(sendableEvent);
json jarr = json::array({ "EVENT", subscriptionIds.at(1), sendableEvent->serialize() });
messageHandler(jarr.dump());
}
@@ -1016,18 +977,18 @@ TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
string shortFormSubscriptionId = nostrService->queryRelays(
shortFormFilters,
- [&shortFormSubscriptionId, &signedTestEvents](const string& subscriptionId, shared_ptr<nostr::data::Event> event)
+ [&shortFormSubscriptionId, &sendableTestEvents](const string& subscriptionId, shared_ptr<nostr::data::Event> event)
{
ASSERT_STREQ(subscriptionId.c_str(), shortFormSubscriptionId.c_str());
ASSERT_NE(
find_if(
- signedTestEvents.begin(),
- signedTestEvents.end(),
+ sendableTestEvents.begin(),
+ sendableTestEvents.end(),
[&event](shared_ptr<nostr::data::Event> testEvent)
{
return *testEvent == *event;
}),
- signedTestEvents.end());
+ sendableTestEvents.end());
},
[&shortFormSubscriptionId, &shortFormPromise]
(const string& subscriptionId)
@@ -1038,18 +999,18 @@ TEST_F(NostrServiceTest, Service_MaintainsMultipleSubscriptions_ThenClosesAll)
[](const string&, const string&) {});
string longFormSubscriptionId = nostrService->queryRelays(
shortFormFilters,
- [&longFormSubscriptionId, &signedTestEvents](const string& subscriptionId, shared_ptr<nostr::data::Event> event)
+ [&longFormSubscriptionId, &sendableTestEvents](const string& subscriptionId, shared_ptr<nostr::data::Event> event)
{
ASSERT_STREQ(subscriptionId.c_str(), longFormSubscriptionId.c_str());
ASSERT_NE(
find_if(
- signedTestEvents.begin(),
- signedTestEvents.end(),
+ sendableTestEvents.begin(),
+ sendableTestEvents.end(),
[&event](shared_ptr<nostr::data::Event> testEvent)
{
return *testEvent == *event;
}),
- signedTestEvents.end());
+ sendableTestEvents.end());
},
[&longFormSubscriptionId, &longFormPromise]
(const string& subscriptionId)