diff --git a/README.md b/README.md index a01b166..a955021 100644 --- a/README.md +++ b/README.md @@ -41,12 +41,20 @@ For more options, see `wisp.toml.example`. ## Features -* NIPs: 1, 2, 9, 11, 13, 16, 33, 40, 42, 45, 50, 65, 70, 77, 86 +* NIPs: 1, 2, 9, 11, 13, 16, 33, 40, 42, 45, 50, 51, 65, 70, 77, 86 * LMDB storage (no external database) * Spider mode for syncing events from external relays * Import/export to JSONL * Prometheus metrics at `GET /metrics` +Marmot/MLS compatible: Wisp's generic NIP-16/NIP-33 handling stores and serves +kind 10050 (DM/inbox relays, replaceable), 10051 (KeyPackage relays, +replaceable), 30443 (KeyPackage, addressable) / legacy 443, and 1059 gift +wraps, so Haven, WhiteNoise, and other Marmot clients work without extra setup. +Gift wraps are stored and served like any other event; Wisp does not implement +the NIP-17 recipient-only serving rule, so operators wanting to restrict who can +read kind 1059 should enable AUTH (`auth_required`). + ## Monitoring Operational metrics are exposed in Prometheus format at `GET /metrics` on the diff --git a/src/nip11.zig b/src/nip11.zig index f80eb94..3e1f28c 100644 --- a/src/nip11.zig +++ b/src/nip11.zig @@ -41,7 +41,7 @@ pub fn write(config: *const Config, nip86: *const Nip86Handler, w: anytype) !voi try writeJsonString(w, contact); } - try w.writeAll(",\"supported_nips\":[1,2,9,11,13,16,33,40,42,45,50,65,70,77,86]"); + try w.writeAll(",\"supported_nips\":[1,2,9,11,13,16,33,40,42,45,50,51,65,70,77,86]"); try w.writeAll(",\"software\":\"https://github.com/privkeyio/wisp\""); try w.writeAll(",\"version\":\"0.5.12\""); diff --git a/tests/integration.sh b/tests/integration.sh index 206a42f..cae4c21 100755 --- a/tests/integration.sh +++ b/tests/integration.sh @@ -72,6 +72,35 @@ chk "NIP-16 replaceable kept single" 1 "$(req -k 0 -a "$PK2")" chk "NIP-16 replaceable keeps latest" "v2" \ "$(timeout 10 noz req -k 0 -a "$PK2" "$R" 2>/dev/null | grep -o 'v[12]' | head -1)" +# --- NIP-51 DM relays list (kind 10050, NIP-17 inbox) replaceable, latest wins --- +dmbase=$(($(date +%s) - 20)) +pub --sec $SEC2 -k 10050 --ts $dmbase -t relay=wss://relay.one -c "" +pub --sec $SEC2 -k 10050 --ts $((dmbase + 1)) -t relay=wss://relay.two -c "" +sleep 0.5 +chk "NIP-51 kind 10050 kept single" 1 "$(req -k 10050 -a "$PK2")" +chk "NIP-51 kind 10050 keeps latest" "wss://relay.two" \ + "$(timeout 10 noz req -k 10050 -a "$PK2" "$R" 2>/dev/null | grep -oE 'wss://relay\.(one|two)' | head -1)" + +# --- Marmot/NIP-EE KeyPackage relays list (kind 10051) replaceable, latest wins --- +kpbase=$(($(date +%s) - 20)) +pub --sec $SEC2 -k 10051 --ts $kpbase -t relay=wss://kp.one -c "" +pub --sec $SEC2 -k 10051 --ts $((kpbase + 1)) -t relay=wss://kp.two -c "" +sleep 0.5 +chk "Marmot kind 10051 kept single" 1 "$(req -k 10051 -a "$PK2")" +chk "Marmot kind 10051 keeps latest" "wss://kp.two" \ + "$(timeout 10 noz req -k 10051 -a "$PK2" "$R" 2>/dev/null | grep -oE 'wss://kp\.(one|two)' | head -1)" + +# --- Marmot KeyPackage (kind 30443) addressable, keyed by d tag, latest wins --- +kabase=$(($(date +%s) - 20)) +pub --sec $SEC2 -k 30443 -d device1 --ts $kabase -c "kp-v1" +pub --sec $SEC2 -k 30443 -d device1 --ts $((kabase + 1)) -c "kp-v2" +pub --sec $SEC2 -k 30443 -d device2 --ts $((kabase + 1)) -c "kp-other" +sleep 0.5 +chk "Marmot kind 30443 same d-tag replaced" 1 "$(req -k 30443 -d device1)" +chk "Marmot kind 30443 different d-tags kept" 2 "$(req -k 30443 -a "$PK2")" +chk "Marmot kind 30443 keeps latest per d" "kp-v2" \ + "$(timeout 10 noz req -k 30443 -d device1 -a "$PK2" "$R" 2>/dev/null | grep -oE 'kp-v[12]' | head -1)" + # --- NIP-16 ephemeral (kind 20000) not stored --- pub --sec $SEC1 -k 20000 -c "ephemeral" sleep 0.5