Michael Stewart

Nostr Series — Part 2: One Object To Rule Them All!

The data model for Nostr is very straightforward, everything on the network is known as an event, from text notes to user information to zaps/tips. While this may initially seem limiting, events are extensible thorough a kind property, which identifies what type of event it is.

Source: Alejo Bernal / Shutterstock.com

NIPs

Any changes or additions to the Nostr protocol are known as NIPs. NIP stands for Nostr Implementation Possibility and exists to promote interoperability. Apart from NIP-01 which describes the protocol, all NIPs are optional. New event types are generally NIPs with specifications defined in the documentation of the codebase. Clients should follow NIP specifications instead of coming up with their own that are not first approved by the developer community, as that would make the implementation incompatible with other clients, which is antithetical to the use of Nostr.

Since Nostr is completely open-source, anyone can submit a pull request for a new NIP to be integrated into the protocol. Existing NIPs on the master branch have been approved and integrated and are free to use for any client.


Events

Here is an example event for a simple text note, of kind 1, which could represent something like a Twitter post:

{
  "id": "4376c65d2f232afbe9b882a35baa4f6fe8667c4e684749af565f981833ed6a65",
  "pubkey": "6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93",
  "created_at": 1673347337,
  "kind": 1,
  "content": "Walled gardens became prisons, and nostr is the first step towards tearing down the prison walls.",
  "tags": [
    ["e", "3da979448d9ba263864c4d6f14984c423a3838364ec255f03c7904b1ae77f206"],
    ["p", "bf2376e17ba4ec269d10fcc996a4746b451152be9031fa48e74553dde5526bce"]
  ],
  "sig": "908a15e46fb4d8675bab026fc230a0e3542bfade63da02d542fb78b2a8513fcd0092619a2c8c1221e581946e0191f2af505dfdf8657a414dbca329186f009262"
}

You can find an up-to-date list of the different event types here.

The following is a brief description for each property of this event:

  • id: Unique ID of the event
  • pubkey: The public key of the user that sent the event (public identifier)
  • created_at: When the event was published
  • kind: As previously mentioned, what type of event this is
  • content: Content for the event, in this case a text note
  • tags: Tags on the event that can be used for links, tagging other users, or referencing other events. NIP-01 defines three standard tags, where e refers to an event, p refers to another user via their pubkey, and a refers to coordinates of an event, including the preferred relay. This specification has been expanded with new tag types, such as hashtags (type t), that of course can be found in later NIPs within the documentation
  • sig: Used by clients to verify that this event did in fact come from the user referenced via the pubkey property

Clients can filter event subscriptions by any property, for example kind, pubkey, tags and created_at. This enables a query like “show me all posts by Michael with the hashtag #bitcoin in the last 7 days”. Through this specification, we can create post feeds, threads through event tags, profile pages or have clients create their own algorithms for data feeds.


Metadata

Another important event kind is metadata, which is utilized for user information, such as name, an about blurb, picture, and nip05 (used for zaps, a little more on that next). To send or subscribe to metadata events, use the kind 0.

The metadata object:

{
  "name": "Michael",
  "about": "Software Engineer",
  "picture": "me.png",
  "nip05": "mikkthemagnificent@getalby.com",
  "other": [{"test_key": "test_value"}]
}

The other property allows the flexibility to add any other additional metadata not defined in NIP-01 or NIP-05.

In order to further support the metadata kind, there is also a specification for optional i tags that can be added to the event to link an identity on twitter, github, mastodon or telegram. This i tag has two parameters, platform:identity and proof, a string or object that verifies that the user owns this identity on that particular platform:

{
  "tags": [
    ["i", "github:semisol", "9721ce4ee4fceb91c9711ca2a6c9a5ab"],
    ["i", "twitter:semisol_public", "1619358434134196225"],
    ["i", "mastodon:bitcoinhackers.org/@semisol", "109775066355589974"]
    ["i", "telegram:1087295469", "nostrdirectory/770"]
  ],
  ...
}

Zaps

A more recent event kind is for zaps, enabling users to tip and transfer value, via the Bitcoin Lightning Network.

NIP-57 introduces two new message types:

  • 9734 for zap requests
  • 9375 for zap receipts

At a high level, clients can zap events (eg. sending a tip to a user for a useful or interesting post) or users via their public key directly, given that the associated user has set up their nip05. We will deep-dive into the particular details of this functionality in a later post.

With all of this, we should now have a decent fundamental understanding of how the Nostr protocol works. The simple yet flexible data model means that the protocol is easily extensible moving forward, and as we can see new event kinds are being added to enable different functionalities such as micropayments and even chess moves.


Further Reading


Like this post and want to support the series? Tip me some sats on lightning at mikkthemagnificent@getalby.com:


5 responses to “Nostr Series — Part 2: One Object To Rule Them All!”

Leave a reply to Nostr Series — Part 4: My First Client – Michael Stewart Cancel reply