diff --git a/packages/common/src/enums/index.ts b/packages/common/src/enums/index.ts index 6ea9a367..f0511a29 100644 --- a/packages/common/src/enums/index.ts +++ b/packages/common/src/enums/index.ts @@ -1,4 +1,3 @@ export * from './client.enum'; export * from './event.enum'; export * from './log.enum'; -export * from './message.enum'; diff --git a/packages/common/src/enums/message.enum.ts b/packages/common/src/enums/message.enum.ts deleted file mode 100644 index 71deba00..00000000 --- a/packages/common/src/enums/message.enum.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Message types - */ -export enum MessageType { - REQ = 'REQ', - EVENT = 'EVENT', - CLOSE = 'CLOSE', - AUTH = 'AUTH', - EOSE = 'EOSE', - OK = 'OK', - NOTICE = 'NOTICE', -} diff --git a/packages/common/src/interfaces/message.interface.ts b/packages/common/src/interfaces/message.interface.ts index 44c58700..f159c418 100644 --- a/packages/common/src/interfaces/message.interface.ts +++ b/packages/common/src/interfaces/message.interface.ts @@ -1,15 +1,18 @@ -import { MessageType } from '../enums'; import { EventId, SubscriptionId } from './common.interface'; import { Event } from './event.interface'; import { Filter } from './filter.interface'; -export type MessageTypeEvent = MessageType.EVENT | 'EVENT'; -export type MessageTypeReq = MessageType.REQ | 'REQ'; -export type MessageTypeClose = MessageType.CLOSE | 'CLOSE'; -export type MessageTypeAuth = MessageType.AUTH | 'AUTH'; -export type MessageTypeOk = MessageType.OK | 'OK'; -export type MessageTypeEose = MessageType.EOSE | 'EOSE'; -export type MessageTypeNotice = MessageType.NOTICE | 'NOTICE'; +export const MessageType = { + REQ: 'REQ', + EVENT: 'EVENT', + CLOSE: 'CLOSE', + AUTH: 'AUTH', + EOSE: 'EOSE', + OK: 'OK', + NOTICE: 'NOTICE', + CLOSED: 'CLOSED', +} as const; +export type TMessageType = (typeof MessageType)[keyof typeof MessageType]; export type IncomingMessage = | IncomingEventMessage @@ -17,20 +20,39 @@ export type IncomingMessage = | IncomingCloseMessage | IncomingAuthMessage; -export type IncomingEventMessage = [MessageTypeEvent, Event]; -export type IncomingReqMessage = [MessageTypeReq, SubscriptionId, ...Filter[]]; -export type IncomingCloseMessage = [MessageTypeClose, SubscriptionId]; -export type IncomingAuthMessage = [MessageTypeAuth, Event]; +export type IncomingEventMessage = [typeof MessageType.EVENT, Event]; +export type IncomingReqMessage = [ + typeof MessageType.REQ, + SubscriptionId, + ...Filter[], +]; +export type IncomingCloseMessage = [typeof MessageType.CLOSE, SubscriptionId]; +export type IncomingAuthMessage = [typeof MessageType.AUTH, Event]; export type OutgoingMessage = | OutgoingOkMessage | OutgoingEventMessage | OutgoingEoseMessage | OutgoingNoticeMessage - | OutgoingAuthMessage; + | OutgoingAuthMessage + | OutgoingClosedMessage; -export type OutgoingOkMessage = [MessageTypeOk, EventId, boolean, string]; -export type OutgoingEventMessage = [MessageTypeEvent, SubscriptionId, Event]; -export type OutgoingEoseMessage = [MessageTypeEose, SubscriptionId]; -export type OutgoingNoticeMessage = [MessageTypeNotice, string]; -export type OutgoingAuthMessage = [MessageTypeAuth, string]; +export type OutgoingOkMessage = [ + typeof MessageType.OK, + EventId, + boolean, + string, +]; +export type OutgoingEventMessage = [ + typeof MessageType.EVENT, + SubscriptionId, + Event, +]; +export type OutgoingEoseMessage = [typeof MessageType.EOSE, SubscriptionId]; +export type OutgoingNoticeMessage = [typeof MessageType.NOTICE, string]; +export type OutgoingAuthMessage = [typeof MessageType.AUTH, string]; +export type OutgoingClosedMessage = [ + typeof MessageType.CLOSED, + SubscriptionId, + string, +]; diff --git a/packages/core/__test__/nostr-relay.spec.ts b/packages/core/__test__/nostr-relay.spec.ts index 3738879b..3f0ad17c 100644 --- a/packages/core/__test__/nostr-relay.spec.ts +++ b/packages/core/__test__/nostr-relay.spec.ts @@ -228,12 +228,18 @@ describe('NostrRelay', () => { ); expect(result).toEqual({ events: [] }); - expect(client.send).toHaveBeenCalledWith( + expect(client.send).toHaveBeenNthCalledWith( + 1, JSON.stringify([ - MessageType.NOTICE, + MessageType.CLOSED, + subscriptionId, "restricted: we can't serve DMs to unauthenticated users, does your client implement NIP-42?", ]), ); + expect(client.send).toHaveBeenNthCalledWith( + 2, + JSON.stringify([MessageType.AUTH, ctx.id]), + ); }); it('should handle req successfully if client is authenticated and filter contains encrypted direct message kind', async () => { diff --git a/packages/core/src/interfaces/handle-result.interface.ts b/packages/core/src/interfaces/handle-result.interface.ts index e9d4c7ac..76974529 100644 --- a/packages/core/src/interfaces/handle-result.interface.ts +++ b/packages/core/src/interfaces/handle-result.interface.ts @@ -85,8 +85,8 @@ export type HandleAuthMessageResult = { * Result of handling an incoming message */ export type HandleMessageResult = - | ({ messageType: MessageType.REQ } & HandleReqMessageResult) - | ({ messageType: MessageType.EVENT } & HandleEventMessageResult) - | ({ messageType: MessageType.CLOSE } & HandleCloseMessageResult) - | ({ messageType: MessageType.AUTH } & HandleAuthMessageResult) + | ({ messageType: typeof MessageType.REQ } & HandleReqMessageResult) + | ({ messageType: typeof MessageType.EVENT } & HandleEventMessageResult) + | ({ messageType: typeof MessageType.CLOSE } & HandleCloseMessageResult) + | ({ messageType: typeof MessageType.AUTH } & HandleAuthMessageResult) | void; diff --git a/packages/core/src/nostr-relay.ts b/packages/core/src/nostr-relay.ts index d27ffd7d..19939a6a 100644 --- a/packages/core/src/nostr-relay.ts +++ b/packages/core/src/nostr-relay.ts @@ -29,6 +29,7 @@ import { SubscriptionService } from './services/subscription.service'; import { LazyCache, createOutgoingAuthMessage, + createOutgoingClosedMessage, createOutgoingEoseMessage, createOutgoingEventMessage, createOutgoingNoticeMessage, @@ -252,10 +253,12 @@ export class NostrRelay { !ctx.pubkey ) { ctx.sendMessage( - createOutgoingNoticeMessage( + createOutgoingClosedMessage( + subscriptionId, "restricted: we can't serve DMs to unauthenticated users, does your client implement NIP-42?", ), ); + ctx.sendMessage(createOutgoingAuthMessage(ctx.id)); return { events }; } diff --git a/packages/core/src/utils/response.ts b/packages/core/src/utils/response.ts index 7bc5c604..12472757 100644 --- a/packages/core/src/utils/response.ts +++ b/packages/core/src/utils/response.ts @@ -2,6 +2,7 @@ import { Event, MessageType, OutgoingAuthMessage, + OutgoingClosedMessage, OutgoingEoseMessage, OutgoingEventMessage, OutgoingNoticeMessage, @@ -74,3 +75,17 @@ export function createOutgoingAuthMessage( ): OutgoingAuthMessage { return [MessageType.AUTH, challenge]; } + +/** + * Create an outgoing CLOSED message. + * More info: https://github.com/nostr-protocol/nips/blob/master/01.md + * + * @param subscriptionId Subscription Id + * @param message Reason for closing the subscription + */ +export function createOutgoingClosedMessage( + subscriptionId: SubscriptionId, + message = '', +): OutgoingClosedMessage { + return [MessageType.CLOSED, subscriptionId, message]; +}