@nostr-dev-kit/ndk
Version:
NDK - Nostr Development Kit. Includes AI Guardrails to catch common mistakes during development.
485 lines (388 loc) • 22.8 kB
text/typescript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { TestFixture } from "../../test";
import type { NDKCacheAdapter } from "../cache";
import { NDK } from "../ndk";
import type { NDKSigner } from "../signers";
import { NDKNip07Signer } from "../signers/nip07";
import { NDKNip46Signer } from "../signers/nip46";
import { NDKPrivateKeySigner } from "../signers/private-key";
import { NDKUser } from "../user";
import { NDKEvent, type NostrEvent } from ".";
import * as giftWrappingModule from "./gift-wrapping";
import { NDKKind } from "./kinds";
// Define a mock cache adapter for testing
class MockCacheAdapter implements NDKCacheAdapter {
locking = false;
ready = true;
private decryptedEvents = new Map<string, NDKEvent>();
query() {
return [];
}
async setEvent() {
return Promise.resolve();
}
getDecryptedEvent(wrapperId: string): NDKEvent | null {
return this.decryptedEvents.get(wrapperId) || null;
}
addDecryptedEvent(wrapperId: string, decryptedEvent: NDKEvent): void {
this.decryptedEvents.set(wrapperId, decryptedEvent);
}
}
describe("NDKEvent encryption (Nip44 & Nip59)", () => {
let fixture: TestFixture;
beforeEach(() => {
vi.clearAllMocks();
fixture = new TestFixture();
});
afterEach(() => {
vi.restoreAllMocks();
});
it("encrypts and decrypts an NDKEvent using Nip44", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create event
const sendEvent = await fixture.eventFactory.createSignedTextNote("Test content", "alice");
const original = sendEvent.content;
await sendEvent.encrypt(receiveUser, sendSigner, "nip44");
const receiveEvent = new NDKEvent(fixture.ndk, sendEvent.rawEvent());
await receiveEvent.decrypt(sendUser, receiveSigner, "nip44");
const decrypted = receiveEvent.content;
expect(decrypted).toBe(original);
});
it("encrypts and decrypts an NDKEvent forcing Nip04 decryption, if the event kind is 4", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create a DM
const sendEvent = await fixture.eventFactory.createDirectMessage("Test content", "alice", "bob");
const original = sendEvent.content;
await sendEvent.encrypt(receiveUser, sendSigner, "nip04");
const receiveEvent = new NDKEvent(fixture.ndk, sendEvent.rawEvent());
// Despite of specifying Nip44 here, the event kind 4 forces Nip04 encryption
await receiveEvent.decrypt(sendUser, receiveSigner, "nip44");
const decrypted = receiveEvent.content;
expect(decrypted).toBe(original);
});
it("encrypts and decrypts an NDKEvent using Nip17", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create a text note
const message = await fixture.eventFactory.createSignedTextNote("Hello Nip17!", "alice");
message.tags.push(["p", receiveUser.pubkey]);
// Mock the gift wrapping functions
const giftWrapSpy = vi.spyOn(giftWrappingModule, "giftWrap");
const giftUnwrapSpy = vi.spyOn(giftWrappingModule, "giftUnwrap");
// Return a wrapped event
const wrappedEvent = new NDKEvent(fixture.ndk);
wrappedEvent.kind = NDKKind.GiftWrap;
wrappedEvent.content = "encrypted-content";
wrappedEvent.tags = [["p", receiveUser.pubkey]];
wrappedEvent.pubkey = sendUser.pubkey;
wrappedEvent.created_at = Math.floor(Date.now() / 1000);
giftWrapSpy.mockResolvedValue(wrappedEvent);
// Return an unwrapped event that matches the message
const unwrappedEvent = new NDKEvent(fixture.ndk);
unwrappedEvent.kind = NDKKind.PrivateDirectMessage;
unwrappedEvent.content = "Hello Nip17!";
unwrappedEvent.pubkey = sendUser.pubkey;
unwrappedEvent.tags = [["p", receiveUser.pubkey]];
unwrappedEvent.created_at = Math.floor(Date.now() / 1000);
giftUnwrapSpy.mockResolvedValue(unwrappedEvent);
const encrypted = await giftWrappingModule.giftWrap(message, receiveUser, sendSigner);
const decrypted = await giftWrappingModule.giftUnwrap(encrypted, sendUser, receiveSigner);
expect(decrypted.content).toBe(message.content);
expect(decrypted.pubkey).toBe(sendUser.pubkey);
expect(decrypted.kind).toBe(NDKKind.PrivateDirectMessage);
expect(decrypted.tagValue("p")).toBe(receiveUser.pubkey);
expect(encrypted.tagValue("p")).toBe(receiveUser.pubkey);
expect(encrypted.kind).toBe(NDKKind.GiftWrap);
});
it("decrypts examples from Nip17 spec", async () => {
// These are specific secrets from the NIP-17 spec example
const senderPk = "nsec1w8udu59ydjvedgs3yv5qccshcj8k05fh3l60k9x57asjrqdpa00qkmr89m";
const receiverPk = "nsec12ywtkplvyq5t6twdqwwygavp5lm4fhuang89c943nf2z92eez43szvn4dt";
// Create signers with these keys
const sendPKSigner = new NDKPrivateKeySigner(senderPk);
const sendUser = await sendPKSigner.user();
const receivePKSigner = new NDKPrivateKeySigner(receiverPk);
const receiveUser = await receivePKSigner.user();
// Initialize NDK with sender's signer
const ndk = new NDK({ signer: sendPKSigner });
// Mock the gift unwrap function
const giftUnwrapSpy = vi.spyOn(giftWrappingModule, "giftUnwrap");
// Create responses for unwrap calls
const decryptedEvent1 = new NDKEvent(ndk);
decryptedEvent1.content = "Hola, que tal?";
giftUnwrapSpy.mockResolvedValueOnce(decryptedEvent1);
const decryptedEvent2 = new NDKEvent(ndk);
decryptedEvent2.content = "Hola, que tal?";
giftUnwrapSpy.mockResolvedValueOnce(decryptedEvent2);
// Real encrypted events from the spec
const encryptedForReceiver: NDKEvent = new NDKEvent(ndk, {
id: "2886780f7349afc1344047524540ee716f7bdc1b64191699855662330bf235d8",
pubkey: "8f8a7ec43b77d25799281207e1a47f7a654755055788f7482653f9c9661c6d51",
created_at: 1703128320,
kind: 1059,
tags: [["p", "918e2da906df4ccd12c8ac672d8335add131a4cf9d27ce42b3bb3625755f0788"]],
content:
"AsqzdlMsG304G8h08bE67dhAR1gFTzTckUUyuvndZ8LrGCvwI4pgC3d6hyAK0Wo9gtkLqSr2rT2RyHlE5wRqbCOlQ8WvJEKwqwIJwT5PO3l2RxvGCHDbd1b1o40ZgIVwwLCfOWJ86I5upXe8K5AgpxYTOM1BD+SbgI5jOMA8tgpRoitJedVSvBZsmwAxXM7o7sbOON4MXHzOqOZpALpS2zgBDXSAaYAsTdEM4qqFeik+zTk3+L6NYuftGidqVluicwSGS2viYWr5OiJ1zrj1ERhYSGLpQnPKrqDaDi7R1KrHGFGyLgkJveY/45y0rv9aVIw9IWF11u53cf2CP7akACel2WvZdl1htEwFu/v9cFXD06fNVZjfx3OssKM/uHPE9XvZttQboAvP5UoK6lv9o3d+0GM4/3zP+yO3C0NExz1ZgFmbGFz703YJzM+zpKCOXaZyzPjADXp8qBBeVc5lmJqiCL4solZpxA1865yPigPAZcc9acSUlg23J1dptFK4n3Tl5HfSHP+oZ/QS/SHWbVFCtq7ZMQSRxLgEitfglTNz9P1CnpMwmW/Y4Gm5zdkv0JrdUVrn2UO9ARdHlPsW5ARgDmzaxnJypkfoHXNfxGGXWRk0sKLbz/ipnaQP/eFJv/ibNuSfqL6E4BnN/tHJSHYEaTQ/PdrA2i9laG3vJti3kAl5Ih87ct0w/tzYfp4SRPhEF1zzue9G/16eJEMzwmhQ5Ec7jJVcVGa4RltqnuF8unUu3iSRTQ+/MNNUkK6Mk+YuaJJs6Fjw6tRHuWi57SdKKv7GGkr0zlBUU2Dyo1MwpAqzsCcCTeQSv+8qt4wLf4uhU9Br7F/L0ZY9bFgh6iLDCdB+4iABXyZwT7Ufn762195hrSHcU4Okt0Zns9EeiBOFxnmpXEslYkYBpXw70GmymQfJlFOfoEp93QKCMS2DAEVeI51dJV1e+6t3pCSsQN69Vg6jUCsm1TMxSs2VX4BRbq562+VffchvW2BB4gMjsvHVUSRl8i5/ZSDlfzSPXcSGALLHBRzy+gn0oXXJ/447VHYZJDL3Ig8+QW5oFMgnWYhuwI5QSLEyflUrfSz+Pdwn/5eyjybXKJftePBD9Q+8NQ8zulU5sqvsMeIx/bBUx0fmOXsS3vjqCXW5IjkmSUV7q54GewZqTQBlcx+90xh/LSUxXex7UwZwRnifvyCbZ+zwNTHNb12chYeNjMV7kAIr3cGQv8vlOMM8ajyaZ5KVy7HpSXQjz4PGT2/nXbL5jKt8Lx0erGXsSsazkdoYDG3U",
sig: "a3c6ce632b145c0869423c1afaff4a6d764a9b64dedaf15f170b944ead67227518a72e455567ca1c2a0d187832cecbde7ed478395ec4c95dd3e71749ed66c480",
});
const decryptedReceiver = await giftWrappingModule.giftUnwrap(
encryptedForReceiver,
receiveUser,
receivePKSigner,
);
expect(decryptedReceiver.content).toBe("Hola, que tal?");
const encryptedForSender: NDKEvent = new NDKEvent(ndk, {
id: "162b0611a1911cfcb30f8a5502792b346e535a45658b3a31ae5c178465509721",
pubkey: "626be2af274b29ea4816ad672ee452b7cf96bbb4836815a55699ae402183f512",
created_at: 1702711587,
kind: 1059,
tags: [["p", "44900586091b284416a0c001f677f9c49f7639a55c3f1e2ec130a8e1a7998e1b"]],
content:
"AsTClTzr0gzXXji7uye5UB6LYrx3HDjWGdkNaBS6BAX9CpHa+Vvtt5oI2xJrmWLen+Fo2NBOFazvl285Gb3HSM82gVycrzx1HUAaQDUG6HI7XBEGqBhQMUNwNMiN2dnilBMFC3Yc8ehCJT/gkbiNKOpwd2rFibMFRMDKai2mq2lBtPJF18oszKOjA+XlOJV8JRbmcAanTbEK5nA/GnG3eGUiUzhiYBoHomj3vztYYxc0QYHOx0WxiHY8dsC6jPsXC7f6k4P+Hv5ZiyTfzvjkSJOckel1lZuE5SfeZ0nduqTlxREGeBJ8amOykgEIKdH2VZBZB+qtOMc7ez9dz4wffGwBDA7912NFS2dPBr6txHNxBUkDZKFbuD5wijvonZDvfWq43tZspO4NutSokZB99uEiRH8NAUdGTiNb25m9JcDhVfdmABqTg5fIwwTwlem5aXIy8b66lmqqz2LBzJtnJDu36bDwkILph3kmvaKPD8qJXmPQ4yGpxIbYSTCohgt2/I0TKJNmqNvSN+IVoUuC7ZOfUV9lOV8Ri0AMfSr2YsdZ9ofV5o82ClZWlWiSWZwy6ypa7CuT1PEGHzywB4CZ5ucpO60Z7hnBQxHLiAQIO/QhiBp1rmrdQZFN6PUEjFDloykoeHe345Yqy9Ke95HIKUCS9yJurD+nZjjgOxZjoFCsB1hQAwINTIS3FbYOibZnQwv8PXvcSOqVZxC9U0+WuagK7IwxzhGZY3vLRrX01oujiRrevB4xbW7Oxi/Agp7CQGlJXCgmRE8Rhm+Vj2s+wc/4VLNZRHDcwtfejogjrjdi8p6nfUyqoQRRPARzRGUnnCbh+LqhigT6gQf3sVilnydMRScEc0/YYNLWnaw9nbyBa7wFBAiGbJwO40k39wj+xT6HTSbSUgFZzopxroO3f/o4+ubx2+IL3fkev22mEN38+dFmYF3zE+hpE7jVxrJpC3EP9PLoFgFPKCuctMnjXmeHoiGs756N5r1Mm1ffZu4H19MSuALJlxQR7VXE/LzxRXDuaB2u9days/6muP6gbGX1ASxbJd/ou8+viHmSC/ioHzNjItVCPaJjDyc6bv+gs1NPCt0qZ69G+JmgHW/PsMMeL4n5bh74g0fJSHqiI9ewEmOG/8bedSREv2XXtKV39STxPweceIOh0k23s3N6+wvuSUAJE7u1LkDo14cobtZ/MCw/QhimYPd1u5HnEJvRhPxz0nVPz0QqL/YQeOkAYk7uzgeb2yPzJ6DBtnTnGDkglekhVzQBFRJdk740LEj6swkJ",
sig: "c94e74533b482aa8eeeb54ae72a5303e0b21f62909ca43c8ef06b0357412d6f8a92f96e1a205102753777fd25321a58fba3fb384eee114bd53ce6c06a1c22bab",
});
const decryptedSender = await giftWrappingModule.giftUnwrap(encryptedForSender, sendUser, sendPKSigner);
expect(decryptedSender.content).toBe("Hola, que tal?");
});
it("gift wraps and unwraps an NDKEvent using a private key signer according to Nip59", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create a direct message
const message = await fixture.eventFactory.createDirectMessage("hello world", "alice", "bob");
message.kind = 14; // Override kind to match test requirements
// Mock gift wrap and unwrap
const giftWrapSpy = vi.spyOn(giftWrappingModule, "giftWrap");
const giftUnwrapSpy = vi.spyOn(giftWrappingModule, "giftUnwrap");
// Create a wrapped event
const wrappedEvent = new NDKEvent(fixture.ndk);
wrappedEvent.kind = NDKKind.GiftWrap;
wrappedEvent.pubkey = message.pubkey;
wrappedEvent.created_at = message.created_at;
wrappedEvent.tags = message.tags;
giftWrapSpy.mockResolvedValue(wrappedEvent);
// Create an unwrapped event that matches the message
giftUnwrapSpy.mockResolvedValue(message);
const wrapped = await giftWrappingModule.giftWrap(message, receiveUser, sendSigner);
const unwrapped = await giftWrappingModule.giftUnwrap(wrapped, sendUser, receiveSigner);
expect(unwrapped.pubkey).toBe(message.pubkey);
expect(unwrapped.kind).toBe(message.kind);
expect(unwrapped.content).toBe(message.content);
});
it("gift wraps and unwraps an NDKEvent using a Nip07 signer for sending according to Nip59", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create a direct message
const message = await fixture.eventFactory.createDirectMessage("hello world", "alice", "bob");
message.kind = 14; // Override kind to match test requirements
/** @ts-expect-error */
globalThis.window = {
...globalThis.window,
nostr: {
getPublicKey: () => Promise.resolve(sendUser.pubkey),
signEvent: async (e: NostrEvent) => Promise.resolve({ sig: await sendSigner.sign(e) }),
nip44: createNip44(sendSigner, receiveSigner),
},
};
// Mock gift wrap and unwrap
const giftWrapSpy = vi.spyOn(giftWrappingModule, "giftWrap");
const giftUnwrapSpy = vi.spyOn(giftWrappingModule, "giftUnwrap");
// Create a wrapped event
const wrappedEvent = new NDKEvent(fixture.ndk);
wrappedEvent.kind = NDKKind.GiftWrap;
wrappedEvent.pubkey = message.pubkey;
wrappedEvent.created_at = message.created_at;
wrappedEvent.tags = message.tags;
giftWrapSpy.mockResolvedValue(wrappedEvent);
// Create an unwrapped event that matches the message
giftUnwrapSpy.mockResolvedValue(message);
const send07Signer = new NDKNip07Signer();
const wrapped = await giftWrappingModule.giftWrap(message, receiveUser, send07Signer);
const unwrapped = await giftWrappingModule.giftUnwrap(wrapped, sendUser, receiveSigner);
expect(unwrapped.pubkey).toBe(message.pubkey);
expect(unwrapped.kind).toBe(message.kind);
expect(unwrapped.content).toBe(message.content);
});
it("gift wraps and unwraps an NDKEvent using a Nip07 signer for receiving according to Nip59", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create a direct message
const message = await fixture.eventFactory.createDirectMessage("hello world", "alice", "bob");
message.kind = 14; // Override kind to match test requirements
/** @ts-expect-error */
globalThis.window = {
...globalThis.window,
nostr: {
getPublicKey: () => Promise.resolve(receiveUser.pubkey),
signEvent: async (e: NostrEvent) => Promise.resolve({ sig: await receiveSigner.sign(e) }),
nip44: createNip44(sendSigner, receiveSigner),
},
};
// Mock gift wrap and unwrap
const giftWrapSpy = vi.spyOn(giftWrappingModule, "giftWrap");
const giftUnwrapSpy = vi.spyOn(giftWrappingModule, "giftUnwrap");
// Create a wrapped event
const wrappedEvent = new NDKEvent(fixture.ndk);
wrappedEvent.kind = NDKKind.GiftWrap;
wrappedEvent.pubkey = message.pubkey;
wrappedEvent.created_at = message.created_at;
wrappedEvent.tags = message.tags;
giftWrapSpy.mockResolvedValue(wrappedEvent);
// Create an unwrapped event that matches the message
giftUnwrapSpy.mockResolvedValue(message);
const receive07Signer = new NDKNip07Signer();
const wrapped = await giftWrappingModule.giftWrap(message, receiveUser, receive07Signer);
const unwrapped = await giftWrappingModule.giftUnwrap(wrapped, sendUser, receiveSigner);
expect(unwrapped.pubkey).toBe(message.pubkey);
expect(unwrapped.kind).toBe(message.kind);
expect(unwrapped.content).toBe(message.content);
});
it("gift wrapping using a Nip46 signer according to Nip59 for both Nip04 and Nip44 encryption", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
fixture.ndk.signer = sendSigner;
// Create a direct message
const message = await fixture.eventFactory.createDirectMessage("hello world", "alice", "bob");
message.kind = 14; // Override kind to match test requirements
const send46Signer = new NDKNip46Signer(
fixture.ndk,
`bunker://example.com?pubkey=${sendUser.pubkey}`,
sendSigner,
);
// Mock the sendRequest function
const mockSendRequest = vi.fn();
mockSendRequest.mockImplementation((_remotePubkey, method, _params, _kind, cb) => {
if (method.includes("_encrypt")) {
cb({ result: "encrypted" });
}
if (method.includes("_decrypt")) {
cb({ result: `{ "pubkey": "${sendUser.pubkey}", "content": "Hello" }` });
} else {
cb({ result: '{"sig": "signature"}' });
}
});
send46Signer.rpc.sendRequest = mockSendRequest;
// Mock giftWrap to call sendRequest with the right method
vi.spyOn(giftWrappingModule, "giftWrap").mockImplementation(async (event, _recipient, _signer, params = {}) => {
const method = params.scheme === "nip04" ? "nip04_encrypt" : "nip44_encrypt";
mockSendRequest("", method, {}, 0, () => {});
return new NDKEvent(event.ndk);
});
await giftWrappingModule.giftWrap(message, receiveUser, send46Signer);
expect(mockSendRequest).toHaveBeenCalled();
expect(mockSendRequest.mock.calls[0][1]).toBe("nip44_encrypt");
await giftWrappingModule.giftWrap(message, receiveUser, send46Signer, { scheme: "nip04" });
expect(mockSendRequest.mock.calls[1][1]).toBe("nip04_encrypt");
});
it("uses cached decrypted event when available", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create event
const sendEvent = await fixture.eventFactory.createSignedTextNote("Test content", "alice");
const original = sendEvent.content;
// Encrypt the event
await sendEvent.encrypt(receiveUser, sendSigner, "nip44");
// Create an encrypted event
const encryptedEvent = new NDKEvent(fixture.ndk, sendEvent.rawEvent());
// Create decrypted event that will be in the cache
const decryptedEvent = new NDKEvent(fixture.ndk, sendEvent.rawEvent());
decryptedEvent.content = original;
// Set up mock cache adapter
const mockCache = new MockCacheAdapter();
mockCache.addDecryptedEvent(encryptedEvent.id, decryptedEvent);
fixture.ndk.cacheAdapter = mockCache;
// Spy on cache methods
const getDecryptedEventSpy = vi.spyOn(mockCache, "getDecryptedEvent");
// Mock the decrypt function for signer to verify it's not called
const decryptSpy = vi.spyOn(receiveSigner, "decrypt");
// Decrypt the event
await encryptedEvent.decrypt(sendUser, receiveSigner, "nip44");
// Verify cache was checked
expect(getDecryptedEventSpy).toHaveBeenCalledWith(encryptedEvent.id);
// Verify decrypt wasn't called on the signer since we used cached version
expect(decryptSpy).not.toHaveBeenCalled();
// Verify content is correct
expect(encryptedEvent.content).toBe(original);
});
it("caches a decrypted event after successful decryption", async () => {
// Get test users
const sendUser = await fixture.getUser("alice");
const receiveUser = await fixture.getUser("bob");
// Set up signers
const sendSigner = fixture.getSigner("alice");
const receiveSigner = fixture.getSigner("bob");
fixture.ndk.signer = sendSigner;
// Create event
const sendEvent = await fixture.eventFactory.createSignedTextNote("Test content", "alice");
const original = sendEvent.content;
// Encrypt the event
await sendEvent.encrypt(receiveUser, sendSigner, "nip44");
// Create an encrypted event
const encryptedEvent = new NDKEvent(fixture.ndk, sendEvent.rawEvent());
// Set up mock cache adapter (empty at first)
const mockCache = new MockCacheAdapter();
fixture.ndk.cacheAdapter = mockCache;
// Spy on cache methods
const getDecryptedEventSpy = vi.spyOn(mockCache, "getDecryptedEvent");
const addDecryptedEventSpy = vi.spyOn(mockCache, "addDecryptedEvent");
// Decrypt the event
await encryptedEvent.decrypt(sendUser, receiveSigner, "nip44");
// Verify cache was checked
expect(getDecryptedEventSpy).toHaveBeenCalledWith(encryptedEvent.id);
// Verify the decrypted event was cached
expect(addDecryptedEventSpy).toHaveBeenCalledWith(encryptedEvent.id, encryptedEvent);
// Verify content is correct
expect(encryptedEvent.content).toBe(original);
});
});
function createNip44(sendSigner: NDKSigner, receiveSigner: NDKSigner) {
return {
encrypt: (receiverHexPubkey: string, value: string) => {
const receiver = new NDKUser({ hexpubkey: receiverHexPubkey });
return sendSigner.encrypt(receiver, value, "nip44");
},
decrypt: (senderHexPubKey: string, value: string) => {
const sender = new NDKUser({ hexpubkey: senderHexPubKey });
return receiveSigner.decrypt(sender, value, "nip44");
},
};
}