Skip to main content

README.md

# Nostr library

[![Hex.pm](https://img.shields.io/hexpm/v/nostr_lib.svg)](https://hex.pm/packages/nostr_lib)
[![Hex Docs](https://img.shields.io/badge/hex-docs-blue.svg)](https://hexdocs.pm/nostr_lib)
[![License](https://img.shields.io/hexpm/l/nostr_lib.svg)](https://github.com/sgiath/nostr-lib/blob/master/LICENSE)

A comprehensive low-level Elixir library implementing the [Nostr protocol](https://nostr.com/).
Provides structures, parsing, serialization, and cryptographic functions for building Nostr
applications.

## Features

- Full event lifecycle: creation, signing, validation, serialization
- Schnorr signature support (secp256k1)
- NIP-44 encryption (versioned encrypted payloads)
- NIP-19 bech32 encoding (npub, nsec, note, nprofile, nevent, naddr)
- NIP-59 gift wrap protocol for private messaging
- WebSocket message protocol handling
- NIP-13 proof-of-work difficulty validation and mining helpers
- NIP-29 relay-based groups helpers
- NIP-77 negentropy wire message handling (`NEG-OPEN`, `NEG-MSG`, `NEG-CLOSE`, `NEG-ERR`)
- NIP-98 HTTP auth event creation and validation
- Subscription filter building

## Installation

Add `nostr_lib` to your dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:nostr_lib, "~> 0.2.1"}
  ]
end
```

## Quick Start

### Create and Sign an Event

```elixir
# Generate or use existing private key (32 bytes hex)
private_key = "your_private_key_hex"

# Create a text note (kind 1)
{:ok, event} = Nostr.Event.Note.create("Hello Nostr!", private_key)

# Serialize for sending to relay
json = Nostr.Event.serialize(event)
```

### Parse Incoming Events

```elixir
# Parse JSON from relay
{:ok, event} = Nostr.Event.parse(json_string)

# Validate event signature
case Nostr.Event.Validator.validate(event) do
  {:ok, event} -> # Valid event
  {:error, reason, event} -> # Invalid
end
```

### Build Subscription Filters

```elixir
# Create a filter for text notes from specific authors
filter = %Nostr.Filter{
  kinds: [1],
  authors: ["pubkey1", "pubkey2"],
  limit: 100
}
```

### Bech32 Encoding

```elixir
# Encode public key as npub
{:ok, npub} = Nostr.Bech32.encode(:npub, pubkey_hex)
# => "npub1..."

# Decode back
{:ok, {:npub, pubkey}} = Nostr.Bech32.decode(npub)
```

## Implemented NIPs

| NIP                                                                | Status     | Description                 | Event Kinds              |
| ------------------------------------------------------------------ | ---------- | --------------------------- | ------------------------ |
| [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) | Full       | Basic protocol              | 0, 1                     |
| [NIP-02](https://github.com/nostr-protocol/nips/blob/master/02.md) | Full       | Follow list                 | 3                        |
| [NIP-03](https://github.com/nostr-protocol/nips/blob/master/03.md) | Full       | OpenTimestamps              | 1040                     |
| [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md) | Deprecated | Encrypted DMs (use NIP-17)  | 4                        |
| [NIP-05](https://github.com/nostr-protocol/nips/blob/master/05.md) | Full       | DNS-based identifiers       | -                        |
| [NIP-09](https://github.com/nostr-protocol/nips/blob/master/09.md) | Full       | Event deletion              | 5                        |
| [NIP-13](https://github.com/nostr-protocol/nips/blob/master/13.md) | Full       | Proof of Work               | -                        |
| [NIP-16](https://github.com/nostr-protocol/nips/blob/master/16.md) | Full       | Event kind ranges           | 1000-39999               |
| [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) | Full       | Private direct messages     | 14, 15, 10050            |
| [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md) | Deprecated | Reposts                     | 6                        |
| [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md) | Full       | Bech32 encoding             | -                        |
| [NIP-21](https://github.com/nostr-protocol/nips/blob/master/21.md) | Full       | nostr: URI scheme           | -                        |
| [NIP-22](https://github.com/nostr-protocol/nips/blob/master/22.md) | Full       | Comments                    | 1111                     |
| [NIP-23](https://github.com/nostr-protocol/nips/blob/master/23.md) | Full       | Long-form content           | 30023, 30024             |
| [NIP-25](https://github.com/nostr-protocol/nips/blob/master/25.md) | Full       | Reactions                   | 7, 17                    |
| [NIP-28](https://github.com/nostr-protocol/nips/blob/master/28.md) | Full       | Public chat channels        | 40-44                    |
| [NIP-29](https://github.com/nostr-protocol/nips/blob/master/29.md) | Partial    | Relay-based groups helpers  | 9000-9022, 39000-39003   |
| [NIP-30](https://github.com/nostr-protocol/nips/blob/master/30.md) | Full       | Custom emoji                | -                        |
| [NIP-32](https://github.com/nostr-protocol/nips/blob/master/32.md) | Full       | Labeling                    | 1985                     |
| [NIP-36](https://github.com/nostr-protocol/nips/blob/master/36.md) | Full       | Sensitive content           | -                        |
| [NIP-37](https://github.com/nostr-protocol/nips/blob/master/37.md) | Full       | Draft events                | 31234                    |
| [NIP-38](https://github.com/nostr-protocol/nips/blob/master/38.md) | Full       | User statuses               | 30315                    |
| [NIP-39](https://github.com/nostr-protocol/nips/blob/master/39.md) | Full       | External identities         | -                        |
| [NIP-42](https://github.com/nostr-protocol/nips/blob/master/42.md) | Full       | Relay authentication        | 22242                    |
| [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md) | Full       | Versioned encryption        | -                        |
| [NIP-45](https://github.com/nostr-protocol/nips/blob/master/45.md) | Partial    | Event counting              | -                        |
| [NIP-49](https://github.com/nostr-protocol/nips/blob/master/49.md) | Full       | Private key encryption      | -                        |
| [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md) | Full       | Lists                       | 10001-10030, 30000-30030 |
| [NIP-52](https://github.com/nostr-protocol/nips/blob/master/52.md) | Full       | Calendar                    | 31924                    |
| [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) | Full       | Reporting                   | 1984                     |
| [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) | Full       | Lightning zaps              | 9734, 9735               |
| [NIP-58](https://github.com/nostr-protocol/nips/blob/master/58.md) | Full       | Badges                      | 8                        |
| [NIP-59](https://github.com/nostr-protocol/nips/blob/master/59.md) | Full       | Gift wrap                   | 13, 1059                 |
| [NIP-65](https://github.com/nostr-protocol/nips/blob/master/65.md) | Full       | Relay list metadata         | 10002                    |
| [NIP-77](https://github.com/nostr-protocol/nips/blob/master/77.md) | Partial    | Negentropy message contract | -                        |
| [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md) | Full       | File metadata               | 1063                     |
| [NIP-98](https://github.com/nostr-protocol/nips/blob/master/98.md) | Partial    | HTTP Auth event semantics   | 27235                    |

## Core Modules

| Module          | Description                                                     |
| --------------- | --------------------------------------------------------------- |
| `Nostr.Event`   | Core event struct with create, parse, serialize, sign, validate |
| `Nostr.Crypto`  | Cryptographic operations (keys, signing, encryption)            |
| `Nostr.Message` | WebSocket protocol messages (EVENT, REQ, CLOSE, etc.)           |
| `Nostr.Filter`  | Subscription filter building                                    |
| `Nostr.Bech32`  | NIP-19 bech32 encoding/decoding                                 |
| `Nostr.NIP44`   | Versioned encrypted payloads                                    |
| `Nostr.NIP17`   | Private message convenience functions                           |
| `Nostr.NIP05`   | DNS-based identifier verification                               |

## Event Types

Each event kind has a dedicated module in `Nostr.Event.*`:

| Kind  | Module             | Description                   |
| ----- | ------------------ | ----------------------------- |
| 0     | `Metadata`         | User profile metadata         |
| 1     | `Note`             | Text notes/posts              |
| 3     | `Contacts`         | Follow list                   |
| 4     | `DirectMessage`    | Encrypted DMs (deprecated)    |
| 5     | `Deletion`         | Event deletion requests       |
| 6     | `Repost`           | Reposts (deprecated)          |
| 7     | `Reaction`         | Reactions to events           |
| 8     | `BadgeAward`       | Badge awards                  |
| 13    | `Seal`             | Sealed/encrypted events       |
| 14    | `PrivateMessage`   | Private chat messages         |
| 15    | `FileMessage`      | Encrypted file messages       |
| 17    | `ExternalReaction` | Reactions to external content |
| 40-44 | `Channel*`         | Public chat channels          |
| 1040  | `OpenTimestamps`   | Timestamp attestations        |
| 1059  | `GiftWrap`         | Gift wrapped events           |
| 1063  | `FileMetadata`     | File metadata                 |
| 1111  | `Comment`          | Threaded comments             |
| 1984  | `Report`           | Content reports               |
| 1985  | `Label`            | Content labels                |
| 9734  | `ZapRequest`       | Lightning zap requests        |
| 9735  | `ZapReceipt`       | Lightning zap receipts        |
| 10002 | `RelayList`        | Relay list metadata           |
| 10050 | `DMRelayList`      | DM relay preferences          |
| 22242 | `ClientAuth`       | Client authentication         |
| 27235 | `HttpAuth`         | HTTP authentication           |
| 30023 | `Article`          | Long-form content             |
| 30315 | `UserStatus`       | User status updates           |

## Related Packages

This library is part of a larger Nostr ecosystem for Elixir:

- **nostr_lib** (this package) - Low-level protocol implementation
- **nostr_client** - WebSocket client for connecting to relays
- **nostr_server** - WebSocket server for building relays
- **nostr_relay** - Full relay implementation

## Documentation

Full documentation is available on [HexDocs](https://hexdocs.pm/nostr_lib).

## Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.