# Getting Started

`zig-nostr` is a Nostr protocol library for [Zig](https://ziglang.org). It
targets Zig **0.16** and is in **active development** (`v0.14.9`).

## Install

Fetch the library into your project's `build.zig.zon`:

```sh
zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.14.9.tar.gz
```

Then wire the module in `build.zig`:

```zig
const nostr = b.dependency("nostr", .{ .target = target, .optimize = optimize });
your_module.addImport("nostr", nostr.module("nostr"));
```

The library vendors and compiles bitcoin-core's libsecp256k1 and LMDB from
source, so no system packages are required.

## Platforms

The library builds for macOS, Linux and Windows, on x86_64 and aarch64, and CI builds it and runs the tests on all three systems. To check a Windows build from another system, `zig build test -Dtarget=x86_64-windows-gnu` compiles the test binary and then stops with an error, because a non-Windows host cannot run it. A store takes its full map size on disk on Windows (1 GiB by default) from the first open, where on macOS and Linux it grows with what is kept.

## Quickstart: sign and verify an event

```zig
const std = @import("std");
const nostr = @import("nostr");

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();

    // Time comes from the Io implementation in Zig 0.16, the same way sockets
    // and threads do. Threaded takes a threadsafe allocator, which the arena
    // above is not.
    var threaded = std.Io.Threaded.init(std.heap.page_allocator, .{});
    defer threaded.deinit();
    const io = threaded.io();

    // A Signer wraps the libsecp256k1 context; deinit it when done.
    var signer = nostr.keys.Signer.init();
    defer signer.deinit();

    // Load a keypair from a 32-byte secret key.
    const secret: nostr.keys.SecretKey = your_secret_key; // 32 bytes
    const keypair = try signer.keyPairFromSecretKey(secret);

    // Build and sign a kind:1 text note.
    const created_at = std.Io.Timestamp.now(io, .real).toSeconds();
    const note = try nostr.event.create(
        allocator,
        signer,
        keypair,
        created_at,
        1,
        &.{},
        "hello from zig-nostr",
        null,
    );

    // Verify: recompute the canonical id, then check the Schnorr signature.
    std.debug.assert(try nostr.event.verify(allocator, signer, note));

    // Serialize to the wire JSON form.
    const json = try nostr.event.toJson(allocator, note);
    std.debug.print("{s}\n", .{json});
}
```

## What's in the box

The `nostr` module re-exports focused namespaces:

- `keys`: secp256k1 keys and BIP-340 Schnorr sign/verify
- `event`: the NIP-01 event model, canonical id, JSON encode/decode
- `nip19` / `bech32`: `npub`/`nsec`/`note`/`nprofile`/`nevent`/`naddr` encoding
- `nip06` / `bip39`: mnemonic key derivation
- `nip49`: encrypted key storage at rest (`ncryptsec`)
- `nip44`: v2 payload encryption
- `nip46` / `nip46_client`: remote signing ("bunker") protocol, the signer side and a client that connects to one
- `nip04`: legacy encrypted messages, for older clients only
- `nip59`: gift wrap and NIP-17 private messages
- `nip42`: client authentication to relays
- `relay` / `websocket` / `message` / `filter`: live transport & subscriptions, with NIP-50 `search` on the filter
- `nip65`: relay lists and outbox routing
- `nip05` / `nip11`: DNS identifiers and relay information documents, parsed (the library does no HTTP)
- `nip13`: proof of work, counting and mining
- `nip77`: negentropy set reconciliation
- `nip98` / `nip86` / `blossom`: HTTP authorization headers, the relay management API and Blossom media authorization and blob descriptors
- `liveness`: when a relay connection has gone quiet, and what to do about it
- `store`: the local-first, memory-mapped event store

See [Architecture](/architecture) for how these fit together.

## Build from source

```sh
git clone https://github.com/zig-nostr/nostr
cd nostr
zig build test    # run the suite
```

To fuzz the parsers that read bytes from outside (frames, relay messages, events, NIP-19, NIP-44, NIP-46 and more) until you stop it, use `zig build test --fuzz -Doptimize=ReleaseSafe`.
