mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
This script validates protocol interoperability by publishing Video Post and View events, and sending Encrypted DMs using ephemeral keys against public relays. It ensures the NostrClient facade and event builders function correctly in a Node.js environment. Co-authored-by: PR0M3TH3AN <[email protected]>
186 lines
6.1 KiB
JavaScript
186 lines
6.1 KiB
JavaScript
import './setup-test-env.js';
|
|
import { NostrClient } from '../../js/nostr/client.js';
|
|
import { buildVideoPostEvent, buildViewEvent, NOTE_TYPES } from '../../js/nostrEventSchemas.js';
|
|
import * as NostrTools from 'nostr-tools';
|
|
|
|
const bytesToHex = (bytes) => {
|
|
return Buffer.from(bytes).toString('hex');
|
|
};
|
|
|
|
const RELAYS = [
|
|
"wss://relay.damus.io",
|
|
"wss://nos.lol"
|
|
];
|
|
|
|
async function runTests() {
|
|
console.log("Starting Protocol & Interop Tests...");
|
|
|
|
// --- Setup ---
|
|
console.log("[Setup] Generating ephemeral keys...");
|
|
const aliceSkBytes = NostrTools.generateSecretKey();
|
|
const aliceSk = bytesToHex(aliceSkBytes);
|
|
const alicePk = NostrTools.getPublicKey(aliceSkBytes);
|
|
|
|
const bobSkBytes = NostrTools.generateSecretKey();
|
|
const bobSk = bytesToHex(bobSkBytes);
|
|
const bobPk = NostrTools.getPublicKey(bobSkBytes);
|
|
|
|
console.log(`[Setup] Alice: ${alicePk}`);
|
|
console.log(`[Setup] Bob: ${bobPk}`);
|
|
|
|
const aliceClient = new NostrClient();
|
|
aliceClient.relays = [...RELAYS];
|
|
aliceClient.readRelays = [...RELAYS];
|
|
aliceClient.writeRelays = [...RELAYS];
|
|
|
|
const bobClient = new NostrClient();
|
|
bobClient.relays = [...RELAYS];
|
|
bobClient.readRelays = [...RELAYS];
|
|
bobClient.writeRelays = [...RELAYS];
|
|
|
|
console.log("[Setup] Connecting clients...");
|
|
// Initialize to connect
|
|
await aliceClient.init(); // This might try to load stored session, but shouldn't matter
|
|
await bobClient.init();
|
|
|
|
// Register signers
|
|
await aliceClient.registerPrivateKeySigner({ privateKey: aliceSk, pubkey: alicePk });
|
|
aliceClient.pubkey = alicePk; // Explicitly set client pubkey to ensure correct signer resolution
|
|
|
|
await bobClient.registerPrivateKeySigner({ privateKey: bobSk, pubkey: bobPk });
|
|
bobClient.pubkey = bobPk; // Explicitly set client pubkey to ensure correct signer resolution
|
|
|
|
let testsPassed = 0;
|
|
let testsTotal = 0;
|
|
|
|
// --- Test A: Video Post ---
|
|
testsTotal++;
|
|
console.log("\n[Test A] Publishing VIDEO_POST...");
|
|
try {
|
|
const videoPayload = {
|
|
version: 3,
|
|
title: "Interop Test Video " + Date.now(),
|
|
description: "This is a test video event.",
|
|
videoRootId: "interop-test-" + Date.now(),
|
|
mode: "dev",
|
|
isPrivate: false,
|
|
isNsfw: false,
|
|
isForKids: false,
|
|
enableComments: true
|
|
};
|
|
|
|
// We use signAndPublishEvent directly with a manually built event to test the schema helper
|
|
const event = buildVideoPostEvent({
|
|
pubkey: alicePk,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
dTagValue: videoPayload.videoRootId,
|
|
content: videoPayload
|
|
});
|
|
|
|
const { signedEvent } = await aliceClient.signAndPublishEvent(event);
|
|
console.log(`[Test A] Published event ${signedEvent.id}`);
|
|
|
|
// Verify
|
|
console.log("[Test A] Verifying roundtrip...");
|
|
// Give relays a moment
|
|
await new Promise(r => setTimeout(r, 2000));
|
|
|
|
// getEventById returns the Video object (converted), but we can ask for raw too
|
|
const result = await bobClient.getEventById(signedEvent.id, { includeRaw: true });
|
|
if (!result || !result.rawEvent) throw new Error("Failed to fetch event back");
|
|
|
|
const fetched = result.rawEvent;
|
|
if (fetched.id !== signedEvent.id) throw new Error("Fetched ID mismatch");
|
|
|
|
// Parse content
|
|
const content = typeof fetched.content === 'string' ? JSON.parse(fetched.content) : fetched.content;
|
|
if (content.title !== videoPayload.title) throw new Error("Content mismatch: title");
|
|
|
|
console.log("[Test A] PASSED");
|
|
testsPassed++;
|
|
} catch (e) {
|
|
console.error("[Test A] FAILED:", e);
|
|
}
|
|
|
|
// --- Test B: View Event ---
|
|
testsTotal++;
|
|
console.log("\n[Test B] Publishing VIEW_EVENT...");
|
|
try {
|
|
const viewEvent = buildViewEvent({
|
|
pubkey: alicePk,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
pointerValue: "test-video-pointer", // Arbitrary pointer for test
|
|
content: "view-test"
|
|
});
|
|
|
|
const { signedEvent: signedView } = await aliceClient.signAndPublishEvent(viewEvent);
|
|
console.log(`[Test B] Published view event ${signedView.id}`);
|
|
|
|
await new Promise(r => setTimeout(r, 2000));
|
|
|
|
// Bob fetches raw event
|
|
const fetchedView = await bobClient.fetchRawEventById(signedView.id);
|
|
if (!fetchedView) throw new Error("Failed to fetch view event");
|
|
if (fetchedView.id !== signedView.id) throw new Error("View event ID mismatch");
|
|
|
|
console.log("[Test B] PASSED");
|
|
testsPassed++;
|
|
} catch (e) {
|
|
console.error("[Test B] FAILED:", e);
|
|
}
|
|
|
|
// --- Test C: Direct Message ---
|
|
testsTotal++;
|
|
console.log("\n[Test C] Sending Direct Message...");
|
|
try {
|
|
const message = "Hello Bob, this is Alice " + Date.now();
|
|
const npubBob = NostrTools.nip19.npubEncode(bobPk);
|
|
|
|
const sendResult = await aliceClient.sendDirectMessage(npubBob, message);
|
|
if (!sendResult.ok) throw new Error("Failed to send DM: " + (sendResult.error || "unknown"));
|
|
console.log("[Test C] DM sent successfully");
|
|
|
|
await new Promise(r => setTimeout(r, 3000));
|
|
|
|
console.log("[Test C] Bob checking messages...");
|
|
// Force bob to list messages (which triggers decryption using his registered signer)
|
|
const messages = await bobClient.listDirectMessages(bobPk, { limit: 5 });
|
|
|
|
const received = messages.find(m => m.plaintext === message);
|
|
if (!received) {
|
|
console.log("Received messages:", messages.map(m => m.plaintext));
|
|
throw new Error("Bob did not find the specific message");
|
|
}
|
|
|
|
if (received.sender.pubkey !== alicePk) {
|
|
console.log(`[Test C] Sender mismatch: Expected ${alicePk}, got ${received.sender.pubkey}`);
|
|
throw new Error("Sender mismatch");
|
|
}
|
|
|
|
console.log("[Test C] PASSED");
|
|
testsPassed++;
|
|
} catch (e) {
|
|
console.error("[Test C] FAILED:", e);
|
|
}
|
|
|
|
// --- Summary ---
|
|
console.log("\n---------------------------------------------------");
|
|
console.log(`Tests Completed: ${testsPassed}/${testsTotal}`);
|
|
|
|
aliceClient.logout();
|
|
bobClient.logout();
|
|
|
|
if (testsPassed === testsTotal) {
|
|
console.log("ALL TESTS PASSED");
|
|
process.exit(0);
|
|
} else {
|
|
console.error("SOME TESTS FAILED");
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
runTests().catch(e => {
|
|
console.error("Unhandled execution error:", e);
|
|
process.exit(1);
|
|
});
|