All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
This is a breaking release that fixes the wire/crypto layer. Prior versions did not correctly speak the NIP-01 wire protocol and shipped a broken NIP-04 implementation; message builders, validators, and several crypto primitives changed shape. Any consumer relying on the old (non-functional) output must update. See the migration notes below.
createReqMessage
→ ["REQ", subId, ...filters], createCloseMessage → ["CLOSE", subId],
createNoticeMessage → ["NOTICE", msg], createOkMessage →
["OK", eventId, bool, msg]. Previously they emitted ["REQ", {subscription_id,
filters}] etc., which every compliant relay rejects. Downstream emitters fixed
too: NIP-46 transport subscribe, NIP-28 channel subscribe/unsubscribe, NIP-33
parameterized subscribe, and NIP-02 createContactListSubscription (which
previously omitted the subscription id entirely).validateMessage / validateEvent rewritten for positional args. Control
messages with string/boolean payloads (NOTICE/EOSE/OK/CLOSED) are now
accepted; CLOSED added to MESSAGE_TYPES.[type, ...data] and rebuilding
[type, data] (which turned ["REQ","sub1",{...}] into ["REQ",["sub1",{...}]]).encryptMessage/decryptMessage are now
called as (message, senderPriv, recipientPub) and (ciphertext, recipientPriv,
senderPub) per the nostr-crypto-utils signature. Every kind-4 DM was previously
broken and non-interoperable. createEncryptedDM now also includes pubkey and
created_at so the event is publishable.validateSignature performed no verification (returned true for any event
with a string sig, and true for non-EVENT messages). It now performs real
BIP-340 verification (validateEvent + verifySignature), is async
(returns Promise<boolean>), and returns false for non-EVENT messages.schnorr(sha256("nostr:delegation:<delegatee>:<conditions>")), not an event
signature; verification no longer re-serializes with a fresh created_at.
Conditions use the NIP-26 grammar (kind=, created_at>, created_at<).["nonce", n, target] tag inside the standard 6-element NIP-01 id preimage;
calculatePowEventId now returns { id, nonce, tags }; validateEventPoW
recomputes the id before counting leading zero bits (a forged id of "0000…"
is rejected).validateEvent uses strict type checks (accepts kind:0, empty content,
created_at:0) and enforces hex format on id/pubkey/sig.bech32Decode normalizes all-uppercase input (BIP-173 / QR) and lifts the
90-char cap for NIP-19 TLV entities; encodeToBech32 throws on odd-length /
non-hex input instead of minting a checksum-valid string for the wrong key.encode*/decode* enforce 32-byte (64 hex char) lengths.getEventTreatment no longer classifies kind 41/42 (channel
metadata/message) as replaceable — prevents channel-history data loss.NostrWSFilter tag queries use NIP-01 #e/#p keys instead of
tags: Record<string,string[]>.nostr-vectors.json known-answer vectors.@noble/curves and @noble/hashes as direct dependencies (NIP-26 schnorr).package.json in dist/cjs for Node-RED compatibility