Private Messages (NIP-17)

NIP-17 defines an encrypted direct messaging scheme using NIP-44 encryption, NIP-59 seals and gift wraps. See NIP-17 for a detailed description. This scheme is used to send messages between two parties avoiding metadata leaks as in NIP-04 (Encrypted Direct Message).

Rust
    // Sender
    let alice_keys =
        Keys::parse("5c0c523f52a5b6fad39ed2403092df8cebc36318b39383bca6c00808626fab3a")?;
    let alice_client = Client::new(alice_keys);
    alice_client.add_relay(url.clone()).await?;
    alice_client.connect().await;

    // Receiver
    let bob_keys = Keys::parse("nsec1j4c6269y9w0q2er2xjw8sv2ehyrtfxq3jwgdlxj6qfn8z4gjsq5qfvfk99")?;
    let bob_client = Client::new(bob_keys.clone());
    bob_client.add_relay(url.clone()).await?;
    bob_client.connect().await;

    // Initialize subscription on Bob's side before sending the message
    // Limit is set to 0 to get only new events!
    // Timestamp::now() CAN'T be used for gift wrap since the timestamps are tweaked!
    let message_filter = Filter::new()
        .kind(Kind::GiftWrap)
        .pubkey(bob_keys.public_key())
        .limit(0);
    let subscription_id = bob_client.subscribe(vec![message_filter], None).await?;

    // Alice sends private message to Bob
    alice_client.send_private_msg(bob_keys.public_key(), "Hello Bob!".to_string(), None).await?;
    println!("Sent private message to Bob");

    // Bob receives private message
    bob_client.handle_notifications(|notification| async {
        if let RelayPoolNotification::Event { event, .. } = notification {
            if event.kind == Kind::GiftWrap {
                let UnwrappedGift { rumor, sender } = bob_client.unwrap_gift_wrap(&event).await?;
                if rumor.kind == Kind::PrivateDirectMessage {
                    println!("Bob received private message from {sender}: {}", &rumor.content);
                    return Ok(true); // Message received, exit.
                }
            }
        }
        Ok(false)
    }).await?;

    bob_client.unsubscribe(subscription_id.val).await;
Python

TODO

JavaScript

TODO

Kotlin

TODO

Swift

TODO