Relay Message
The backbone of the Nostr network is built on relays rather than application specific centralized databases. Clients use WebSockets as a means to connect to relays and pass relevant data back and forth around the network. In accordance with the protocol base specification (NIP-01) there are 5 main types of messages which relays construct as JSON arrays. This section is concerned with the construction of these message objects using the Relay Message Module.
JSON de/serialization
use nostr_sdk::prelude::*;
pub fn relay_message() -> Result<()> {
// Deserialize from json
let json = r#"["EVENT", "random_string", {"id":"70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5","pubkey":"379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe","created_at":1612809991,"kind":1,"tags":[],"content":"test","sig":"273a9cd5d11455590f4359500bccb7a89428262b96b3ea87a756b770964472f8c3e87f5d5e64d8d2e859a71462a3f477b554565c4f2f326cb01dd7620db71502"}]"#;
let msg = RelayMessage::from_json(json)?;
// Serialize as json
let json = msg.as_json();
println!("{json}");
Ok(())
}
The RelayMessage
class easily handles the construction of the 5 main message types EVENT
, OK
, EOSE
(end of stored events), CLOSED
and NOTICE
.
In the examples below we can utilize the relevant class methods event()
, ok()
, eose()
, closed()
and notice()
, respectively, to create the relay message objects.
Once we have the RelayMessage
objects we can use the as_enum()
or as_json()
methods to present their content.
Note that when using as_enum()
we unlock some additional methods associated with the RelayMessageEnum
class.
These allow for logical tests to be performed to establish the type of message object being assessed (for example, is_ok()
will return a bool result assessing if the object represents an OK
message type).
# Create Event relay message
print(" Event Relay Message:")
message = RelayMessage.event("subscription_ID_abc123", event)
print(f" - Event Message: {message.as_enum().is_event_msg()}")
print(f" - JSON: {message.as_json()}")
# Create event acceptance relay message
print(" Event Acceptance Relay Message:")
message = RelayMessage.ok(event.id(), False, "You have no power here, Gandalf The Grey")
print(f" - Event Acceptance Message: {message.as_enum().is_ok()}")
print(f" - JSON: {message.as_json()}")
# Create End of Stored Events relay message
print(" End of Stored Events Relay Message:")
message = RelayMessage.eose("subscription_ID_abc123")
print(f" - End of Stored Events Message: {message.as_enum().is_end_of_stored_events()}")
print(f" - JSON: {message.as_json()}")
# Create Closed relay message
print(" Closed Relay Message:")
message = RelayMessage.closed("subscription_ID_abc123", "So long and thanks for all the fish")
print(f" - Closed Message: {message.as_enum().is_closed()}")
print(f" - JSON: {message.as_json()}")
# Create Notice relay message
print(" Notice Relay Message:")
message = RelayMessage.notice("You have been served")
print(f" - Notice Message: {message.as_enum().is_notice()}")
print(f" - JSON: {message.as_json()}")
When presented with a relay message object as either a JSON or an instance of the RelayMessageEnum
class we can parse these data using the from_json()
or from_enum()
methods, respectively.
# Parse Messages from JSON and/or Enum
print(" Parse Relay Messages:")
message = RelayMessage.from_json('["NOTICE","You have been served"]')
print(f" - ENUM: {message.as_enum()}")
message = RelayMessage.from_enum(cast(RelayMessageEnum, RelayMessageEnum.NOTICE("You have been served")))
print(f" - JSON: {message.as_json()}")
The RelayMessage
class easily handles the construction of the 5 main message types EVENT
, OK
, EOSE
(end of stored events), CLOSED
and NOTICE
.
In the examples below we can utilize the relevant class methods event()
, ok()
, eose()
, closed()
and notice()
, respectively, to create the relay message objects.
Once we have the RelayMessage
objects we can use the asJson()
method to present their content.
console.log(" Event Relay Message:");
let relayMessage = RelayMessage.event("subscription_ID_abc123", event);
console.log(` - JSON: ${relayMessage.asJson()}`);
console.log(" Event Acceptance Relay Message:");
relayMessage = RelayMessage.ok(event.id, false, "You have no power here, Gandalf The Grey");
console.log(` - JSON: ${relayMessage.asJson()}`);
console.log(" End of Stored Events Relay Message:");
relayMessage = RelayMessage.eose("subscription_ID_abc123");
console.log(` - JSON: ${relayMessage.asJson()}`);
console.log(" Closed Relay Message:");
relayMessage = RelayMessage.closed("subscription_ID_abc123", "So long and thanks for all the fish");
console.log(` - JSON: ${relayMessage.asJson()}`);
console.log(" Notice Relay Message:");
relayMessage = RelayMessage.notice("You have been served");
console.log(` - JSON: ${relayMessage.asJson()}`);
When presented with a relay message object as either a JSON we can parse these data using the fromJson()
method.
console.log(" Parse Relay Message:");
relayMessage = RelayMessage.fromJson('["NOTICE","You have been served"]');
console.log(` - JSON: ${relayMessage.asJson()}`);
TODO
TODO
TODO
Authorization and Count Messages
TODO
As an extension of the relay messaging section of the protocol NIP-42 and NIP-45 introduce two new messaging types AUTH
and COUNT
.
The AUTH
type is designed to facilitate a method by which clients can authenticate with a given relay.
Whereas the COUNT
type offers a method for relays to provide simple counts of events to clients (upon request).
These are constructed in much the same way as the earlier message examples, by using the RelayMessage
class in conjunction with the relevant methods auth()
and count()
.
As before the as_enum()
method can be used to unlock logical test methods (e.g., is_auth()
) associated with these message objects.
# Create Authorization relay message (NIP42)
print(" Auth Relay Message:")
message = RelayMessage.auth("I Challenge You To A Duel! (or some other challenge string)")
print(f" - Auth Message: {message.as_enum().is_auth()}")
print(f" - JSON: {message.as_json()}")
# Create Count relay message (NIP45)
print(" Count Relay Message:")
message = RelayMessage.count("subscription_ID_abc123", 42)
print(f" - Count Message: {message.as_enum().is_count()}")
print(f" - JSON: {message.as_json()}")
As an extension of the relay messaging section of the protocol NIP-42 and NIP-45 introduce two new messaging types AUTH
and COUNT
.
The AUTH
type is designed to facilitate a method by which clients can authenticate with a given relay.
Whereas the COUNT
type offers a method for relays to provide simple counts of events to clients (upon request).
These are constructed in much the same way as the earlier message examples, by using the RelayMessage
class in conjunction with the relevant methods auth()
and count()
.
console.log(" Auth Relay Message:");
relayMessage = RelayMessage.auth("I Challenge You To A Duel! (or some other challenge string)");
console.log(` - JSON: ${relayMessage.asJson()}`);
console.log(" Count Relay Message:");
relayMessage = RelayMessage.count("subscription_ID_abc123", 42);
console.log(` - JSON: ${relayMessage.asJson()}`);
TODO
TODO
TODO
Error Messages
TODO
Finally, the RelayMessageEnum
class also opens up two additional message types NEG_ERR()
and NEG_CODE()
.
These do not form part of the standard protocol specification but do have specific uses when it comes to providing methods by which error messaging (or error codes) can be handled by relays. To construct these we need to first create them as instance of the RelayMessageEnum
class and then pass these into a RelayMessage
object using the from_enum()
method.
# Negative Error Code
print(" Negative Relay Message (code):")
relay_message_neg = RelayMessageEnum.NEG_ERR("subscription_ID_abc123", "404")
message = RelayMessage.from_enum(cast(RelayMessageEnum, relay_message_neg))
print(f" - Negative Error Code: {message.as_enum().is_neg_err()}")
print(f" - JSON: {message.as_json()}")
# Negative Error Message
print(" Negative Relay Message (message):")
relay_message_neg = RelayMessageEnum.NEG_MSG("subscription_ID_abc123", "This is not the message you are looking for")
message = RelayMessage.from_enum(cast(RelayMessageEnum, relay_message_neg))
print(f" - Negative Error Message: {message.as_enum().is_neg_msg()}")
print(f" - JSON: {message.as_json()}")
Not available currently with JavaScript bindings.
TODO
TODO
TODO