Nostr client relay

Nostr_client_relay is a Nostr C++ engine that allows to build Nostr applications for command line, desktop or web. It is available on GitHub

JSON

Nostr uses JSON as data format. JSON is a data-interchange format easy for humans to read and write. JSON is built on two structures: a collection of name/value pairs, called an object, and an ordered list of values, called an array (or vector). Object vales can be strings, numbers and a boolean value for true or false.

API

Nostr_client_relay allows an easy integration between C++ objects like strings and vectors and Nostr JSON entities like events and filters, defined in NIP-01 , using the JSON for modern C++ library.

Data structures

A data structure is a storage that is used to store and organize data. Nostr uses the JSON data structures: arrays and objects with string and integer values. An array is a collection of like variables that share a single name. Strings are a sequence of characters, used to store human-readable text, like words. A Nostr event (NIP-01) is defined as

```cpp class event_t { std::string id; std::string pubkey; std::time_t created_at; int kind; std::vector<std::vector<std::string>> tags; std::string content; std::string sig; }; ```

A filter is defined as

```cpp class filter_t { std::vector<std::string> ids; std::vector<std::string> authors; std::vector<int> kinds; std::vector<std::string> e; std::vector<std::string> p; std::time_t since; std::time_t until; size_t limit; }; ```

Functions

Make request

```cpp std::string make_request(const std::string& subscription_id, const filter_t& filter); ```

The function make_request generates the JSON REQ to transmit to a relay. It accepts as input parameters a string with a subscription identifier and a filter. The output (return value of the function) is the JSON as a string.

```cpp const std::string pubkey("4ea843d54a8fdab39aa45f61f19f3ff79cc19385370f6a272dda81fade0a052b"); std::string subscription_id = "my_id"; nostr::filter_t filter; filter.authors.push_back(pubkey); filter.kinds.push_back(1); filter.limit = 1; std::string json = nostr::make_request(subscription_id, filter); ```

The following JSON is generated, where the pubkey was inserted as an item in the filter's authors array.

```json [ "REQ", "my_id", { "authors": [ "4ea843d54a8fdab39aa45f61f19f3ff79cc19385370f6a272dda81fade0a052b" ], "kinds": [ 1 ], "limit": 1 } ] ```

Note: the utility functions json_to_file and from_file can be used to save formatted JSON to a text file and to read it from file.

```cpp std::string json; comm::json_to_file("request.json", json); comm::from_file("request.json", json); ```

Make event

```cpp std::string make_event(nostr::event_t& ev, const std::optional<std::string>& seckey); ```

The function make_event generates the JSON EVENT to transmit to a relay. It accepts as input parameters an event data structure and an optional secret key to sign the event. If no key is supplied, a random key is generated. This function generates:

```cpp std::optional seckey; nostr::event_t ev; ev.content = "hello world"; ev.kind = 1; std::string json = nostr::make_event(ev, seckey); ```

The following JSON is generated

```json [ "EVENT", { "content": "hello world", "created_at": 1688543634, "id": "d4675a05eb2720b44bee08bd7c1131786f2d17ef7c1f35ee69005d5ca3377242", "kind": 1, "pubkey": "e7328fe0f6b936457b0d3fdc0e1a264e8ac80e0416f239009345750609fdc0d8", "sig": "472acc460529a2cf56a4ff45f6726d5aa84ff556635fc56855911ee20f055689c508f05d3c64067e919d4335076e9014f47614cd2e7d5b66ba31d8c19973b21c", "tags": [] } ] ```

Get message type

```cpp Type get_message_type(const std::string& json); ```

The function get_message_type returns an identifier for the kind of Nostr message:

```cpp enum class Type { EVENT, REQ, CLOSE, EOSE, NOTICE, UNKNOWN }; ```

All Nostr messages are JSON arrays, so the identifier (string "EVENT" at array position zero, the first position) is obtained by inspecting array index positions with

```cpp nlohmann::json js_message = nlohmann::json::parse(json); std::string type = js_message.at(0); if (type.compare("EVENT") == 0) { return nostr::Type::EVENT; } ```

Parse request

```cpp int parse_request(const std::string& json, std::string& request_id, nostr::filter_t& filter); ```

The function parse_request is used to parse a request. It has as input parameters the JSON REQ as a string, and a request identifier. The output is a filter on the parameter list with the parsed JSON objects as C++ objects. To read the JSON used above in the function make_request

```cpp std::string json = R"([ "REQ", "34E8C71B-C0FB-4D6D-9CBB-694A091D6A2D", { "authors": [ "4ea843d54a8fdab39aa45f61f19f3ff79cc19385370f6a272dda81fade0a052b" ], "kinds": [ 1 ], "limit": 1 } ])"; std::string request_id; nostr::filter_t filter; nostr::parse_request(json, request_id, filter); std::cout << request_id << std::endl; std::cout << filter.authors.at(0) << std::endl; ```

Note: The functions returns an integer value for success (0) or failure (-1). The function success can be tested with

```cpp if (nostr::parse_request(json, request_id, filter) < 0) { std::cout << "something went wrong"; } ```

Parse relay event

```cpp int parse_relay_event(const std::string& json, std::string& event_id, nostr::event_t& ev); ```

The function parse_relay_event is used to parse an event sent by a relay.

```cpp std::string json = R"([ "EVENT", "34E8C71B-C0FB-4D6D-9CBB-694A091D6A2D", { "content": "https://github.com/pedro-vicente/nostr_client_relay", "created_at": 1686887953, "id": "24d7deac8173f5e7ead51282106728ae39d44aa558ff3c5b3b236bece71684ef", "kind": 1, "pubkey": "4ea843d54a8fdab39aa45f61f19f3ff79cc19385370f6a272dda81fade0a052b", "sig": "14d1b7ea0cd8f4275221c297d0d30f5afe2a87a13b743211ed23bcb5dac095498b2b34f645544e3c956577d6554d812fbf908ccb7857b2e920875046579a105c", "tags": [] } ])"; std::string event_id; nostr::event_t ev; nostr::parse_relay_event(json, event_id, ev); std::cout << event_id << std::endl; std::cout << ev.content << std::endl; ```

Relay to

```cpp relay_to(const std::string& uri, const std::string& json, std::vector<std::string>&& store); ```

The function relay_to is used to send a Nostr message (REQ or EVENT) to a relay and return the responses in a array of strings.

```cpp std::string json = R"([ "REQ", "34E8C71B-C0FB-4D6D-9CBB-694A091D6A2D", { "authors": [ "4ea843d54a8fdab39aa45f61f19f3ff79cc19385370f6a272dda81fade0a052b" ], "kinds": [ 1 ], "limit": 1 } ])"; std::string uri = "nos.lol"; std::vector<std::string>& response; nostr::relay_to(uri, json, response); comm::to_file("response.txt", response); for (int idx = 0; idx < response.size(); idx++) { std::string message = response.at(idx); std::cout << message << std::endl; } ```

The above call returned these 2 messages

```json ["EVENT","34E8C71B-C0FB-4D6D-9CBB-694A091D6A2D",{"content":"API version 1 released. Nostr_client_relay is a Nostr C++ engine that allows to build Nostr applications for command line, desktop or web. https://pedro-vicente.net/nostro.html","created_at":1688194430,"id":"9d05a7d271e63dd47dcda1f7c7058f1ce4c903fd24dfe6fdfd72034a040a9923","kind":1,"pubkey":"4ea843d54a8fdab39aa45f61f19f3ff79cc19385370f6a272dda81fade0a052b","sig":"c0aeca949da8b444f80009c81120b2d0059516c0c324b0d6cf523dfd1a20f78bdceec0324d0d3f9940d74b146d7e2d45b105dddd38658c4b07ec2b37ec89ff12","tags":[]}] ["EOSE","34E8C71B-C0FB-4D6D-9CBB-694A091D6A2D"] ```

Get follows

```cpp int get_follows(const std::string& uri, const std::string& pubkey, std::vector<std::string>& response); ```

The function get_follows is a more elaborated higher level function that returns a list of Nostr accounts followed from a public key input.

```cpp std::vector<std::string>& response; std::string uri = "nos.lol"; const std::string pubkey("4ea843d54a8fdab39aa45f61f19f3ff79cc19385370f6a272dda81fade0a052b"); nostr::get_follows(uri, pubkey, response); comm::to_file("response.txt", response); for (int idx = 0; idx < response.size(); idx++) { std::string message = response.at(idx); std::cout << message << std::endl; } ```

The above call returns messages in the form of EVENTS and EOSE

```json ["EVENT","731E4775-80AF-4819-81D6-F21BF3A1B296",{"content":"that needs to be listed on nostr.watch and then it will appear in NADAR.","created_at":1680047175,"id":"e730f566d2d992af7e8efbc1f48d15d316b5b07feb5274d5a2cb75014c538435","kind":1,"pubkey":"c708943ea349519dcf56b2a5c138fd9ed064ad65ddecae6394eabd87a62f1770","sig":"9704b9087879222c492226ab417de9cce436bb18d3022298f0ee1f076b07817022597a051b6a72cfdf68b52be9dcd2a7654b48d2b2b705d1a820444ad114324a","tags":[["e","f6fd01e5d1ba4fc343b27524e4d602f487a800b9c32cd4a0c2521cfdd348eca8","","root"],["e","404e611879f22c07b80c9e387e4c2c777d75af80d73cef15af98cfe52fed736a","","reply"],["p","d030bd233a1347e510c372b1878e00204b228072814361451623707896435da9"],["p","f4f377146e5f784dd0da0814bd95fa42d0ed7ce000d229299a7e8f95c640966f"]]}] ["EOSE","731E4775-80AF-4819-81D6-F21BF3A1B296"] ```

Last modified:
Home