diff --git a/examples/ESP32TestNWC/ESP32TestNWC.cpp b/examples/ESP32TestNWC/ESP32TestNWC.cpp index af03d5e..a622868 100644 --- a/examples/ESP32TestNWC/ESP32TestNWC.cpp +++ b/examples/ESP32TestNWC/ESP32TestNWC.cpp @@ -1,20 +1,20 @@ -#include "services/NWC.h" #include "Transport.h" #include "esp32/ESP32Platform.h" - +#include "services/NWC.h" // CONFIGURATION #define WIFI_SSID "Wokwi-GUEST" #define WIFI_PASS "" #define WIFI_CHANNEL 6 // IMPORTANT !!! Set a valid NWC url here -#define NWC_URL "nostr+walletconnect://69effe7b49a6dd5cf525bd0905917a5005ffe480b58eeb8e861418cf3ae760d9?relay=wss://relay.getalby.com/v1&secret=1205ebd25d79a52a4e51920f6e1981a43400dc49daaa65d367bd8090218d206c&lud16=rblb@getalby.com" +#define NWC_URL \ + "nostr+walletconnect://69effe7b49a6dd5cf525bd0905917a5005ffe480b58eeb8e861418cf3ae760d9?relay=wss://relay.getalby.com/" \ + "v1&secret=1205ebd25d79a52a4e51920f6e1981a43400dc49daaa65d367bd8090218d206c&lud16=rblb@getalby.com" // Note: running this setting with default values will send 10 sats to the address below #define PAYOUT_ADDRESS "zap@rblb.it" #define PAYOUT_AMOUNT_MSAT 10000 - void testNWC(); void setup() { @@ -46,6 +46,7 @@ void setup() { testNWC(); } + nostr::NWC *nwc; nostr::Transport *transport; @@ -57,13 +58,8 @@ void testNWC() { transport = nostr::esp32::ESP32Platform::getTransport(); nwc = new nostr::NWC(transport, NWC_URL); - nwc->getBalance( - [&](nostr::GetBalanceResponse resp) { - Serial.println("[!] Balance: " + String(resp.balance) + " msatoshis"); - }, - [](String err, String errMsg) { - Serial.println("[!] Error: " + err + " " + errMsg); - }); + nwc->getBalance([&](nostr::GetBalanceResponse resp) { Serial.println("[!] Balance: " + String(resp.balance) + " msatoshis"); }, + [](String err, String errMsg) { Serial.println("[!] Error: " + err + " " + errMsg); }); nwc->getInfo( [&](nostr::GetInfoResponse resp) { Serial.println("[!] Alias: " + resp.alias); @@ -77,19 +73,11 @@ void testNWC() { Serial.println(" " + method); } }, - [](String err, String errMsg) { - Serial.println("[!] Error: " + err + " " + errMsg); - }); + [](String err, String errMsg) { Serial.println("[!] Error: " + err + " " + errMsg); }); - NostrString invoice = transport->getInvoiceFromLNAddr( PAYOUT_ADDRESS, PAYOUT_AMOUNT_MSAT, "Arduino NWC test"); - Serial.println("[!] Paying " + String(PAYOUT_AMOUNT_MSAT) + " msats to " + - PAYOUT_ADDRESS + " invoice: " + invoice); + NostrString invoice = transport->getInvoiceFromLNAddr(PAYOUT_ADDRESS, PAYOUT_AMOUNT_MSAT, "Arduino NWC test"); + Serial.println("[!] Paying " + String(PAYOUT_AMOUNT_MSAT) + " msats to " + PAYOUT_ADDRESS + " invoice: " + invoice); nwc->payInvoice( - invoice, PAYOUT_AMOUNT_MSAT, - [&](nostr::PayInvoiceResponse resp) { - Serial.println("[!] Payment successful"); - }, - [](String err, String errMsg) { - Serial.println("[!] Error: " + err + " " + errMsg); - }); + invoice, PAYOUT_AMOUNT_MSAT, [&](nostr::PayInvoiceResponse resp) { Serial.println("[!] Payment successful"); }, + [](String err, String errMsg) { Serial.println("[!] Error: " + err + " " + errMsg); }); } \ No newline at end of file diff --git a/examples/ESP32TestNip01/ESP32TestNip01.cpp b/examples/ESP32TestNip01/ESP32TestNip01.cpp index 7db0343..adc40b1 100644 --- a/examples/ESP32TestNip01/ESP32TestNip01.cpp +++ b/examples/ESP32TestNip01/ESP32TestNip01.cpp @@ -1,9 +1,9 @@ #include "ArduinoJson.h" #include "NostrEvent.h" #include "NostrPool.h" +#include "Transport.h" #include "Utils.h" #include "esp32/ESP32Platform.h" -#include "Transport.h" #include "time.h" #define WIFI_SSID "Wokwi-GUEST" @@ -13,11 +13,10 @@ #define RELAY "wss://nostr.rblb.it:7777" #define PRIVKEY "1558dadfae151555818a6aa6cf046ca3dfbb196c419efc18482479a74b74009a" -std::vector pools; +std::vector pools; void testNIP01(); -void setup() -{ +void setup() { //////////////////////// /// INITIALIZATION /// Note: you need some form of this code in your sketch @@ -47,34 +46,29 @@ void setup() testNIP01(); } - - -void loop(){ - - // We need to call some pool methods in the main loop to make its internal loop work properly - // it is not very important how it is done, here we keep a reference of every pool in a vector - // but you can do it in a different way - for(nostr::NostrPool* pool:pools){ - // Run internal loop: refresh relays, complete pending connections, send pending messages +void loop() { + // We need to call some pool methods in the main loop to make its internal + // loop work properly it is not very important how it is done, here we keep + // a reference of every pool in a vector but you can do it in a different + // way + for (nostr::NostrPool *pool : pools) { + // Run internal loop: refresh relays, complete pending connections, send + // pending messages pool->loop(); } } -nostr::Transport* transport; +nostr::Transport *transport; -// Just a test for basic -// nostr functionality void testNIP01() { String relay = RELAY; - // nostr private key String privKey = PRIVKEY; transport = nostr::esp32::ESP32Platform::getTransport(); // We need a NostrPool instance that will handle all the communication nostr::NostrPool *pool = new nostr::NostrPool(transport); - pools.push_back( - pool); // NB. we are adding it to this vector since we need to call - // pool->loop() in the main loop to make it work properly + pools.push_back(pool); // NB. we are adding it to this vector since we need to call + // pool->loop() in the main loop to make it work properly // Lets subscribe to the relay String subId = pool->subscribeMany( @@ -86,15 +80,13 @@ void testNIP01() { // {"since",{"1234567890"}}, // {"until",{"1234567890"}}, // {"limit",{"10"}}, - {"#t", {"arduinoTest"}}} //, + {"#t", {"arduinoTest"}}} //, // You can add another filter here }, [&](const String &subId, nostr::SignedNostrEvent *event) { - // This is the callback that will be called when an event is - // received We can access the event content with event->getContent() - - // Here you should handle the event, for this test we will just - // serialize it and print to console + // Received events callback, we can access the event content with + // event->getContent() Here you should handle the event, for this + // test we will just serialize it and print to console JsonDocument doc; JsonArray arr = doc["data"].to(); event->toSendableEvent(arr); @@ -112,8 +104,7 @@ void testNIP01() { // This is the callback that will be called when the subscription is // EOSE Serial.println("Subscription EOSE: " + subId); - } - ); + }); // NB. you might want to save the subId somewhere since you are going to // need it to close the subscription like so: pool.closeSubscription(subId); @@ -123,8 +114,7 @@ void testNIP01() { // Lets try to send an event // First we create an unsigned event - nostr::UnsignedNostrEvent ev(1, "Hello, World!", - nostr::Utils::unixTimeSeconds()); + nostr::UnsignedNostrEvent ev(1, "Hello, World!", nostr::Utils::unixTimeSeconds()); // we can add some tags ev.getTags()->addTag("t", {"arduinoTest"}); // then we sign it with our private key and we will get a SignedNostrEvent @@ -142,5 +132,3 @@ void testNIP01() { pool->publish({relay}, &signEv); // The event will be sent in the next loop() call } - - diff --git a/examples/ESP32TestNip04/ESP32TestNip04.cpp b/examples/ESP32TestNip04/ESP32TestNip04.cpp index 58e2e0d..81a9429 100644 --- a/examples/ESP32TestNip04/ESP32TestNip04.cpp +++ b/examples/ESP32TestNip04/ESP32TestNip04.cpp @@ -10,8 +10,7 @@ void testNIP04(); -void setup() -{ +void setup() { //////////////////////// /// INITIALIZATION /// Note: you need some form of this code in your sketch @@ -23,7 +22,6 @@ void setup() //////////////////////// Serial.begin(115200); - Serial.println("Init time"); nostr::esp32::ESP32Platform::initTime("pool.ntp.org"); @@ -39,30 +37,25 @@ void setup() testNIP04(); } - -void testNIP04(){ - // Test encryption used in dms and other things - - +void testNIP04() { String privKeyA = "1558dadfae151555818a6aa6cf046ca3dfbb196c419efc18482479a74b74009a"; String pubKeyA = nostr::Utils::getPublicKey(privKeyA); String privKeyB = "4ba55ee68773c243f9bc714fac149b623e3a583f92738a0c633d38535110f6f2"; String pubKeyB = nostr::Utils::getPublicKey(privKeyB); String text = "Hello world 123"; - Serial.println("Text: \"" + text+"\""); + Serial.println("Text: \"" + text + "\""); nostr::Nip04 nip04; String encryptedText = nip04.encrypt(privKeyA, pubKeyB, text); - Serial.println("Encrypted text: \"" + encryptedText+"\""); + Serial.println("Encrypted text: \"" + encryptedText + "\""); String decryptedText = nip04.decrypt(privKeyB, pubKeyA, encryptedText); - Serial.println("Decrypted text: \"" + decryptedText+"\""); - - if(text.equals(decryptedText)){ + Serial.println("Decrypted text: \"" + decryptedText + "\""); + + if (text.equals(decryptedText)) { Serial.println("NIP04 test passed"); - }else{ + } else { Serial.println("NIP04 test failed"); } - } void loop() {} diff --git a/src/Nip04.cpp b/src/Nip04.cpp index fbc16bd..0ce2495 100644 --- a/src/Nip04.cpp +++ b/src/Nip04.cpp @@ -1,17 +1,14 @@ #include "Nip04.h" using namespace nostr; -NostrString Nip04::decrypt(NostrString& privateKeyHex, - NostrString& senderPubKeyHex, NostrString content) { - +NostrString Nip04::decrypt(NostrString &privateKeyHex, NostrString &senderPubKeyHex, NostrString content) { + int ivParamIndex = NostrString_indexOf(content, "?iv="); - NostrString encryptedMessage = - NostrString_substring(content, 0, ivParamIndex); + NostrString encryptedMessage = NostrString_substring(content, 0, ivParamIndex); NostrString encryptedMessageHex = NostrString_base64ToHex(encryptedMessage); int encryptedMessageSize = NostrString_length(encryptedMessageHex) / 2; byte encryptedMessageBin[encryptedMessageSize]; - NostrString_hexToBytes(encryptedMessageHex, encryptedMessageBin, - encryptedMessageSize); + NostrString_hexToBytes(encryptedMessageHex, encryptedMessageBin, encryptedMessageSize); // fromHex(encryptedMessageHex, encryptedMessageBin, // encryptedMessageSize); @@ -40,13 +37,11 @@ NostrString Nip04::decrypt(NostrString& privateKeyHex, NostrString sharedPointXHex = NostrString_bytesToHex(sharedPointX, 32); NostrString message = decryptData(sharedPointX, ivBin, encryptedMessageHex); - message= NostrString_trim(message); + message = NostrString_trim(message); - return message; } -NostrString Nip04::encrypt(NostrString& privateKeyHex, - NostrString& recipientPubKeyHex, NostrString content) { +NostrString Nip04::encrypt(NostrString &privateKeyHex, NostrString &recipientPubKeyHex, NostrString content) { // Get shared point // Create the private key object int byteSize = 32; @@ -57,8 +52,7 @@ NostrString Nip04::encrypt(NostrString& privateKeyHex, byte publicKeyBin[64]; // fromHex("02" + NostrString(recipientPubKeyHex), publicKeyBin, 64); - NostrString_hexToBytes("02" + NostrString(recipientPubKeyHex), publicKeyBin, - 64); + NostrString_hexToBytes("02" + NostrString(recipientPubKeyHex), publicKeyBin, 64); PublicKey otherDhPublicKey(publicKeyBin); byte sharedPointX[32]; @@ -83,8 +77,7 @@ NostrString Nip04::encrypt(NostrString& privateKeyHex, uint8_t encryptedMessage[encryptedMessageSize]; // fromHex(encryptedMessageHex, encryptedMessage, // encryptedMessageSize); - NostrString_hexToBytes(encryptedMessageHex, encryptedMessage, - encryptedMessageSize); + NostrString_hexToBytes(encryptedMessageHex, encryptedMessage, encryptedMessageSize); String encryptedMessageBase64 = hexToBase64(encryptedMessageHex); @@ -95,9 +88,7 @@ NostrString Nip04::encrypt(NostrString& privateKeyHex, NostrString Nip04::encryptData(byte key[32], byte iv[16], NostrString msg) { // message has to be padded at the end so it is a multiple of 16 - int padding_diff = NostrString_length(msg) % 16 == 0 - ? 16 - : 16 - (NostrString_length(msg) % 16); + int padding_diff = NostrString_length(msg) % 16 == 0 ? 16 : 16 - (NostrString_length(msg) % 16); int byteSize = NostrString_length(msg) + padding_diff; byte messageBin[byteSize]; @@ -111,8 +102,7 @@ NostrString Nip04::encryptData(byte key[32], byte iv[16], NostrString msg) { return toHex(messageBin, sizeof(messageBin)); } -void Nip04::stringToByteArray(const char *input, int padding_diff, - byte *output) { +void Nip04::stringToByteArray(const char *input, int padding_diff, byte *output) { int i = 0; // remove end-of-string char while (input[i] != '\0') { @@ -126,8 +116,7 @@ void Nip04::stringToByteArray(const char *input, int padding_diff, } } -NostrString Nip04::decryptData(byte key[32], byte iv[16], - NostrString messageHex) { +NostrString Nip04::decryptData(byte key[32], byte iv[16], NostrString messageHex) { int byteSize = NostrString_length(messageHex) / 2; byte messageBin[byteSize]; NostrString_hexToBytes(messageHex, messageBin, byteSize); diff --git a/src/Nip04.h b/src/Nip04.h index 55bb00e..7907a2e 100644 --- a/src/Nip04.h +++ b/src/Nip04.h @@ -9,24 +9,17 @@ #include "Utils.h" namespace nostr { - class Nip04 { - public: - NostrString decrypt(NostrString& privateKeyHex, - NostrString& senderPubKeyHex, - NostrString content); - NostrString encrypt(NostrString &privateKeyHex, - NostrString& recipientPubKeyHex, - NostrString content); +class Nip04 { + public: + NostrString decrypt(NostrString &privateKeyHex, NostrString &senderPubKeyHex, NostrString content); + NostrString encrypt(NostrString &privateKeyHex, NostrString &recipientPubKeyHex, NostrString content); - private: - NostrString encryptData(byte key[32], byte iv[16], - NostrString msg) ; + private: + NostrString encryptData(byte key[32], byte iv[16], NostrString msg); - void stringToByteArray(const char *input, int padding_diff, - byte *output) ; + void stringToByteArray(const char *input, int padding_diff, byte *output); - NostrString decryptData(byte key[32], byte iv[16], - NostrString messageHex) ; - }; -} // namespace nostr -#endif // NIP47_H \ No newline at end of file + NostrString decryptData(byte key[32], byte iv[16], NostrString messageHex); +}; +} // namespace nostr +#endif // NIP47_H \ No newline at end of file diff --git a/src/Nip47.cpp b/src/Nip47.cpp index 5163a3a..5868283 100644 --- a/src/Nip47.cpp +++ b/src/Nip47.cpp @@ -2,18 +2,16 @@ using namespace nostr; -SignedNostrEvent Nip47::createEvent(NostrString method, - JsonDocument doc) { +SignedNostrEvent Nip47::createEvent(NostrString method, JsonDocument doc) { doc["method"] = method; NostrString contentString; serializeJson(doc, contentString); doc.clear(); - contentString = this->nip04.encrypt(this->userPrivKey, this->servicePubKey, - contentString); + contentString = this->nip04.encrypt(this->userPrivKey, this->servicePubKey, contentString); UnsignedNostrEvent event(23194, contentString, Utils::unixTimeSeconds()); - NostrEventTags* tags = event.getTags(); + NostrEventTags *tags = event.getTags(); tags->addTag("p", {this->servicePubKey}); return event.sign(this->userPrivKey); @@ -29,10 +27,7 @@ SignedNostrEvent Nip47::payInvoice(NostrString invoice, unsigned long amount) { return this->createEvent("pay_invoice", doc); } -SignedNostrEvent Nip47::makeInvoice(unsigned long amount, - NostrString description, - NostrString descriptionHash, - unsigned long expiry) { +SignedNostrEvent Nip47::makeInvoice(unsigned long amount, NostrString description, NostrString descriptionHash, unsigned long expiry) { JsonDocument doc; JsonObject params = doc["params"].to(); params["amount"] = amount; @@ -73,8 +68,7 @@ SignedNostrEvent Nip47::getInfo() { JsonObject params = doc["params"].to(); return this->createEvent("get_info", doc); } -SignedNostrEvent Nip47::multiPayInvoice( - std::initializer_list invoices) { +SignedNostrEvent Nip47::multiPayInvoice(std::initializer_list invoices) { JsonDocument doc; JsonObject params = doc["params"].to(); JsonArray iv = params["invoices"].to(); @@ -86,9 +80,7 @@ SignedNostrEvent Nip47::multiPayInvoice( return this->createEvent("multi_pay_invoice", doc); } -SignedNostrEvent Nip47::payKeySend(NostrString pubkey, unsigned long amount, - NostrString preimage, - std::initializer_list tlv) { +SignedNostrEvent Nip47::payKeySend(NostrString pubkey, unsigned long amount, NostrString preimage, std::initializer_list tlv) { JsonDocument doc; JsonObject params = doc["params"].to(); params["pubkey"] = pubkey; @@ -108,8 +100,7 @@ SignedNostrEvent Nip47::payKeySend(NostrString pubkey, unsigned long amount, return this->createEvent("pay_key_send", doc); } -SignedNostrEvent Nip47::multiPayKeySend( - std::initializer_list keySends) { +SignedNostrEvent Nip47::multiPayKeySend(std::initializer_list keySends) { JsonDocument doc; JsonObject params = doc["params"].to(); JsonArray ks = params["key_sends"].to(); @@ -133,10 +124,7 @@ SignedNostrEvent Nip47::multiPayKeySend( return this->createEvent("multi_pay_key_send", doc); } -SignedNostrEvent Nip47::listTransactions(unsigned long from, - unsigned long until, int limit, - int offset, bool unpaid, - NostrString type) { +SignedNostrEvent Nip47::listTransactions(unsigned long from, unsigned long until, int limit, int offset, bool unpaid, NostrString type) { JsonDocument doc; JsonObject params = doc["params"].to(); if (from > 0) { @@ -159,15 +147,13 @@ SignedNostrEvent Nip47::listTransactions(unsigned long from, return this->createEvent("list_transactions", doc); } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received pay_invoice response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); JsonDocument doc; deserializeJson(doc, content); @@ -192,14 +178,12 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received multi_pay_invoice response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); JsonDocument doc; deserializeJson(doc, content); @@ -225,16 +209,14 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received pay_keysend response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); JsonDocument doc; deserializeJson(doc, content); @@ -259,15 +241,13 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received multi_pay_keysend response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); JsonDocument doc; deserializeJson(doc, content); @@ -293,15 +273,13 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received make_invoice response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); JsonDocument doc; deserializeJson(doc, content); @@ -316,26 +294,19 @@ void Nip47::parseResponse(SignedNostrEvent* response, if (NostrString_equals(resultType, "make_invoice")) { out.result.type = data["type"].as(); out.result.invoice = data["invoice"].as(); - out.result.description = - data["description"].as(); - out.result.descriptionHash = - data["description_hash"].as(); + out.result.description = data["description"].as(); + out.result.descriptionHash = data["description_hash"].as(); out.result.preimage = data["preimage"].as(); - out.result.paymentHash = - data["payment_hash"].as(); + out.result.paymentHash = data["payment_hash"].as(); out.result.amount = data["amount"].as(); - out.result.feesPaid = - data["fees_paid"].as(); - out.result.createdAt = - data["created_at"].as(); - out.result.expiresAt = - data["expires_at"].as(); + out.result.feesPaid = data["fees_paid"].as(); + out.result.createdAt = data["created_at"].as(); + out.result.expiresAt = data["expires_at"].as(); JsonDocument metadataDoc; JsonObject metadataObject = metadataDoc.as(); for (JsonPair kv : data["metadata"].as()) { - metadataObject[kv.key().c_str()] = - kv.value().as(); + metadataObject[kv.key().c_str()] = kv.value().as(); } out.result.metadata = metadataObject; @@ -350,15 +321,13 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received lookup_invoice response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); JsonDocument doc; deserializeJson(doc, content); @@ -373,28 +342,20 @@ void Nip47::parseResponse(SignedNostrEvent* response, if (NostrString_equals(resultType, "lookup_invoice")) { out.result.type = data["type"].as(); out.result.invoice = data["invoice"].as(); - out.result.description = - data["description"].as(); - out.result.descriptionHash = - data["description_hash"].as(); + out.result.description = data["description"].as(); + out.result.descriptionHash = data["description_hash"].as(); out.result.preimage = data["preimage"].as(); - out.result.paymentHash = - data["payment_hash"].as(); + out.result.paymentHash = data["payment_hash"].as(); out.result.amount = data["amount"].as(); - out.result.feesPaid = - data["fees_paid"].as(); - out.result.createdAt = - data["created_at"].as(); - out.result.expiresAt = - data["expires_at"].as(); - out.result.settledAt = - data["settled_at"].as(); + out.result.feesPaid = data["fees_paid"].as(); + out.result.createdAt = data["created_at"].as(); + out.result.expiresAt = data["expires_at"].as(); + out.result.settledAt = data["settled_at"].as(); JsonDocument metadataDoc; JsonObject metadataObject = metadataDoc.as(); for (JsonPair kv : data["metadata"].as()) { - metadataObject[kv.key().c_str()] = - kv.value().as(); + metadataObject[kv.key().c_str()] = kv.value().as(); } out.result.metadata = metadataObject; @@ -409,15 +370,13 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received list_transactions response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); JsonDocument doc; deserializeJson(doc, content); @@ -433,34 +392,21 @@ void Nip47::parseResponse(SignedNostrEvent* response, for (JsonPair kv : data["transactions"].as()) { Transaction transaction; transaction.type = kv.value()["type"].as(); - transaction.invoice = - kv.value()["invoice"].as(); - transaction.description = - kv.value()["description"].as(); - transaction.descriptionHash = - kv.value()["description_hash"].as(); - transaction.preimage = - kv.value()["preimage"].as(); - transaction.paymentHash = - kv.value()["payment_hash"].as(); - transaction.amount = - kv.value()["amount"].as(); - transaction.feesPaid = - kv.value()["fees_paid"].as(); - transaction.createdAt = - kv.value()["created_at"].as(); - transaction.expiresAt = - kv.value()["expires_at"].as(); - transaction.settledAt = - kv.value()["settled_at"].as(); + transaction.invoice = kv.value()["invoice"].as(); + transaction.description = kv.value()["description"].as(); + transaction.descriptionHash = kv.value()["description_hash"].as(); + transaction.preimage = kv.value()["preimage"].as(); + transaction.paymentHash = kv.value()["payment_hash"].as(); + transaction.amount = kv.value()["amount"].as(); + transaction.feesPaid = kv.value()["fees_paid"].as(); + transaction.createdAt = kv.value()["created_at"].as(); + transaction.expiresAt = kv.value()["expires_at"].as(); + transaction.settledAt = kv.value()["settled_at"].as(); JsonDocument metadataDoc; - JsonObject metadataObject = - metadataDoc.as(); - for (JsonPair kv : - kv.value()["metadata"].as()) { - metadataObject[kv.key().c_str()] = - kv.value().as(); + JsonObject metadataObject = metadataDoc.as(); + for (JsonPair kv : kv.value()["metadata"].as()) { + metadataObject[kv.key().c_str()] = kv.value().as(); } transaction.metadata = metadataObject; @@ -477,23 +423,20 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received get_balance response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); - JsonDocument doc; -deserializeJson(doc, content); -JsonObject error = doc["error"]; -if (!error.isNull()) { - out.errorCode = error["code"].as(); - out.errorMessage = error["message"].as(); - } - else { + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); + JsonDocument doc; + deserializeJson(doc, content); + JsonObject error = doc["error"]; + if (!error.isNull()) { + out.errorCode = error["code"].as(); + out.errorMessage = error["message"].as(); + } else { if (doc.containsKey("result") && doc.containsKey("result_type")) { NostrString resultType = doc["result_type"].as(); JsonObject data = doc["result"]; @@ -510,17 +453,14 @@ if (!error.isNull()) { out.errorMessage = "Invalid Event"; } } -void Nip47::parseResponse(SignedNostrEvent* response, - Nip47Response& out) { +void Nip47::parseResponse(SignedNostrEvent *response, Nip47Response &out) { out.errorCode = ""; out.errorMessage = ""; Utils::log("NWC: received get_info response"); if (response->verify()) { - NostrString content = this->nip04.decrypt( - this->userPrivKey, this->servicePubKey, response->getContent()); + NostrString content = this->nip04.decrypt(this->userPrivKey, this->servicePubKey, response->getContent()); - JsonDocument doc; deserializeJson(doc, content); JsonObject error = doc["error"]; @@ -536,8 +476,7 @@ void Nip47::parseResponse(SignedNostrEvent* response, out.result.color = data["color"].as(); out.result.pubkey = data["pubkey"].as(); out.result.network = data["network"].as(); - out.result.blockHeight = - data["block_height"].as(); + out.result.blockHeight = data["block_height"].as(); out.result.blockHash = data["block_hash"].as(); JsonArray methodsObj = data["methods"].as(); for (JsonVariant v : methodsObj) { @@ -555,18 +494,15 @@ void Nip47::parseResponse(SignedNostrEvent* response, } } - -void Nip47::parseNWC(NostrString nwc, NWCData& data) { +void Nip47::parseNWC(NostrString nwc, NWCData &data) { NostrString prefix = "nostr+walletconnect://"; int prefixPos = NostrString_indexOf(nwc, prefix.c_str()); if (prefixPos != -1) { - NostrString withoutPrefix = - NostrString_substring(nwc, prefixPos + NostrString_length(prefix)); + NostrString withoutPrefix = NostrString_substring(nwc, prefixPos + NostrString_length(prefix)); int queryPos = NostrString_indexOf(withoutPrefix, "?"); if (queryPos != -1) { data.pubkey = NostrString_substring(withoutPrefix, 0, queryPos); - NostrString queryParams = - NostrString_substring(withoutPrefix, queryPos + 1); + NostrString queryParams = NostrString_substring(withoutPrefix, queryPos + 1); std::vector paramsXvals; NostrString_split(queryParams, '&', paramsXvals); for (NostrString paramXval : paramsXvals) { @@ -575,8 +511,7 @@ void Nip47::parseNWC(NostrString nwc, NWCData& data) { if (paramXvalSplit.size() == 2) { if (NostrString_equals(paramXvalSplit[0], "relay")) { data.relay = NostrString_urlDecode(paramXvalSplit[1]); - } else if (NostrString_equals(paramXvalSplit[0], - "secret")) { + } else if (NostrString_equals(paramXvalSplit[0], "secret")) { data.secret = NostrString_urlDecode(paramXvalSplit[1]); } } diff --git a/src/Nip47.h b/src/Nip47.h index 790ab88..78487ee 100644 --- a/src/Nip47.h +++ b/src/Nip47.h @@ -2,194 +2,159 @@ #define _NIP47_H #include "ArduinoJson.h" +#include "Nip04.h" #include "NostrEvent.h" #include "NostrString.h" #include "Utils.h" -#include "Nip04.h" namespace nostr { - typedef struct s_Invoice { - NostrString invoice; - unsigned long amount; - } Invoice; - typedef struct s_TLVRecords { - NostrString type; - NostrString value; - } TLVRecords; - typedef struct s_KeySend { - NostrString pubkey; - unsigned long amount; - NostrString preimage; - std::initializer_list tlv; - } KeySend; - - template - class Nip47Response { - public: - Nip47Response() {} - - Nip47Response(NostrString errorCode, NostrString errorMessage, - NostrString resultType, T result) - : errorCode(errorCode), - errorMessage(errorMessage), - resultType(resultType), - result(result) {} - NostrString errorCode = ""; - NostrString errorMessage = ""; - NostrString resultType = ""; - T result; - }; - - typedef struct s_PayInvoiceResponse { - NostrString preimage; - } PayInvoiceResponse; - - typedef struct s_MultiPayInvoiceResponse { - NostrString preimage; - NostrString d; - } MultiPayInvoiceResponse; - - typedef struct s_PayKeySendResponse { - NostrString preimage; - } PayKeySendResponse; - - typedef struct s_MultiPayKeySendResponse { - NostrString preimage; - NostrString d; - - } MultiPayKeySendResponse; - - typedef struct s_MakeInvoiceResponse { - NostrString type; - NostrString invoice; - NostrString description; - NostrString descriptionHash; - NostrString preimage; - NostrString paymentHash; - unsigned long long amount; - unsigned long long feesPaid; - unsigned long long createdAt; - unsigned long long expiresAt; - JsonObject metadata; - } MakeInvoiceResponse; - - typedef struct s_LookUpInvoiceResponse { - NostrString type; - NostrString invoice; - NostrString description; - NostrString descriptionHash; - NostrString preimage; - NostrString paymentHash; - unsigned long long amount; - unsigned long long feesPaid; - unsigned long long createdAt; - unsigned long long expiresAt; - unsigned long long settledAt; - - JsonObject metadata; - } LookUpInvoiceResponse; - - - typedef struct s_Transaction { - NostrString type; - NostrString invoice; - NostrString description; - NostrString descriptionHash; - NostrString preimage; - NostrString paymentHash; - unsigned long long amount; - unsigned long long feesPaid; - unsigned long long createdAt; - unsigned long long expiresAt; - unsigned long long settledAt; - - JsonObject metadata; - - } Transaction; - - - typedef struct s_ListTransactionsResponse { - std::vector transactions; - } ListTransactionsResponse; - - typedef struct s_GetBalanceResponse { - unsigned long long balance; - } GetBalanceResponse; - - - typedef struct s_GetInfoResponse { - NostrString alias; - NostrString color; - NostrString pubkey; - NostrString network; - unsigned long long blockHeight; - NostrString blockHash; - std::vector methods; - } GetInfoResponse; - - typedef struct s_NWCData { - NostrString relay; - NostrString pubkey; - NostrString secret; - } NWCData; - - class Nip47 { - public: - Nip47(){}; - Nip47(Nip04 nip04, NostrString servicePubKey, - NostrString userPrivKey) - : servicePubKey(servicePubKey), - userPrivKey(userPrivKey), - nip04(nip04) {} - SignedNostrEvent payInvoice(NostrString invoice, - unsigned long amount = -1); - SignedNostrEvent multiPayInvoice( - std::initializer_list invoices); - SignedNostrEvent payKeySend(NostrString pubkey, unsigned long amount, - NostrString preimage = "", - std::initializer_list tlv = {}); - SignedNostrEvent multiPayKeySend( - std::initializer_list keySends); - SignedNostrEvent makeInvoice(unsigned long amount, - NostrString description = "", - NostrString descriptionHash = "", - unsigned long expiry = 0); - SignedNostrEvent lookUpPaymentHash(NostrString paymentHash); - SignedNostrEvent lookUpInvoice(NostrString invoice); - SignedNostrEvent listTransactions(unsigned long from = 0, - unsigned long until = 0, - int limit = 0, int offset = 0, - bool unpaid = false, - NostrString type = ""); - SignedNostrEvent getBalance(); - SignedNostrEvent getInfo(); - - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - void parseResponse(SignedNostrEvent* response, - Nip47Response& out); - static void parseNWC(NostrString, NWCData&); - - private: - NostrString servicePubKey; - NostrString userPrivKey; - Nip04 nip04; - SignedNostrEvent createEvent(NostrString method, - JsonDocument doc); - }; -} // namespace nostr - -#endif // NIP47_H \ No newline at end of file +typedef struct s_Invoice { + NostrString invoice; + unsigned long amount; +} Invoice; +typedef struct s_TLVRecords { + NostrString type; + NostrString value; +} TLVRecords; +typedef struct s_KeySend { + NostrString pubkey; + unsigned long amount; + NostrString preimage; + std::initializer_list tlv; +} KeySend; + +template class Nip47Response { + public: + Nip47Response() {} + + Nip47Response(NostrString errorCode, NostrString errorMessage, NostrString resultType, T result) : errorCode(errorCode), errorMessage(errorMessage), resultType(resultType), result(result) {} + NostrString errorCode = ""; + NostrString errorMessage = ""; + NostrString resultType = ""; + T result; +}; + +typedef struct s_PayInvoiceResponse { + NostrString preimage; +} PayInvoiceResponse; + +typedef struct s_MultiPayInvoiceResponse { + NostrString preimage; + NostrString d; +} MultiPayInvoiceResponse; + +typedef struct s_PayKeySendResponse { + NostrString preimage; +} PayKeySendResponse; + +typedef struct s_MultiPayKeySendResponse { + NostrString preimage; + NostrString d; + +} MultiPayKeySendResponse; + +typedef struct s_MakeInvoiceResponse { + NostrString type; + NostrString invoice; + NostrString description; + NostrString descriptionHash; + NostrString preimage; + NostrString paymentHash; + unsigned long long amount; + unsigned long long feesPaid; + unsigned long long createdAt; + unsigned long long expiresAt; + JsonObject metadata; +} MakeInvoiceResponse; + +typedef struct s_LookUpInvoiceResponse { + NostrString type; + NostrString invoice; + NostrString description; + NostrString descriptionHash; + NostrString preimage; + NostrString paymentHash; + unsigned long long amount; + unsigned long long feesPaid; + unsigned long long createdAt; + unsigned long long expiresAt; + unsigned long long settledAt; + + JsonObject metadata; +} LookUpInvoiceResponse; + +typedef struct s_Transaction { + NostrString type; + NostrString invoice; + NostrString description; + NostrString descriptionHash; + NostrString preimage; + NostrString paymentHash; + unsigned long long amount; + unsigned long long feesPaid; + unsigned long long createdAt; + unsigned long long expiresAt; + unsigned long long settledAt; + + JsonObject metadata; + +} Transaction; + +typedef struct s_ListTransactionsResponse { + std::vector transactions; +} ListTransactionsResponse; + +typedef struct s_GetBalanceResponse { + unsigned long long balance; +} GetBalanceResponse; + +typedef struct s_GetInfoResponse { + NostrString alias; + NostrString color; + NostrString pubkey; + NostrString network; + unsigned long long blockHeight; + NostrString blockHash; + std::vector methods; +} GetInfoResponse; + +typedef struct s_NWCData { + NostrString relay; + NostrString pubkey; + NostrString secret; +} NWCData; + +class Nip47 { + public: + Nip47(){}; + Nip47(Nip04 nip04, NostrString servicePubKey, NostrString userPrivKey) : servicePubKey(servicePubKey), userPrivKey(userPrivKey), nip04(nip04) {} + SignedNostrEvent payInvoice(NostrString invoice, unsigned long amount = -1); + SignedNostrEvent multiPayInvoice(std::initializer_list invoices); + SignedNostrEvent payKeySend(NostrString pubkey, unsigned long amount, NostrString preimage = "", std::initializer_list tlv = {}); + SignedNostrEvent multiPayKeySend(std::initializer_list keySends); + SignedNostrEvent makeInvoice(unsigned long amount, NostrString description = "", NostrString descriptionHash = "", unsigned long expiry = 0); + SignedNostrEvent lookUpPaymentHash(NostrString paymentHash); + SignedNostrEvent lookUpInvoice(NostrString invoice); + SignedNostrEvent listTransactions(unsigned long from = 0, unsigned long until = 0, int limit = 0, int offset = 0, bool unpaid = false, NostrString type = ""); + SignedNostrEvent getBalance(); + SignedNostrEvent getInfo(); + + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + void parseResponse(SignedNostrEvent *response, Nip47Response &out); + static void parseNWC(NostrString, NWCData &); + + private: + NostrString servicePubKey; + NostrString userPrivKey; + Nip04 nip04; + SignedNostrEvent createEvent(NostrString method, JsonDocument doc); +}; +} // namespace nostr + +#endif // NIP47_H \ No newline at end of file diff --git a/src/NostrEvent.cpp b/src/NostrEvent.cpp index c9986b2..6a6f497 100644 --- a/src/NostrEvent.cpp +++ b/src/NostrEvent.cpp @@ -1,75 +1,60 @@ #include "NostrEvent.h" - - - using namespace nostr; - -const std::vector &NostrEventTags::getTags() const -{ +const std::vector &NostrEventTags::getTags() const { return tags; } const std::vector NostrEventTags::emptyTags; const std::vector &NostrEventTags::getTag(NostrString key) const { - for (auto &tag : tags) - { - if (NostrString_equals(tag.key , key)) { + for (auto &tag : tags) { + if (NostrString_equals(tag.key, key)) { return tag.value; } } return this->emptyTags; } -unsigned int NostrEventTags::addTag(NostrString key, - std::initializer_list values) { +unsigned int NostrEventTags::addTag(NostrString key, std::initializer_list values) { NostrEventTag tag; tag.key = key; - for (auto &value : values) - { + for (auto &value : values) { tag.value.push_back(value); } tags.push_back(tag); return tags.size(); } -unsigned int NostrEventTags::addTag(NostrString key, - std::vector values) { +unsigned int NostrEventTags::addTag(NostrString key, std::vector values) { NostrEventTag tag; tag.key = key; - for (auto &value : values) - { + for (auto &value : values) { tag.value.push_back(value); } tags.push_back(tag); return tags.size(); } -void NostrEventTags::removeTag(unsigned int index) -{ +void NostrEventTags::removeTag(unsigned int index) { tags.erase(tags.begin() + index); } void NostrEventTags::removeTags(NostrString key) { - for (int i = 0; i < tags.size(); i++) - { - if (NostrString_equals(tags[i].key ,key)) - { + for (int i = 0; i < tags.size(); i++) { + if (NostrString_equals(tags[i].key, key)) { tags.erase(tags.begin() + i); i--; } } } -void NostrEventTags::clearTags() -{ +void NostrEventTags::clearTags() { tags.clear(); } -void NostrEventTags::toJson(JsonArray arr) const -{ +void NostrEventTags::toJson(JsonArray arr) const { for (int i = 0; i < tags.size(); i++) { JsonArray arr2 = arr.add(); arr2.add(tags[i].key); @@ -106,15 +91,15 @@ SignedNostrEvent UnsignedNostrEvent::sign(NostrString privateKeyHex) { serializeJson(doc["data"], message); doc.clear(); - Utils::log("Compute signature of: "+message); + Utils::log("Compute signature of: " + message); // sha256 of message converted to hex, assign to msghash - byte hash[64] = {0}; + byte hash[64] = {0}; int hashLen = 0; hashLen = sha256(message, hash); NostrString msgHash = NostrString_bytesToHex(hash, hashLen); - Utils::log("Message hash: "+msgHash); + Utils::log("Message hash: " + msgHash); // Generate the schnorr sig of the messageHash byte messageBytes[NOSTR_DIGEST_SIZE]; @@ -122,34 +107,25 @@ SignedNostrEvent UnsignedNostrEvent::sign(NostrString privateKeyHex) { SchnorrSignature signature = privateKey.schnorr_sign(messageBytes); NostrString signatureHex = NostrString(signature); - SignedNostrEvent signedEvent( - msgHash, - pubKeyHex, - this->created_at, - this->kind, - this->tags, - this->content, - signatureHex - ); + SignedNostrEvent signedEvent(msgHash, pubKeyHex, this->created_at, this->kind, this->tags, this->content, signatureHex); Utils::log("Signature hash " + signatureHex); - return signedEvent; } -bool SignedNostrEvent::verify() const{ +bool SignedNostrEvent::verify() const { Serial.println("Verifying event signature"); byte messageBytes[32]; // fromHex(this->id, messageBytes, 32); NostrString_hexToBytes(this->id, messageBytes, 32); // Serial.println("Message hash: "+this->id); - Utils::log("Message hash: "+this->id); + Utils::log("Message hash: " + this->id); byte pubeyBytes[32]; - NostrString_hexToBytes("02"+this->pubkey, pubeyBytes, 32); + NostrString_hexToBytes("02" + this->pubkey, pubeyBytes, 32); // fromHex("02"+this->pubkey, pubeyBytes, 32); // Serial.println("Pubkey: "+this->pubkey); - Utils::log("Pubkey: "+this->pubkey); + Utils::log("Pubkey: " + this->pubkey); PublicKey pub(pubeyBytes); @@ -159,12 +135,10 @@ bool SignedNostrEvent::verify() const{ SchnorrSignature signature(signatureBytes); // Serial.println("Signature: " + this->signature); Utils::log("Signature: " + this->signature); - return pub.schnorr_verify(signature, messageBytes); - + return pub.schnorr_verify(signature, messageBytes); } -void SignedNostrEvent::toJson(JsonObject doc) const -{ +void SignedNostrEvent::toJson(JsonObject doc) const { doc["id"] = this->id; doc["pubkey"] = this->pubkey; doc["created_at"] = this->created_at; @@ -172,27 +146,25 @@ void SignedNostrEvent::toJson(JsonObject doc) const JsonArray tags = doc["tags"].to(); this->tags.toJson(tags); doc["content"] = this->content; - doc["sig"] = this->signature; - + doc["sig"] = this->signature; } -void SignedNostrEvent::toSendableEvent(JsonArray doc) const -{ +void SignedNostrEvent::toSendableEvent(JsonArray doc) const { doc.add("EVENT"); JsonObject obj = doc.add(); this->toJson(obj); } -SignedNostrEvent::SignedNostrEvent(JsonArray arr){ - if(arr[0] != "EVENT"){ +SignedNostrEvent::SignedNostrEvent(JsonArray arr) { + if (arr[0] != "EVENT") { throw std::runtime_error("Invalid event type"); } - + JsonObject obj; - if(arr.size()>2){ + if (arr.size() > 2) { obj = arr[2]; this->subid = arr[1].as(); - }else{ + } else { obj = arr[1]; } diff --git a/src/NostrEvent.h b/src/NostrEvent.h index 449cdbe..e5ea95c 100644 --- a/src/NostrEvent.h +++ b/src/NostrEvent.h @@ -2,7 +2,6 @@ #ifndef _NOSTR_EVENT_H #define _NOSTR_EVENT_H - #include "NostrString.h" #include @@ -20,166 +19,149 @@ #include "Hash.h" #include "Utils.h" namespace nostr { - using EventSubmissionFailureCallback = std::function; - - class SignedNostrEvent; - - typedef struct s_NostrEventTag { - NostrString key; - std::vector value; - } NostrEventTag; - - class NostrEventTags { - public: - static const std::vector emptyTags; - NostrEventTags(){}; - - /** - * Get the number of tags - */ - unsigned int count() { return tags.size(); } - - /** - * Get all tags - */ - const std::vector &getTags() const; - - /** - * Get the first occurrence of a tag with the given key - */ - const std::vector &getTag(NostrString key) const; - - /** - * Add a tag with a given key and set of values - * NB. You can add multiple tags with the same key - */ - unsigned int addTag(NostrString key, - std::initializer_list values); - - /** - * Add a tag with a given key and set of values - * NB. You can add multiple tags with the same key - */ - - unsigned int addTag(NostrString key, std::vector values); - - /** - * Remove a tag at a given index - */ - void removeTag(unsigned int index); - - /** - * Remove all occurrences of a tag with the given key - */ - void removeTags(NostrString key); - - /** - * Remove all tags - */ - void clearTags(); - - /** - * Output to json - */ - void toJson(JsonArray doc) const; - - protected: - std::vector tags; - }; +using EventSubmissionFailureCallback = std::function; + +class SignedNostrEvent; + +typedef struct s_NostrEventTag { + NostrString key; + std::vector value; +} NostrEventTag; + +class NostrEventTags { + public: + static const std::vector emptyTags; + NostrEventTags(){}; + + /** + * Get the number of tags + */ + unsigned int count() { return tags.size(); } + + /** + * Get all tags + */ + const std::vector &getTags() const; + + /** + * Get the first occurrence of a tag with the given key + */ + const std::vector &getTag(NostrString key) const; + + /** + * Add a tag with a given key and set of values + * NB. You can add multiple tags with the same key + */ + unsigned int addTag(NostrString key, std::initializer_list values); + + /** + * Add a tag with a given key and set of values + * NB. You can add multiple tags with the same key + */ + + unsigned int addTag(NostrString key, std::vector values); + + /** + * Remove a tag at a given index + */ + void removeTag(unsigned int index); + + /** + * Remove all occurrences of a tag with the given key + */ + void removeTags(NostrString key); /** - * Base class for NostrEvent + * Remove all tags */ - class NostrEvent { - public: - NostrEvent(){}; - - virtual ~NostrEvent(){}; - unsigned long int getCreatedAt() { return this->created_at; } - unsigned int getKind() { return this->kind; } - NostrEventTags *getTags() { return &this->tags; } - NostrString getContent() { return this->content; }; - - protected: - unsigned int kind; - NostrEventTags tags; - unsigned long int created_at; - NostrString content; - NostrEvent(unsigned int kind, NostrEventTags tags, NostrString content, - unsigned long int created_at) - : kind(kind), - tags(tags), - content(content), - created_at(created_at){}; - }; + void clearTags(); /** - * An unsigned NostrEvent. - * This is a support class used to create a new nostr event. - * When the event is ready to be sent, it should be signed with the sign - * method, the result is a SignedNostrEvent that can be sent to the relay. + * Output to json */ - class UnsignedNostrEvent : public NostrEvent { - public: - UnsignedNostrEvent() : NostrEvent(){}; - UnsignedNostrEvent(unsigned int kind, NostrString content, - unsigned long int created_at) - : NostrEvent(kind, NostrEventTags(), content, created_at){}; - - /** - * Sign the event with a private key - */ - SignedNostrEvent sign(NostrString privateKeyHex); - - void setCreatedAt(unsigned long int created_at) { - this->created_at = created_at; - }; - void setKind(unsigned int kind) { this->kind = kind; }; - - void setContent(NostrString content) { this->content = content; }; - }; + void toJson(JsonArray doc) const; + + protected: + std::vector tags; +}; + +/** + * Base class for NostrEvent + */ +class NostrEvent { + public: + NostrEvent(){}; + + virtual ~NostrEvent(){}; + unsigned long int getCreatedAt() { return this->created_at; } + unsigned int getKind() { return this->kind; } + NostrEventTags *getTags() { return &this->tags; } + NostrString getContent() { return this->content; }; + + protected: + unsigned int kind; + NostrEventTags tags; + unsigned long int created_at; + NostrString content; + NostrEvent(unsigned int kind, NostrEventTags tags, NostrString content, unsigned long int created_at) : kind(kind), tags(tags), content(content), created_at(created_at){}; +}; + +/** + * An unsigned NostrEvent. + * This is a support class used to create a new nostr event. + * When the event is ready to be sent, it should be signed with the sign + * method, the result is a SignedNostrEvent that can be sent to the relay. + */ +class UnsignedNostrEvent : public NostrEvent { + public: + UnsignedNostrEvent() : NostrEvent(){}; + UnsignedNostrEvent(unsigned int kind, NostrString content, unsigned long int created_at) : NostrEvent(kind, NostrEventTags(), content, created_at){}; /** - * A signed NostrEvent as it is received by the client and sent to the - * relay. + * Sign the event with a private key */ - class SignedNostrEvent : public NostrEvent { - friend class UnsignedNostrEvent; - friend class NostrPool; - - private: - NostrString id; - NostrString pubkey; - NostrString signature; - NostrString subid; - bool stored; - - public: - NostrString getId() { return this->id; } - bool isStored() { return this->stored; } - - NostrString getPubkey() { return this->pubkey; }; - - const NostrEventTags *getTags() const { return &this->tags; }; - - NostrString getSignature() const { return this->signature; }; - NostrString getSubId() const { return this->subid; }; - void toSendableEvent(JsonArray doc) const; - void toJson(JsonObject doc) const; - bool verify() const; - - protected: - SignedNostrEvent(JsonArray relayEvent); - SignedNostrEvent(NostrString id, NostrString pubkey, unsigned long int created_at, - unsigned int kind, NostrEventTags tags, NostrString content, - NostrString signature) - : NostrEvent(kind, tags, content, created_at), - id(id), - pubkey(pubkey), - signature(signature), - stored(false){}; - }; - - -} // namespace nostr + SignedNostrEvent sign(NostrString privateKeyHex); + + void setCreatedAt(unsigned long int created_at) { this->created_at = created_at; }; + void setKind(unsigned int kind) { this->kind = kind; }; + + void setContent(NostrString content) { this->content = content; }; +}; + +/** + * A signed NostrEvent as it is received by the client and sent to the + * relay. + */ +class SignedNostrEvent : public NostrEvent { + friend class UnsignedNostrEvent; + friend class NostrPool; + + private: + NostrString id; + NostrString pubkey; + NostrString signature; + NostrString subid; + bool stored; + + public: + NostrString getId() { return this->id; } + bool isStored() { return this->stored; } + + NostrString getPubkey() { return this->pubkey; }; + + const NostrEventTags *getTags() const { return &this->tags; }; + + NostrString getSignature() const { return this->signature; }; + NostrString getSubId() const { return this->subid; }; + void toSendableEvent(JsonArray doc) const; + void toJson(JsonObject doc) const; + bool verify() const; + + protected: + SignedNostrEvent(JsonArray relayEvent); + SignedNostrEvent(NostrString id, NostrString pubkey, unsigned long int created_at, unsigned int kind, NostrEventTags tags, NostrString content, NostrString signature) + : NostrEvent(kind, tags, content, created_at), id(id), pubkey(pubkey), signature(signature), stored(false){}; +}; + +} // namespace nostr #endif \ No newline at end of file diff --git a/src/NostrPool.cpp b/src/NostrPool.cpp index e822f20..4dc6383 100644 --- a/src/NostrPool.cpp +++ b/src/NostrPool.cpp @@ -6,117 +6,95 @@ void NostrRelay::send(NostrString message) { this->messageQueue.push_back(message); } -void NostrRelay::processQueue() -{ - if (!this->conn->isReady()){ +void NostrRelay::processQueue() { + if (!this->conn->isReady()) { return; } - if (this->messageQueue.size() > 0) { - for (auto &message : this->messageQueue) { - this->conn->send(message); - } - this->messageQueue.clear(); + if (this->messageQueue.size() > 0) { + for (auto &message : this->messageQueue) { + this->conn->send(message); } + this->messageQueue.clear(); + } } void NostrPool::onEvent(NostrRelay *relay, NostrString message) { - - Utils::log("Received: " + message); - JsonDocument doc; - deserializeJson(doc, message); - if (doc.size() == 0){ - return; + + Utils::log("Received: " + message); + JsonDocument doc; + deserializeJson(doc, message); + if (doc.size() == 0) { + return; + } + if (NostrString_equals(doc[0], "CLOSED")) { + NostrString subId = doc[1]; + NostrString reason = doc.size() > 2 ? doc[2].as() : ""; + std::map::iterator it = this->subscriptions.find(subId); + if (it != this->subscriptions.end()) { + if (it->second.closeCallback != nullptr) { + it->second.closeCallback(subId, reason); } - if (NostrString_equals(doc[0] , "CLOSED")) { - NostrString subId = doc[1]; - NostrString reason = doc.size() > 2 ? doc[2].as() : ""; - std::map::iterator it = - this->subscriptions.find(subId); - if (it != this->subscriptions.end()) - { - if (it->second.closeCallback != nullptr) - { - it->second.closeCallback(subId, reason); - } - this->subscriptions.erase(it); - } - } else if (NostrString_equals(doc[0] , "EOSE")) { - NostrString subId = doc[1].as(); - NostrSubscription* sub = &this->subscriptions[subId]; - if (!sub->eose) - { - sub->eose = true; - if (sub->eoseCallback != nullptr){ - sub->eoseCallback(subId); - } - } - } else if (NostrString_equals(doc[0], "OK")) { - NostrString eventId = doc[1].as(); - bool success=doc[2].as(); - NostrString message = - doc.size() > 3 ? doc[3].as() : ""; - for(int i=0;ieventStatusCallbackEntries.size();i++){ - EventStatusCallbackEntry entry = this->eventStatusCallbackEntries[i]; - if (NostrString_equals(entry.eventId , eventId)) { - if (entry.statusCallback != nullptr){ - entry.statusCallback(eventId, success, message); - } - this->eventStatusCallbackEntries.erase(this->eventStatusCallbackEntries.begin()+i); - - break; - } + this->subscriptions.erase(it); + } + } else if (NostrString_equals(doc[0], "EOSE")) { + NostrString subId = doc[1].as(); + NostrSubscription *sub = &this->subscriptions[subId]; + if (!sub->eose) { + sub->eose = true; + if (sub->eoseCallback != nullptr) { + sub->eoseCallback(subId); + } + } + } else if (NostrString_equals(doc[0], "OK")) { + NostrString eventId = doc[1].as(); + bool success = doc[2].as(); + NostrString message = doc.size() > 3 ? doc[3].as() : ""; + for (int i = 0; i < this->eventStatusCallbackEntries.size(); i++) { + EventStatusCallbackEntry entry = this->eventStatusCallbackEntries[i]; + if (NostrString_equals(entry.eventId, eventId)) { + if (entry.statusCallback != nullptr) { + entry.statusCallback(eventId, success, message); } + this->eventStatusCallbackEntries.erase(this->eventStatusCallbackEntries.begin() + i); - } else if (NostrString_equals(doc[0], "NOTICE")) { - NostrString message = doc[1].as(); - if(this->noticeCallback!=nullptr){ - this->noticeCallback(relay, message); - } - } else if (NostrString_equals(doc[0] , "EVENT")) { - NostrString subId = doc[1].as(); - NostrSubscription sub = this->subscriptions[subId]; - SignedNostrEvent event(doc.as()); - event.stored=!sub.eose; - if (sub.eventCallback != nullptr){ - sub.eventCallback(subId, &event); - } + break; } - - + } + + } else if (NostrString_equals(doc[0], "NOTICE")) { + NostrString message = doc[1].as(); + if (this->noticeCallback != nullptr) { + this->noticeCallback(relay, message); + } + } else if (NostrString_equals(doc[0], "EVENT")) { + NostrString subId = doc[1].as(); + NostrSubscription sub = this->subscriptions[subId]; + SignedNostrEvent event(doc.as()); + event.stored = !sub.eose; + if (sub.eventCallback != nullptr) { + sub.eventCallback(subId, &event); + } + } } -NostrString NostrPool::subscribeMany( - std::initializer_list urls, - std::initializer_list< - std::map>> - filters, - NostrEventCallback eventCallback, NostrCloseCallback closeCallback, - NostrEOSECallback eoseCallback) { +NostrString NostrPool::subscribeMany(std::initializer_list urls, std::initializer_list>> filters, + NostrEventCallback eventCallback, NostrCloseCallback closeCallback, NostrEOSECallback eoseCallback) { NostrString subId = Utils::getNewSubscriptionId(); JsonDocument doc; JsonArray req = doc["req"].to(); req.add("REQ"); req.add(subId); - for (const auto &filter : filters) - { + for (const auto &filter : filters) { JsonObject filterObj = req.add(); - for (const auto &pair : filter) - { + for (const auto &pair : filter) { NostrString key = pair.first; JsonArray arr = filterObj[key].to(); - bool isUint = NostrString_equals(key, "kinds") || - NostrString_equals(key, "since") || - NostrString_equals(key, "until") || - NostrString_equals(key , "limit"); - for (const auto &value : pair.second) - { - if (isUint) - { + bool isUint = NostrString_equals(key, "kinds") || NostrString_equals(key, "since") || NostrString_equals(key, "until") || NostrString_equals(key, "limit"); + for (const auto &value : pair.second) { + if (isUint) { NostrString vStr = value; arr.add(NostrString_toInt(vStr)); - } - else - { + } else { arr.add(value); } } @@ -126,19 +104,16 @@ NostrString NostrPool::subscribeMany( NostrString json; serializeJson(req, json); - if (this->subscriptions.find(subId) == this->subscriptions.end()) - { + if (this->subscriptions.find(subId) == this->subscriptions.end()) { // if subscription does not exist, create it this->subscriptions[subId] = NostrSubscription(); this->subscriptions[subId].closeCallback = closeCallback; this->subscriptions[subId].eoseCallback = eoseCallback; this->subscriptions[subId].eventCallback = eventCallback; - } - for (auto url : urls) - { - NostrRelay* r=this->ensureRelay(url); + for (auto url : urls) { + NostrRelay *r = this->ensureRelay(url); Utils::log("Subscribe to " + url + " with " + json); r->send(json); } @@ -148,7 +123,7 @@ NostrString NostrPool::subscribeMany( void NostrPool::closeSubscription(NostrString subId) { Utils::log("Closing subscription " + subId); - if(this->subscriptions.find(subId)==this->subscriptions.end()){ + if (this->subscriptions.find(subId) == this->subscriptions.end()) { // if subscription does not exist, ignore return; } @@ -167,28 +142,21 @@ void NostrPool::closeSubscription(NostrString subId) { this->subscriptions.erase(subId); } - - - NostrRelay *NostrPool::ensureRelay(NostrString url) { NostrRelay *relay = NULL; - for (auto &r : this->relays) - { - if (NostrString_equals(r->url , url)) { + for (auto &r : this->relays) { + if (NostrString_equals(r->url, url)) { relay = r; break; } } - if (relay == NULL) - { + if (relay == NULL) { Utils::log("Creating new relay for " + url); - Connection* conn = this->transport->connect(url); + Connection *conn = this->transport->connect(url); relay = new NostrRelay(conn, url); this->relays.push_back(relay); - relay->conn->addMessageListener([this, relay](NostrString message) { - this->onEvent(relay, message); - }); + relay->conn->addMessageListener([this, relay](NostrString message) { this->onEvent(relay, message); }); } return relay; @@ -196,10 +164,8 @@ NostrRelay *NostrPool::ensureRelay(NostrString url) { void NostrPool::disconnectRelay(NostrString url) { - for (int i = 0; i < this->relays.size(); i++) - { - if (NostrString_equals(this->relays[i]->url, url)) - { + for (int i = 0; i < this->relays.size(); i++) { + if (NostrString_equals(this->relays[i]->url, url)) { this->relays[i]->conn->disconnect(); delete this->relays[i]; this->relays.erase(this->relays.begin() + i); @@ -208,33 +174,28 @@ void NostrPool::disconnectRelay(NostrString url) { } } -void NostrPool::close() -{ +void NostrPool::close() { Utils::log("Closing NostrPool"); - for (auto &relay : relays) - { + for (auto &relay : relays) { relay->conn->disconnect(); delete relay; } relays.clear(); } -void NostrPool::publish(std::initializer_list rs, - SignedNostrEvent *event, - NostrEventStatusCallback statusCallback) { +void NostrPool::publish(std::initializer_list rs, SignedNostrEvent *event, NostrEventStatusCallback statusCallback) { JsonDocument doc; JsonArray ev = doc.add(); event->toSendableEvent(ev); NostrString evJson; serializeJson(ev, evJson); doc.clear(); - for (auto &r : rs) - { + for (auto &r : rs) { NostrRelay *relay = this->ensureRelay(r); Utils::log("Sending event to relay: " + r + " with payload: " + evJson); relay->send(evJson); } - if (statusCallback){ + if (statusCallback) { EventStatusCallbackEntry entry; entry.statusCallback = statusCallback; entry.timestampSeconds = Utils::unixTimeSeconds(); @@ -242,32 +203,29 @@ void NostrPool::publish(std::initializer_list rs, this->eventStatusCallbackEntries.push_back(entry); } } -void NostrPool::loop() -{ - if(!this->transport->isReady()){ - return; - } - for (auto &relay : relays) - { +void NostrPool::loop() { + if (!this->transport->isReady()) { + return; + } + for (auto &relay : relays) { relay->conn->loop(); relay->processQueue(); } // remove expired callback entries long long now = Utils::unixTimeSeconds(); - for(int i=0;ieventStatusCallbackEntries.size();i++){ + for (int i = 0; i < this->eventStatusCallbackEntries.size(); i++) { EventStatusCallbackEntry entry = this->eventStatusCallbackEntries[i]; - if (now - entry.timestampSeconds > this->eventStatusTimeoutSeconds){ - this->eventStatusCallbackEntries.erase(this->eventStatusCallbackEntries.begin()+i); + if (now - entry.timestampSeconds > this->eventStatusTimeoutSeconds) { + this->eventStatusCallbackEntries.erase(this->eventStatusCallbackEntries.begin() + i); i--; } } } -std::vector NostrPool::getRelays(){ +std::vector NostrPool::getRelays() { std::vector urls; - for (auto &r : this->relays) - { + for (auto &r : this->relays) { urls.push_back(r->url); } return urls; diff --git a/src/NostrString.cpp b/src/NostrString.cpp index 3488ee5..772d754 100644 --- a/src/NostrString.cpp +++ b/src/NostrString.cpp @@ -3,18 +3,22 @@ #include #include #ifdef ARDUINO -# include -# include -# define NostrString String -long NostrString_toInt(const String& str) { return str.toInt(); } -String NostrString_fromChars(char* chars) { return String(chars); } -bool NostrString_startsWith(const String& str, const char* prefix) { +#include +#include +#define NostrString String +long NostrString_toInt(const String &str) { + return str.toInt(); +} +String NostrString_fromChars(char *chars) { + return String(chars); +} +bool NostrString_startsWith(const String &str, const char *prefix) { return str.startsWith(prefix); } -String NostrString_substring(const String& str, int start, int end) { +String NostrString_substring(const String &str, int start, int end) { return str.substring(start, end); } -String NostrString_substring(const String& str, int start) { +String NostrString_substring(const String &str, int start) { return str.substring(start); } @@ -22,9 +26,7 @@ String NostrString_fromUInt(unsigned long long i) { return String(i); } - void - NostrString_split(const String& str, const char separator, - std::vector& result) { +void NostrString_split(const String &str, const char separator, std::vector &result) { int startIndex = 0; for (int i = 0; i <= str.length(); ++i) { @@ -32,13 +34,12 @@ String NostrString_fromUInt(unsigned long long i) { // Extract the substring from startIndex to i String substring = str.substring(startIndex, i); result.push_back(substring); - startIndex = - i + 1; // Move startIndex to the character after the separator + startIndex = i + 1; // Move startIndex to the character after the separator } } } -String NostrString_urlDecode(const String& encoded) { +String NostrString_urlDecode(const String &encoded) { String decoded = ""; for (int i = 0; i < encoded.length(); i++) { char ch = encoded.charAt(i); @@ -48,7 +49,7 @@ String NostrString_urlDecode(const String& encoded) { String hexStr = encoded.substring(i + 1, i + 3); char hexChar = (char)strtol(hexStr.c_str(), NULL, 16); decoded += hexChar; - i += 2; + i += 2; } else { decoded += ch; } @@ -56,41 +57,49 @@ String NostrString_urlDecode(const String& encoded) { return decoded; } -String NostrString_intToString(long int i) { return String(i); } -int NostrString_indexOf(const String& str1, const char* str2) { +String NostrString_intToString(long int i) { + return String(i); +} +int NostrString_indexOf(const String &str1, const char *str2) { return str1.indexOf(str2); } -void NostrString_hexToBytes(const String& hex, uint8_t* array, size_t arraySize) { +void NostrString_hexToBytes(const String &hex, uint8_t *array, size_t arraySize) { fromHex(hex, array, arraySize); } -String NostrString_bytesToHex(uint8_t* array, size_t arraySize) { +String NostrString_bytesToHex(uint8_t *array, size_t arraySize) { return toHex(array, arraySize); } -long int NostrString_length(const String& str) { return str.length(); } +long int NostrString_length(const String &str) { + return str.length(); +} -const char* NostrString_toChars(const String& str) { return str.c_str(); } +const char *NostrString_toChars(const String &str) { + return str.c_str(); +} -String NostrString_base64ToHex(const String& b64) { return base64ToHex(b64); } +String NostrString_base64ToHex(const String &b64) { + return base64ToHex(b64); +} -String NostrString_trim(const String& s) { - String ss=s; - ss.trim(); - for(int i=0;i 126; - }), - ss.end()); + ss.erase(std::remove_if(ss.begin(), ss.end(), [](unsigned char c) { return std::isspace(c) || c < 32 || c > 126; }), ss.end()); return ss; } -void NostrString_split(const std::string& str, const char separator, std::vector& result) { +void NostrString_split(const std::string &str, const char separator, std::vector &result) { std::string token; std::istringstream tokenStream(str); - while (std::getline(tokenStream, token, separator)) - { + while (std::getline(tokenStream, token, separator)) { result.push_back(token); } } -std::string NostrString_urlDecode(const std::string& encoded) { +std::string NostrString_urlDecode(const std::string &encoded) { std::string decoded = ""; for (int i = 0; i < encoded.length(); i++) { char ch = encoded[i]; @@ -193,7 +206,7 @@ std::string NostrString_urlDecode(const std::string& encoded) { std::string hexStr = encoded.substr(i + 1, 2); char hexChar = (char)strtol(hexStr.c_str(), NULL, 16); decoded += hexChar; - i += 2; + i += 2; } else { decoded += ch; } @@ -203,7 +216,7 @@ std::string NostrString_urlDecode(const std::string& encoded) { std::string NostrString_fromUInt(unsigned long long i) { return std::to_string(i); } -std::string NostrString_urlEncode(const std::string& str) { +std::string NostrString_urlEncode(const std::string &str) { std::string encoded = ""; for (int i = 0; i < str.length(); i++) { char ch = str[i]; diff --git a/src/NostrString.h b/src/NostrString.h index d9e2b9c..47f5c68 100644 --- a/src/NostrString.h +++ b/src/NostrString.h @@ -4,63 +4,59 @@ #include #include #ifdef ARDUINO -# include -# include -# define NostrString String -long NostrString_toInt(const String& str); -String NostrString_fromChars(char* chars); -bool NostrString_startsWith(const String& str, const char* prefix); - -String NostrString_substring(const String& str, int start, int end); -String NostrString_substring(const String& str, int start); +#include +#include +#define NostrString String +long NostrString_toInt(const String &str); +String NostrString_fromChars(char *chars); +bool NostrString_startsWith(const String &str, const char *prefix); + +String NostrString_substring(const String &str, int start, int end); +String NostrString_substring(const String &str, int start); String NostrString_intToString(long int i); -int NostrString_indexOf(const String& str1, const char* str2); -void NostrString_hexToBytes(const String& hex, uint8_t* array, - size_t arraySize); -String NostrString_bytesToHex(uint8_t* array, size_t arraySize); -String NostrString_urlDecode(const String& encoded) ; -long int NostrString_length(const String& str); -bool NostrString_equals(const String& str1, const String& str2); +int NostrString_indexOf(const String &str1, const char *str2); +void NostrString_hexToBytes(const String &hex, uint8_t *array, size_t arraySize); +String NostrString_bytesToHex(uint8_t *array, size_t arraySize); +String NostrString_urlDecode(const String &encoded); +long int NostrString_length(const String &str); +bool NostrString_equals(const String &str1, const String &str2); - const char* NostrString_toChars(const String& str); +const char *NostrString_toChars(const String &str); - String NostrString_base64ToHex(const String& b64); +String NostrString_base64ToHex(const String &b64); - String NostrString_trim(const String& s); - void NostrString_split(const String& str, const char separator, - std::vector& result); - String NostrString_fromUInt(unsigned long long i); - String NostrString_urlEncode(const String& str); +String NostrString_trim(const String &s); +void NostrString_split(const String &str, const char separator, std::vector &result); +String NostrString_fromUInt(unsigned long long i); +String NostrString_urlEncode(const String &str); #else -# define NostrString std::string -long NostrString_toInt(const std::string &str); +#define NostrString std::string +long NostrString_toInt(const std::string &str); std::string NostrString_fromChars(char *chars); -bool NostrString_startsWith(const std::string& str, const char* prefix); +bool NostrString_startsWith(const std::string &str, const char *prefix); -std::string NostrString_substring(const std::string& str, int start, int end); +std::string NostrString_substring(const std::string &str, int start, int end); -std::string NostrString_substring(const std::string &str, int start); +std::string NostrString_substring(const std::string &str, int start); - std::string NostrString_intToString(long int i); -int NostrString_indexOf(const std::string &str1, const char* str2); +int NostrString_indexOf(const std::string &str1, const char *str2); -void NostrString_hexToBytes(const std::string &hex, uint8_t *array, size_t arraySize); +void NostrString_hexToBytes(const std::string &hex, uint8_t *array, size_t arraySize); std::string NostrString_bytesToHex(uint8_t *array, size_t arraySize); -long int NostrString_length(const std::string& str); -const char *NostrString_toChars(const std::string& str); +long int NostrString_length(const std::string &str); +const char *NostrString_toChars(const std::string &str); -std::string NostrString_base64ToHex(const std::string& b64); -std::string NostrString_trim(const std::string& s); -void NostrString_split(const std::string& str, const char separator, - std::vector& result) ; -std::string NostrString_urlDecode(const std::string& encoded) ; +std::string NostrString_base64ToHex(const std::string &b64); +std::string NostrString_trim(const std::string &s); +void NostrString_split(const std::string &str, const char separator, std::vector &result); +std::string NostrString_urlDecode(const std::string &encoded); -bool NostrString_equals(const std::string& str1, const std::string& str2); +bool NostrString_equals(const std::string &str1, const std::string &str2); std::string NostrString_fromUInt(unsigned long long i); -std::string NostrString_urlEncode(const std::string& str); +std::string NostrString_urlEncode(const std::string &str); #endif #endif \ No newline at end of file diff --git a/src/Transport.h b/src/Transport.h index f44cc4c..a21b51d 100644 --- a/src/Transport.h +++ b/src/Transport.h @@ -1,31 +1,27 @@ #ifndef _NOSTR_TRANSPORT_H -#define _NOSTR_TRANSPORT_H +#define _NOSTR_TRANSPORT_H #include "NostrString.h" -namespace nostr{ +namespace nostr { class Connection { - public: - virtual void addMessageListener(std::function listener) ; - virtual void send(NostrString message) = 0; - virtual void disconnect() = 0; - virtual ~Connection() = default; - virtual void loop() = 0; - virtual bool isReady() = 0; - + public: + virtual void addMessageListener(std::function listener); + virtual void send(NostrString message) = 0; + virtual void disconnect() = 0; + virtual ~Connection() = default; + virtual void loop() = 0; + virtual bool isReady() = 0; }; class Transport { - public: - virtual NostrString getInvoiceFromLNAddr(NostrString addr, - unsigned long long amountMSats, - NostrString comment = "") = 0; - virtual Connection *connect(NostrString url) = 0; + public: + virtual NostrString getInvoiceFromLNAddr(NostrString addr, unsigned long long amountMSats, NostrString comment = "") = 0; + virtual Connection *connect(NostrString url) = 0; virtual ~Transport() = default; Transport() = default; virtual void disconnect(Connection *conn) = 0; virtual bool isReady() = 0; virtual void close() = 0; - }; -} +} // namespace nostr #endif \ No newline at end of file diff --git a/src/Utils.cpp b/src/Utils.cpp index 8dea958..27057e4 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -6,12 +6,10 @@ std::function Utils::logger = nullptr; unsigned long long Utils::subs = 0; std::function Utils::realRandom = nullptr; std::function Utils::timeSecondsProvider = nullptr; -void Utils::setUnixTimeSecondsProvider( - std::function timeSecondsProvider) { +void Utils::setUnixTimeSecondsProvider(std::function timeSecondsProvider) { Utils::timeSecondsProvider = timeSecondsProvider; } -void Utils::setRealRandom( - std::function realRandom) { +void Utils::setRealRandom(std::function realRandom) { Utils::realRandom = realRandom; } void Utils::setLogger(std::function logger) { @@ -31,9 +29,8 @@ long long Utils::unixTimeSeconds() { } NostrString Utils::getNewSubscriptionId() { - NostrString chars = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345" - "6789"; + NostrString chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345" + "6789"; NostrString result = ""; result += NostrString_intToString(subs++); int maxLength = 64; @@ -44,7 +41,6 @@ NostrString Utils::getNewSubscriptionId() { return result; } - long int Utils::randomInt(long int min, long int max) { if (!realRandom) { Utils::log("No random function set"); diff --git a/src/Utils.h b/src/Utils.h index 9ec2292..be1f0d5 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -10,32 +10,31 @@ #include "NostrString.h" #define NOSTR_DIGEST_SIZE 32 -namespace nostr{ - - class Utils{ - public: - static std::function logger; - static unsigned long long subs; - static std::function realRandom; - static std::function timeSecondsProvider; - - static void setUnixTimeSecondsProvider(std::function timeSecondsProvider); - static void setRealRandom(std::function realRandom); - static void setLogger(std::function logger); - static void log(const NostrString &message); - static long long unixTimeSeconds(); - - static NostrString getNewSubscriptionId(); - - /** - * Generate a random 32-byte value between min and max (inclusive) - * - */ - static long int randomInt(long int min, long int max); - - static NostrString getPublicKey(NostrString privKeyHex); - }; -} - +namespace nostr { + +class Utils { + public: + static std::function logger; + static unsigned long long subs; + static std::function realRandom; + static std::function timeSecondsProvider; + + static void setUnixTimeSecondsProvider(std::function timeSecondsProvider); + static void setRealRandom(std::function realRandom); + static void setLogger(std::function logger); + static void log(const NostrString &message); + static long long unixTimeSeconds(); + + static NostrString getNewSubscriptionId(); + + /** + * Generate a random 32-byte value between min and max (inclusive) + * + */ + static long int randomInt(long int min, long int max); + + static NostrString getPublicKey(NostrString privKeyHex); +}; +} // namespace nostr #endif \ No newline at end of file diff --git a/src/esp32/ESP32Transport.cpp b/src/esp32/ESP32Transport.cpp index c27d185..c502625 100644 --- a/src/esp32/ESP32Transport.cpp +++ b/src/esp32/ESP32Transport.cpp @@ -1,11 +1,8 @@ #include "ESP32Transport.h" - using namespace nostr; -NostrString esp32::ESP32Transport::getInvoiceFromLNAddr(NostrString addr, - unsigned long long amount, - NostrString comment) { +NostrString esp32::ESP32Transport::getInvoiceFromLNAddr(NostrString addr, unsigned long long amount, NostrString comment) { // username@domain.com // becomes https://domain.com/.well-known/lnurlp/username unsigned int atpos = NostrString_indexOf(addr, "@"); @@ -14,13 +11,13 @@ NostrString esp32::ESP32Transport::getInvoiceFromLNAddr(NostrString addr, } NostrString username = NostrString_substring(addr, 0, atpos); NostrString domain = NostrString_substring(addr, atpos + 1); - NostrString url = "https://" + domain + "/.well-known/lnurlp/" + - NostrString_urlEncode(username); + NostrString url = "https://" + domain + "/.well-known/lnurlp/" + NostrString_urlEncode(username); HTTPClient http; http.begin(url.c_str()); int httpCode = http.GET(); - if (httpCode <= 0 || httpCode != HTTP_CODE_OK) return ""; + if (httpCode <= 0 || httpCode != HTTP_CODE_OK) + return ""; NostrString json = http.getString(); JsonDocument doc; DeserializationError error = deserializeJson(doc, json); @@ -52,11 +49,12 @@ NostrString esp32::ESP32Transport::getInvoiceFromLNAddr(NostrString addr, http.end(); http.begin(lnurlp.c_str()); httpCode = http.GET(); - if (httpCode <= 0 || httpCode != HTTP_CODE_OK) return ""; - json=http.getString(); + if (httpCode <= 0 || httpCode != HTTP_CODE_OK) + return ""; + json = http.getString(); error = deserializeJson(doc, json); if (error) { - Utils::log("Failed to parse lnurlp JSON "+json); + Utils::log("Failed to parse lnurlp JSON " + json); return ""; } NostrString callbackStatus = doc["status"]; @@ -74,7 +72,7 @@ NostrString esp32::ESP32Transport::getInvoiceFromLNAddr(NostrString addr, } Connection *esp32::ESP32Transport::connect(NostrString url) { - ESP32Connection *conn = new ESP32Connection(this,url); + ESP32Connection *conn = new ESP32Connection(this, url); connections.push_back(conn); return conn; } @@ -98,54 +96,49 @@ void esp32::ESP32Transport::disconnect(Connection *conn) { } } -esp32::ESP32Connection::ESP32Connection(ESP32Transport *transport, - NostrString url) { - this->transport=transport; +esp32::ESP32Connection::ESP32Connection(ESP32Transport *transport, NostrString url) { + this->transport = transport; bool ssl = NostrString_startsWith(url, "wss://"); url = NostrString_substring(url, ssl ? 6 : 5); - NostrString host = - NostrString_substring(url, 0, NostrString_indexOf(url, "/")); - NostrString path = - NostrString_substring(url, NostrString_indexOf(url, "/")); - if (path.equals("")) path = "/"; + NostrString host = NostrString_substring(url, 0, NostrString_indexOf(url, "/")); + NostrString path = NostrString_substring(url, NostrString_indexOf(url, "/")); + if (path.equals("")) + path = "/"; int port = ssl ? 443 : 80; if (NostrString_indexOf(host, ":") != -1) { - NostrString portStr = - NostrString_substring(host, NostrString_indexOf(host, ":") + 1); + NostrString portStr = NostrString_substring(host, NostrString_indexOf(host, ":") + 1); port = NostrString_toInt(portStr); host = NostrString_substring(host, 0, NostrString_indexOf(host, ":")); } if (ssl) { - Utils::log("Connecting to " + host + " : " + port + " with path " + - path + " using SSL..."); + Utils::log("Connecting to " + host + " : " + port + " with path " + path + " using SSL..."); ws.beginSSL(host, port, path); } else { - Utils::log("Connecting to " + host + " : " + port + " with path " + - path + "..."); + Utils::log("Connecting to " + host + " : " + port + " with path " + path + "..."); ws.begin(host, port, path); } ws.setReconnectInterval(5000); ws.onEvent([this](WStype_t type, uint8_t *payload, size_t length) { switch (type) { - case WStype_DISCONNECTED: - Utils::log("ESP32Connection disconnected."); - break; - case WStype_CONNECTED: - Utils::log("ESP32Connection connected."); - break; - case WStype_TEXT: { - NostrString message = NostrString_fromChars((char *)payload); - for (auto &listener : messageListeners) { - listener(message); - } - - break; + case WStype_DISCONNECTED: + Utils::log("ESP32Connection disconnected."); + break; + case WStype_CONNECTED: + Utils::log("ESP32Connection connected."); + break; + case WStype_TEXT: { + NostrString message = NostrString_fromChars((char *)payload); + for (auto &listener : messageListeners) { + listener(message); } - case WStype_ERROR: - Utils::log("ESP32Connection error."); - break; - default: - break; + + break; + } + case WStype_ERROR: + Utils::log("ESP32Connection error."); + break; + default: + break; } }); } @@ -164,18 +157,23 @@ bool esp32::ESP32Transport::isReady() { } void esp32::ESP32Connection::loop() { - ws.loop(); + ws.loop(); } -bool esp32::ESP32Connection::isReady() { return ws.isConnected(); } +bool esp32::ESP32Connection::isReady() { + return ws.isConnected(); +} -void esp32::ESP32Connection::addMessageListener( - std::function listener) { +void esp32::ESP32Connection::addMessageListener(std::function listener) { messageListeners.push_back(listener); } -esp32::ESP32Transport::~ESP32Transport() { close(); } +esp32::ESP32Transport::~ESP32Transport() { + close(); +} -esp32::ESP32Connection::~ESP32Connection() { ws.disconnect(); } +esp32::ESP32Connection::~ESP32Connection() { + ws.disconnect(); +} esp32::ESP32Transport::ESP32Transport() {} \ No newline at end of file diff --git a/src/esp32/ESP32Transport.h b/src/esp32/ESP32Transport.h index daa4f4e..c6399d0 100644 --- a/src/esp32/ESP32Transport.h +++ b/src/esp32/ESP32Transport.h @@ -9,42 +9,41 @@ #include "Utils.h" #include "WiFi.h" namespace nostr { - namespace esp32{ - class ESP32Transport; - class ESP32Connection : public Connection { - friend class ESP32Transport; - public: - void send(NostrString message) override; - void disconnect() override; - void loop() override; - bool isReady() override; - void addMessageListener( - std::function listener) override; - ~ESP32Connection() override; - protected: - ESP32Connection(ESP32Transport *transport, NostrString url); +namespace esp32 { +class ESP32Transport; +class ESP32Connection : public Connection { + friend class ESP32Transport; - private: - ESP32Transport *transport; - WebSocketsClient ws; - std::vector> messageListeners; - }; - class ESP32Transport : public Transport { - public: - NostrString getInvoiceFromLNAddr(NostrString addr, - unsigned long long amount, - NostrString comment = "") override; - Connection *connect(NostrString url) override; - void close(); - void disconnect(Connection *conn) override; - ~ESP32Transport() override; - ESP32Transport(); - bool isReady() override; + public: + void send(NostrString message) override; + void disconnect() override; + void loop() override; + bool isReady() override; + void addMessageListener(std::function listener) override; + ~ESP32Connection() override; - private: - std::vector connections; - }; - } -} // namespace nostr + protected: + ESP32Connection(ESP32Transport *transport, NostrString url); + + private: + ESP32Transport *transport; + WebSocketsClient ws; + std::vector> messageListeners; +}; +class ESP32Transport : public Transport { + public: + NostrString getInvoiceFromLNAddr(NostrString addr, unsigned long long amount, NostrString comment = "") override; + Connection *connect(NostrString url) override; + void close(); + void disconnect(Connection *conn) override; + ~ESP32Transport() override; + ESP32Transport(); + bool isReady() override; + + private: + std::vector connections; +}; +} // namespace esp32 +} // namespace nostr #endif diff --git a/src/services/NWC.cpp b/src/services/NWC.cpp index d32c6b6..69653c9 100644 --- a/src/services/NWC.cpp +++ b/src/services/NWC.cpp @@ -7,36 +7,36 @@ NWC::~NWC() { this->close(); } -NWC::NWC( Transport* transport, NostrString nwcUrl){ +NWC::NWC(Transport *transport, NostrString nwcUrl) { this->pool = std::unique_ptr(new NostrPool(transport)); Nip47::parseNWC(nwcUrl, this->nwc); - Utils::log("NWC RELAY: "+this->nwc.relay); + Utils::log("NWC RELAY: " + this->nwc.relay); Utils::log("NWC PUBKEY: " + this->nwc.pubkey); Utils::log("NWC PRIVKEY: ******"); - NostrString accountSecret=this->nwc.secret; + NostrString accountSecret = this->nwc.secret; this->nip47 = Nip47(Nip04(), this->nwc.pubkey, accountSecret); this->accountPubKey = Utils::getPublicKey(accountSecret); } -void NWC::close(){ +void NWC::close() { this->pool->close(); this->callbacks.clear(); } - + void NWC::loop() { this->pool->loop(); // maintain callbacks for (auto it = this->callbacks.begin(); it != this->callbacks.end();) { - if(it->get()->n == 0) { + if (it->get()->n == 0) { NostrString subId = it->get()->subId; this->pool->closeSubscription(subId); it = this->callbacks.erase(it); continue; } - if (Utils::unixTimeSeconds() - it->get()->timestampSeconds > 60*10) { + if (Utils::unixTimeSeconds() - it->get()->timestampSeconds > 60 * 10) { NostrString subId = it->get()->subId; this->pool->closeSubscription(subId); it->get()->onErr("OTHER", "timeout"); @@ -49,15 +49,10 @@ void NWC::loop() { NostrString NWC::sendEvent(SignedNostrEvent *event) { NostrString subId = this->pool->subscribeMany( - {this->nwc.relay}, - {{ - {"kinds", {"23195"}}, - {"#p",{this->accountPubKey}}, - {"#e",{event->getId()}} - }}, + {this->nwc.relay}, {{{"kinds", {"23195"}}, {"#p", {this->accountPubKey}}, {"#e", {event->getId()}}}}, [&](const String &subId, nostr::SignedNostrEvent *event) { NostrString eventRef = event->getTags()->getTag("e")[0]; - for (auto it = this->callbacks.begin(); it != this->callbacks.end();it++) { + for (auto it = this->callbacks.begin(); it != this->callbacks.end(); it++) { if (NostrString_equals(it->get()->eventId, eventRef)) { if (it->get()->n > 0) { it->get()->call(&this->nip47, event); @@ -69,32 +64,21 @@ NostrString NWC::sendEvent(SignedNostrEvent *event) { } } }, - [&](const String &subId, const String &reason) { - Utils::log("NWC: closed subscription: " + reason); - }, - [&](const String &subId) { Utils::log("NWC: EOS"); }); - this->pool->publish( - {this->nwc.relay}, event, - [&](const NostrString &eventId, bool status, const NostrString &msg) { - if(!status){ - Utils::log("NWC: error sending event: "+msg); - }else{ - Utils::log("NWC: event sent: "+eventId); - } - }); + [&](const String &subId, const String &reason) { Utils::log("NWC: closed subscription: " + reason); }, [&](const String &subId) { Utils::log("NWC: EOS"); }); + this->pool->publish({this->nwc.relay}, event, [&](const NostrString &eventId, bool status, const NostrString &msg) { + if (!status) { + Utils::log("NWC: error sending event: " + msg); + } else { + Utils::log("NWC: event sent: " + eventId); + } + }); return subId; } - - -void NWC::payInvoice( - NostrString invoice, unsigned long amount, - std::function onRes, - std::function onErr) { +void NWC::payInvoice(NostrString invoice, unsigned long amount, std::function onRes, std::function onErr) { SignedNostrEvent ev = this->nip47.payInvoice(invoice, amount); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -104,12 +88,9 @@ void NWC::payInvoice( this->callbacks.push_back(std::move(callback)); } -void NWC::multiPayInvoice(std::initializer_list invoices, - std::function onRes, - std::function onErr) { +void NWC::multiPayInvoice(std::initializer_list invoices, std::function onRes, std::function onErr) { SignedNostrEvent ev = this->nip47.multiPayInvoice(invoices); - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; @@ -120,15 +101,11 @@ void NWC::multiPayInvoice(std::initializer_list invoices, this->callbacks.push_back(std::move(callback)); } -void NWC::payKeySend(NostrString pubkey, unsigned long amount, - NostrString preimage, - std::initializer_list tlv, - std::function onRes, - std::function onErr) { +void NWC::payKeySend(NostrString pubkey, unsigned long amount, NostrString preimage, std::initializer_list tlv, std::function onRes, + std::function onErr) { SignedNostrEvent ev = this->nip47.payKeySend(pubkey, amount, preimage, tlv); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -139,13 +116,10 @@ void NWC::payKeySend(NostrString pubkey, unsigned long amount, this->callbacks.push_back(std::move(callback)); } -void NWC::multiPayKeySend(std::initializer_list keySends, - std::function onRes, - std::function onErr) { +void NWC::multiPayKeySend(std::initializer_list keySends, std::function onRes, std::function onErr) { SignedNostrEvent ev = this->nip47.multiPayKeySend(keySends); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -155,14 +129,10 @@ void NWC::multiPayKeySend(std::initializer_list keySends, // this->callbacks.push_back(callback); } -void NWC::makeInvoice(unsigned long amount, NostrString description, - NostrString descriptionHash, unsigned long expiry, - std::function onRes, - std::function onErr) { - SignedNostrEvent ev = - this->nip47.makeInvoice(amount, description, descriptionHash, expiry); - std::unique_ptr> callback( - new NWCResponseCallback()); +void NWC::makeInvoice(unsigned long amount, NostrString description, NostrString descriptionHash, unsigned long expiry, std::function onRes, + std::function onErr) { + SignedNostrEvent ev = this->nip47.makeInvoice(amount, description, descriptionHash, expiry); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -171,16 +141,12 @@ void NWC::makeInvoice(unsigned long amount, NostrString description, callback->subId = this->sendEvent(&ev); // this->callbacks.push_back(callback); this->callbacks.push_back(std::move(callback)); - } -void NWC::lookUpPaymentHash(NostrString paymentHash, - std::function onRes, - std::function onErr) { +void NWC::lookUpPaymentHash(NostrString paymentHash, std::function onRes, std::function onErr) { SignedNostrEvent ev = this->nip47.lookUpPaymentHash(paymentHash); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -191,13 +157,10 @@ void NWC::lookUpPaymentHash(NostrString paymentHash, this->callbacks.push_back(std::move(callback)); } -void NWC::lookUpInvoice(NostrString invoice, - std::function onRes, - std::function onErr) { +void NWC::lookUpInvoice(NostrString invoice, std::function onRes, std::function onErr) { SignedNostrEvent ev = this->nip47.lookUpInvoice(invoice); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -208,14 +171,11 @@ void NWC::lookUpInvoice(NostrString invoice, this->callbacks.push_back(std::move(callback)); } -void NWC::listTransactions(unsigned long from, unsigned long until, int limit, - int offset, bool unpaid, NostrString type, - std::function onRes, - std::function onErr) { +void NWC::listTransactions(unsigned long from, unsigned long until, int limit, int offset, bool unpaid, NostrString type, std::function onRes, + std::function onErr) { SignedNostrEvent ev = this->nip47.listTransactions(from, until); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -226,12 +186,10 @@ void NWC::listTransactions(unsigned long from, unsigned long until, int limit, this->callbacks.push_back(std::move(callback)); } -void NWC::getBalance(std::function onRes, - std::function onErr) { +void NWC::getBalance(std::function onRes, std::function onErr) { SignedNostrEvent ev = this->nip47.getBalance(); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); @@ -242,12 +200,10 @@ void NWC::getBalance(std::function onRes, this->callbacks.push_back(std::move(callback)); } -void NWC::getInfo(std::function onRes, - std::function onErr) { +void NWC::getInfo(std::function onRes, std::function onErr) { SignedNostrEvent ev = this->nip47.getInfo(); // NWCResponseCallback callback; - std::unique_ptr> callback( - new NWCResponseCallback()); + std::unique_ptr> callback(new NWCResponseCallback()); callback->onRes = onRes; callback->onErr = onErr; callback->timestampSeconds = Utils::unixTimeSeconds(); diff --git a/src/services/NWC.h b/src/services/NWC.h index dbf486f..86d96e7 100644 --- a/src/services/NWC.h +++ b/src/services/NWC.h @@ -8,103 +8,76 @@ #include "NostrEvent.h" #include "NostrPool.h" #include "NostrString.h" -#include "Utils.h" #include "Transport.h" +#include "Utils.h" namespace nostr { - class NWCResponseCallbackBase { - public: - virtual ~NWCResponseCallbackBase() = default; - virtual void call(Nip47 *nip47, SignedNostrEvent *ev){} - std::function onErr = nullptr; - unsigned long long timestampSeconds; - NostrString eventId; - NostrString subId; - unsigned int n = 1; - }; +class NWCResponseCallbackBase { + public: + virtual ~NWCResponseCallbackBase() = default; + virtual void call(Nip47 *nip47, SignedNostrEvent *ev) {} + std::function onErr = nullptr; + unsigned long long timestampSeconds; + NostrString eventId; + NostrString subId; + unsigned int n = 1; +}; - template - class NWCResponseCallback : public NWCResponseCallbackBase { - public: - void call(Nip47 *nip47,SignedNostrEvent *ev) override { - Nip47Response resp; - nip47->parseResponse(ev,resp); - if (NostrString_length(resp.errorCode)>0) { - if(this->onErr!=nullptr){ - this->onErr(resp.errorCode,resp.errorMessage); - } - } else { - if(this->onRes!=nullptr){ - this->onRes(resp.result); - } +template class NWCResponseCallback : public NWCResponseCallbackBase { + public: + void call(Nip47 *nip47, SignedNostrEvent *ev) override { + Nip47Response resp; + nip47->parseResponse(ev, resp); + if (NostrString_length(resp.errorCode) > 0) { + if (this->onErr != nullptr) { + this->onErr(resp.errorCode, resp.errorMessage); + } + } else { + if (this->onRes != nullptr) { + this->onRes(resp.result); } } - std::function onRes = nullptr; - - }; + } + std::function onRes = nullptr; +}; - class NWC { - public: - ~NWC(); - NWC(Transport* transport,NostrString nwcUrl); - void loop(); - void close(); - void payInvoice(NostrString invoice, - unsigned long amount = static_cast(-1), - std::function onRes = nullptr, - std::function onErr = nullptr); - void multiPayInvoice( - std::initializer_list invoices, - std::function onRes = nullptr, - std::function onErr = nullptr); - void payKeySend(NostrString pubkey, unsigned long amount, - NostrString preimage = "", - std::initializer_list tlv = {}, - std::function onRes = nullptr, - std::function onErr = nullptr); +class NWC { + public: + ~NWC(); + NWC(Transport *transport, NostrString nwcUrl); + void loop(); + void close(); + void payInvoice(NostrString invoice, unsigned long amount = static_cast(-1), std::function onRes = nullptr, + std::function onErr = nullptr); + void multiPayInvoice(std::initializer_list invoices, std::function onRes = nullptr, std::function onErr = nullptr); + void payKeySend(NostrString pubkey, unsigned long amount, NostrString preimage = "", std::initializer_list tlv = {}, std::function onRes = nullptr, + std::function onErr = nullptr); - void multiPayKeySend( - std::initializer_list keySends, - std::function onRes = nullptr, - std::function onErr = nullptr); + void multiPayKeySend(std::initializer_list keySends, std::function onRes = nullptr, std::function onErr = nullptr); - void makeInvoice( - unsigned long amount, NostrString description = "", - NostrString descriptionHash = "", unsigned long expiry = 0, - std::function onRes = nullptr, - std::function onErr = nullptr); + void makeInvoice(unsigned long amount, NostrString description = "", NostrString descriptionHash = "", unsigned long expiry = 0, std::function onRes = nullptr, + std::function onErr = nullptr); - void lookUpPaymentHash( - NostrString paymentHash, - std::function onRes = nullptr, - std::function onErr = nullptr); + void lookUpPaymentHash(NostrString paymentHash, std::function onRes = nullptr, std::function onErr = nullptr); - void lookUpInvoice( - NostrString invoice, - std::function onRes = nullptr, - std::function onErr = nullptr); + void lookUpInvoice(NostrString invoice, std::function onRes = nullptr, std::function onErr = nullptr); - void listTransactions( - unsigned long from = 0, unsigned long until = 0, int limit = 0, - int offset = 0, bool unpaid = false, NostrString type = "", - std::function onRes = nullptr, - std::function onErr = nullptr); + void listTransactions(unsigned long from = 0, unsigned long until = 0, int limit = 0, int offset = 0, bool unpaid = false, NostrString type = "", + std::function onRes = nullptr, std::function onErr = nullptr); - void getBalance(std::function onRes = nullptr, - std::function onErr = nullptr); + void getBalance(std::function onRes = nullptr, std::function onErr = nullptr); - void getInfo(std::function onRes = nullptr, - std::function onErr = nullptr); + void getInfo(std::function onRes = nullptr, std::function onErr = nullptr); - private: - Transport* transport; - NostrString sendEvent(SignedNostrEvent *ev); - std::unique_ptr pool; - NWCData nwc; - Nip47 nip47; - NostrString accountPubKey; - std::vector> callbacks; - }; -} // namespace nostr + private: + Transport *transport; + NostrString sendEvent(SignedNostrEvent *ev); + std::unique_ptr pool; + NWCData nwc; + Nip47 nip47; + NostrString accountPubKey; + std::vector> callbacks; +}; +} // namespace nostr #endif \ No newline at end of file