// event.ts import { schnorr as schnorr2 } from "@noble/curves/secp256k1"; import { sha256 } from "@noble/hashes/sha256"; import { bytesToHex as bytesToHex2 } from "@noble/hashes/utils"; // keys.ts import { schnorr } from "@noble/curves/secp256k1"; import { bytesToHex } from "@noble/hashes/utils"; function getPublicKey(privateKey) { return bytesToHex(schnorr.getPublicKey(privateKey)); } // utils.ts var utf8Decoder = new TextDecoder("utf-8"); var utf8Encoder = new TextEncoder(); // event.ts var verifiedSymbol = Symbol("verified"); function finishEvent(t, privateKey) { const event = t; event.pubkey = getPublicKey(privateKey); event.id = getEventHash(event); event.sig = getSignature(event, privateKey); event[verifiedSymbol] = true; return event; } function serializeEvent(evt) { if (!validateEvent(evt)) throw new Error("can't serialize event with wrong or missing properties"); return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]); } function getEventHash(event) { let eventHash = sha256(utf8Encoder.encode(serializeEvent(event))); return bytesToHex2(eventHash); } var isRecord = (obj) => obj instanceof Object; function validateEvent(event) { if (!isRecord(event)) return false; if (typeof event.kind !== "number") return false; if (typeof event.content !== "string") return false; if (typeof event.created_at !== "number") return false; if (typeof event.pubkey !== "string") return false; if (!event.pubkey.match(/^[a-f0-9]{64}$/)) return false; if (!Array.isArray(event.tags)) return false; for (let i = 0; i < event.tags.length; i++) { let tag = event.tags[i]; if (!Array.isArray(tag)) return false; for (let j = 0; j < tag.length; j++) { if (typeof tag[j] === "object") return false; } } return true; } function verifySignature(event) { if (typeof event[verifiedSymbol] === "boolean") return event[verifiedSymbol]; const hash = getEventHash(event); if (hash !== event.id) { return event[verifiedSymbol] = false; } try { return event[verifiedSymbol] = schnorr2.verify(event.sig, hash, event.pubkey); } catch (err) { return event[verifiedSymbol] = false; } } function getSignature(event, key) { return bytesToHex2(schnorr2.sign(getEventHash(event), key)); } // nip18.ts function finishRepostEvent(t, reposted, relayUrl, privateKey) { return finishEvent( { kind: 6 /* Repost */, tags: [...t.tags ?? [], ["e", reposted.id, relayUrl], ["p", reposted.pubkey]], content: t.content === "" ? "" : JSON.stringify(reposted), created_at: t.created_at }, privateKey ); } function getRepostedEventPointer(event) { if (event.kind !== 6 /* Repost */) { return void 0; } let lastETag; let lastPTag; for (let i = event.tags.length - 1; i >= 0 && (lastETag === void 0 || lastPTag === void 0); i--) { const tag = event.tags[i]; if (tag.length >= 2) { if (tag[0] === "e" && lastETag === void 0) { lastETag = tag; } else if (tag[0] === "p" && lastPTag === void 0) { lastPTag = tag; } } } if (lastETag === void 0) { return void 0; } return { id: lastETag[1], relays: [lastETag[2], lastPTag?.[2]].filter((x) => typeof x === "string"), author: lastPTag?.[1] }; } function getRepostedEvent(event, { skipVerification } = {}) { const pointer = getRepostedEventPointer(event); if (pointer === void 0 || event.content === "") { return void 0; } let repostedEvent; try { repostedEvent = JSON.parse(event.content); } catch (error) { return void 0; } if (repostedEvent.id !== pointer.id) { return void 0; } if (!skipVerification && !verifySignature(repostedEvent)) { return void 0; } return repostedEvent; } export { finishRepostEvent, getRepostedEvent, getRepostedEventPointer };