1import { describe, it, expect } from "vitest";2import { newEvent, newKey, pub, now, item, sockets } from "./helpers.ts";34const connect = sockets();56describe("NIP-77 negentropy", () => {7 it("reconciles a client set against the relay's, respecting visibility", async () => {8 const sk = newKey();9 const recipient = newKey();10 const c = await connect();11 const t0 = now() - 1000;12 const relayHas = [];13 for (let i = 0; i < 100; i++) relayHas.push(await (async () => {14 const e = newEvent(sk, 1, String(i), [], t0 + Math.floor(i / 3));15 await c.publish(e);16 return e;17 })());18 const local = [];19 for (let i = 0; i < 5; i++) local.push(newEvent(sk, 1, "local " + i, [], t0 + 10 + i));20 const wrap = newEvent(sk, 1059, "dm", [["p", pub(recipient)]], t0 + 5);21 await c.publish(wrap);2223 const clientItems = [...relayHas.slice(0, 60), ...local].map(item);24 const { have, need } = await c.sync(clientItems, { kinds: [1], authors: [pub(sk)] });25 expect(have).toEqual(local.map((e) => e.id).sort());26 expect(need).toEqual(relayHas.slice(60).map((e) => e.id).sort());2728 // Strangers never learn the gift wrap; the recipient does.29 let r = await c.sync(relayHas.map(item), { authors: [pub(sk)] });30 expect(r.need).toEqual([]);31 const rc = await connect();32 await rc.auth(recipient);33 r = await rc.sync(relayHas.map(item), { authors: [pub(sk)] });34 expect(r.need).toEqual([wrap.id]);3536 // Error paths.37 c.send("NEG-MSG", "nope", "61");38 expect((await c.expect("NEG-ERR"))[2]).toMatch(/^closed:/);39 c.send("NEG-OPEN", "bad", {}, "zz");40 expect((await c.expect("NEG-ERR"))[2]).toMatch(/^invalid:/);41 const x = await connect();42 x.send("NEG-OPEN", "dm", { kinds: [1059] }, "61");43 expect((await x.expect("NEG-ERR"))[2]).toMatch(/^auth-required:/);44 x.send("NEG-OPEN", "v", { kinds: [1], authors: [pub(sk)] }, "62");45 expect((await x.expect("NEG-MSG"))[2]).toBe("61");46 });47});