From 5d66ad916536fe701278da3673f3c75f1a1889de Mon Sep 17 00:00:00 2001 From: ennmichael Date: Mon, 27 Feb 2023 14:35:36 +0100 Subject: [PATCH] changes after self-review --- packages/nostr/src/client/index.ts | 4 +- packages/nostr/src/event.ts | 61 +++++++++++++++++++++++++----- packages/nostr/src/keypair.ts | 6 ++- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/packages/nostr/src/client/index.ts b/packages/nostr/src/client/index.ts index b07fa16..e91c91b 100644 --- a/packages/nostr/src/client/index.ts +++ b/packages/nostr/src/client/index.ts @@ -53,7 +53,7 @@ export class Nostr { } /** - * Connect and start communicating with a relay. This method recreates all existing + * Open a connection and start communicating with a relay. This method recreates all existing * subscriptions on the new relay as well. If there is already an existing connection, * this method will only update it with the new options, and an exception will be thrown * if no options are specified. @@ -122,7 +122,7 @@ export class Nostr { } /** - * Disconnect from relays. + * Close connections to relays. * * @param url If specified, only close the connection to this relay. If the connection does * not exist, an exception will be thrown. If this parameter is not specified, all connections diff --git a/packages/nostr/src/event.ts b/packages/nostr/src/event.ts index 5ed1d3d..edca5ee 100644 --- a/packages/nostr/src/event.ts +++ b/packages/nostr/src/event.ts @@ -96,20 +96,30 @@ export class EventId { } } -// TODO Document +/** + * A signed event. Provides access to the event data, ID, and signature. + */ export class SignedEvent { #event: Readonly #eventId: EventId #signature: string + /** + * Sign an event using the specified private key. The private key must match the + * public key from the event. + */ static async sign(event: Event, key: PrivateKey): Promise { const id = await EventId.create(event) const sig = secp.utils - .bytesToHex(await secp.schnorr.sign(id.toString(), key.leak())) + .bytesToHex(await secp.schnorr.sign(id.toString(), key.hexDangerous())) .toLowerCase() return new SignedEvent(event, id, sig) } + /** + * Verify the signature of a raw event. Throw a `ProtocolError` if the signature + * is invalid. + */ static async verify(raw: RawEvent): Promise { const id = await EventId.create(raw) if (id.toString() !== raw.id) { @@ -122,24 +132,28 @@ export class SignedEvent { } private constructor(event: Event, eventId: EventId, signature: string) { - // TODO Copy the event data and document that it's being copied - this.#event = event + this.#event = cloneEvent(event) this.#eventId = eventId this.#signature = signature } - // TODO Document this + /** + * Event ID. + */ get eventId(): EventId { return this.#eventId } - // TODO Document this + /** + * Event data. + */ get event(): Event { - // TODO Copy the event data and document that it's being copied - return this.#event + return cloneEvent(this.#event) } - // TODO Document this + /** + * Event signature. + */ get signature(): string { return this.#signature } @@ -250,6 +264,35 @@ function serializeEventContent(event: Event): string { } } +function cloneEvent(event: Event): Event { + const common = { + createdAt: structuredClone(event.createdAt), + pubkey: new PublicKey(event.pubkey.toString()), + } + if (event.kind === EventKind.SetMetadata) { + return { + kind: EventKind.SetMetadata, + userMetadata: { + about: event.userMetadata.about, + name: event.userMetadata.name, + picture: event.userMetadata.picture, + }, + ...common, + } + } else if (event.kind === EventKind.TextNote) { + return { + kind: EventKind.TextNote, + note: event.note, + ...common, + } + } else { + return { + kind: event.kind, + ...common, + } + } +} + function parseJson(data: string) { try { return JSON.parse(data) diff --git a/packages/nostr/src/keypair.ts b/packages/nostr/src/keypair.ts index 2935451..cfb9507 100644 --- a/packages/nostr/src/keypair.ts +++ b/packages/nostr/src/keypair.ts @@ -43,8 +43,10 @@ export class PrivateKey { return new PublicKey(secp.schnorr.getPublicKey(this.#hex)) } - // TODO Document this - leak(): string { + /** + * The hex representation of the private key. Use with caution! + */ + hexDangerous(): string { return this.#hex } }