askexperts
Version:
AskExperts SDK: build and use AI experts - ask them questions and pay with bitcoin on an open protocol
89 lines • 3.45 kB
JavaScript
/**
* Functions for creating and parsing stream metadata events for NIP-173
*/
import { createEvent, validateNostrEvent } from '../common/crypto.js';
import { STREAM_METADATA_KIND } from './types.js';
/**
* Creates a stream metadata event (kind:173) from a StreamMetadata object
*
* @param metadata - Stream metadata
* @param senderPrivkey - Private key to sign the event
* @returns Signed stream metadata event
*/
export function createStreamMetadataEvent(metadata, senderPrivkey) {
// Create tags for the stream metadata event
const tags = [
["version", metadata.version || "1"],
["encryption", metadata.encryption],
["compression", metadata.compression],
["binary", (!!metadata.binary).toString()]
];
// Add relay tags
for (const relay of metadata.relays) {
tags.push(["relay", relay]);
}
// If encryption is enabled, add the receiver_pubkey tag
if (metadata.encryption !== "none" && metadata.receiver_pubkey) {
tags.push(["receiver_pubkey", metadata.receiver_pubkey]);
}
// Create and sign the stream metadata event
return createEvent(STREAM_METADATA_KIND, "", tags, senderPrivkey);
}
/**
* Parses a stream metadata event (kind:173) into a StreamMetadata object
*
* @param event - Stream metadata event
* @returns StreamMetadata object
* @throws Error if the event is invalid
*/
export function parseStreamMetadataEvent(event) {
// Validate that it's a proper Nostr event
if (!validateNostrEvent(event)) {
throw new Error("Invalid Nostr event: signature verification failed");
}
// Validate that it's a stream metadata event
if (event.kind !== STREAM_METADATA_KIND) {
throw new Error(`Invalid event kind: ${event.kind}. Expected kind:${STREAM_METADATA_KIND} for stream metadata.`);
}
// Extract metadata from the event
const streamId = event.pubkey;
// Extract tags
const versionTag = event.tags.find((tag) => tag[0] === "version");
const encryptionTag = event.tags.find((tag) => tag[0] === "encryption");
const compressionTag = event.tags.find((tag) => tag[0] === "compression");
const binaryTag = event.tags.find((tag) => tag[0] === "binary");
const receiverPubkeyTag = event.tags.find((tag) => tag[0] === "receiver_pubkey");
const relayTags = event.tags.filter((tag) => tag[0] === "relay");
// Validate required tags
if (!versionTag) {
throw new Error("Missing 'version' tag in metadata event");
}
if (!encryptionTag) {
throw new Error("Missing 'encryption' tag in metadata event");
}
if (!compressionTag) {
throw new Error("Missing 'compression' tag in metadata event");
}
if (!binaryTag) {
throw new Error("Missing 'binary' tag in metadata event");
}
if (relayTags.length === 0) {
throw new Error("Missing 'relay' tags in metadata event");
}
// Create metadata object
const metadata = {
streamId,
version: versionTag[1],
encryption: encryptionTag[1],
compression: compressionTag[1],
binary: binaryTag[1] === "true",
relays: relayTags.map((tag) => tag[1]),
event: event
};
// Add receiver_pubkey if encryption is used
if (encryptionTag[1] !== "none" && receiverPubkeyTag) {
metadata.receiver_pubkey = receiverPubkeyTag[1];
}
return metadata;
}
//# sourceMappingURL=metadata.js.map