NIP-19: bech32-encoded entities

Bech32 encoding is used for the primary purpose of transportability between users/client/applications. In addition to bech-32 encoding of the data a series of prefixes are also used to help easily differentiate between different data objects. npub/nsec for public and private keys, respectively and note for note ids.

Extra metadata may be included when communicating between applications to make cross compatibility more streamlined. These follow a type-length-value structure and have the following possible prefixes: nprofile, nevent, nrelay and naddr.

Rust

For most of these examples you will see that the to_bech32() and from_bech32() methods generally facilitate encoding or decoding objects per the NIP-19 standard.

Public and Private (or secret) keys in npub and nsec formats.

println!("Public keys: {:?}", keys.public_key.to_bech32()?);
println!("Secret key: {:?}", keys.secret_key().to_bech32()?);

Simple note presented in NIP-19 format.

let event =
    EventBuilder::text_note("Hello from Rust Nostr rust Bindings!").sign_with_keys(&keys)?;
println!("Event  : {:?}", event.id.to_bech32()?);

Using the Nip19Profile struct to create a shareable nprofile that includes relay data to help other applications to locate the profile data. This is followed by decoding the event object.

// Create NIP-19 profile including relays data
let relay_url = RelayUrl::parse("wss://relay.damus.io")?;
let relays = vec![relay_url];
let nprofile = Nip19Profile::new(keys.public_key, &relays)?;
println!("Profile (encoded): {}", nprofile.to_bech32()?);
// Decode NIP-19 profile
let decode_nprofile = Nip19Profile::from_bech32(&nprofile.to_bech32()?)?;
println!("NIP-19 profile decoded");
println!("Public key: {}", decode_nprofile.public_key);
for (idx, relay) in decode_nprofile.relays.iter().enumerate() {
    println!("{},{}", idx, relay);
}

Using the Nip19Event struct to create a shareable nevent that includes author and relay data. This is followed by decoding the event object.

// Create NIP-19 event including author and relays data
let nevent = Nip19Event::new(event.id)
    .author(keys.public_key)
    .relays(relays.clone());
let encoded_nevent = nevent.to_bech32()?;
println!("Event (encoded): {}", encoded_nevent);
// Decode NIP-19 event
let decoded_event = Nip19Event::from_bech32(&encoded_nevent)?;
let mut decoded_event_map = HashMap::new();
decoded_event_map.insert("event_id", decoded_event.event_id.to_bech32()?);
decoded_event_map.insert(
    "author",
    match decoded_event.author {
        Some(pub_key) => pub_key.to_bech32()?,
        None => "None".to_string(),
    },
);
decoded_event_map.insert(
    "kind",
    match decoded_event.kind {
        Some(kind) => kind.to_string(),
        None => "None".to_string(),
    },
);
decoded_event_map.insert(
    "relays",
    decoded_event
        .relays
        .iter()
        .map(|r| r.to_string())
        .collect::<Vec<_>>()
        .join(", "),
);

println!("Event (decoded)");
for (key, value) in decoded_event_map {
    println!("{} : {}", key, value)
}

Using the Coordinate struct to generate the coordinates for a replaceable event (in this case Metadata).

// Create NIP-19 coordinate
let kind = Kind::TextNote;
let coord = Coordinate::new(kind, keys.public_key);
let coordinate = Nip19Coordinate::new(coord, &relays)?;
let bech_32_coordinate = coordinate.to_bech32()?;
println!(" Coordinate (encoded): {}", bech_32_coordinate);
// Decode NIP-19 coordinate
let decode_coord = Nip19Coordinate::from_bech32(&bech_32_coordinate)?;
println!("Coordinate (decoded): {:?}", decode_coord);
Python

For most of these examples you will see that the to_bech32() and from_bech32() methods generally facilitate encoding or decoding objects per the NIP-19 standard.

Public and Private (or secret) keys in npub and nsec formats.

print(f" Public key: {keys.public_key().to_bech32()}")
print(f" Secret key: {keys.secret_key().to_bech32()}")

Simple note presented in NIP-19 format.

event = EventBuilder.text_note("Hello from rust-nostr Python bindings!").sign_with_keys(keys)
print(f" Event     : {event.id().to_bech32()}")

Using the Nip19Profile class to create a shareable nprofile that includes relay data to help other applications to locate the profile data.

# Create NIP-19 profile including relays data
relays = ["wss://relay.damus.io"]
nprofile = Nip19Profile(keys.public_key(),relays)
print(f" Profile (encoded): {nprofile.to_bech32()}")

Using the Nip19 class to decode the previously shared profile data. This class helps generalize the decoding process for all NIP-19 objects.

# Decode NIP-19 profile
decode_nprofile = Nip19.from_bech32(nprofile.to_bech32())
print(f" Profile (decoded): {decode_nprofile}")

Using the Nip19Event class to create a shareable nevent that includes author and relay data. This is followed by decoding the event object.

# Create NIP-19 event including author and relays data
nevent = Nip19Event(event.id(), keys.public_key(), kind=None, relays=relays)
print(f" Event (encoded): {nevent.to_bech32()}")
# Decode NIP-19 event
decode_nevent = Nip19.from_bech32(nevent.to_bech32())
print(f" Event (decoded): {decode_nevent}")

Using the Coordinate class to generate the coordinates for a replaceable event (in this case Metadata). This is followed by decoding the object.

# Create NIP-19 coordinate
coord = Coordinate(Kind(0),keys.public_key())
coordinate = Nip19Coordinate(coord, [])
print(f" Coordinate (encoded): {coordinate.to_bech32()}")
# Decode NIP-19 coordinate
decode_coord = Nip19.from_bech32(coordinate.to_bech32())
print(f" Coordinate (decoded): {decode_coord}")
JavaScript

For most of these examples you will see that the toBech32() and fromBech32() methods generally facilitate encoding or decoding objects per the NIP-19 standard.

Public and Private (or secret) keys in npub and nsec formats.

console.log(` Public key: ${keys.publicKey.toBech32()}`);
console.log(` Secret key: ${keys.secretKey.toBech32()}`);

Simple note presented in NIP-19 format.

let event = EventBuilder.textNote("Hello from Rust Nostr JS Bindings!").signWithKeys(keys);
console.log(` Event     : ${event.id.toBech32()}`);

Using the Nip19Profile class to create a shareable nprofile that includes relay data to help other applications to locate the profile data. This is followed by decoding the event object.

// Create NIP-19 profile including relays data
let relays = ["wss://relay.damus.io"];
let nprofile = new Nip19Profile(keys.publicKey, relays);
console.log(` Profile (encoded): ${nprofile.toBech32()}`);
// Decode NIP-19 profile
let decode_nprofile = Nip19Profile.fromBech32(nprofile.toBech32());
console.log(` Profile (decoded): ${decode_nprofile.publicKey().toBech32()}`);

Using the Nip19Event class to create a shareable nevent that includes author and relay data. This is followed by decoding the event object.

// Create NIP-19 event including author and relays data
let nevent = new Nip19Event(event.id, keys.publicKey, undefined, relays);
console.log(` Event (encoded): ${nevent.toBech32()}`);
// Decode NIP-19 event
let decode_nevent = Nip19Event.fromBech32(nevent.toBech32());
console.log(` Event (decoded): ${decode_nevent.eventId().toBech32()}`);

Using the Coordinate class to generate the coordinates for a replaceable event (in this case Metadata). This is followed by decoding the object which uses the parse method.

// Create NIP-19 coordinate
let kind = new Kind(0);
let coord = new Coordinate(kind, keys.publicKey);
let coordinate = new Nip19Coordinate(coord, [])
let bech32Coordinate = coordinate.toBech32();
console.log(` Coordinate (encoded): ${bech32Coordinate}`);
// Decode NIP-19 coordinate
let decode_coord = Nip19Coordinate.fromBech32(bech32Coordinate);
console.log(` Coordinate (decoded): ${decode_coord}`);
Kotlin

TODO

Swift

TODO

Flutter

TODO