Skip to content

feat: add NIP-45 Event Count support#522

Merged
cameri merged 7 commits intocameri:mainfrom
a-khushal:feat/nip45-count
Apr 21, 2026
Merged

feat: add NIP-45 Event Count support#522
cameri merged 7 commits intocameri:mainfrom
a-khushal:feat/nip45-count

Conversation

@a-khushal
Copy link
Copy Markdown
Contributor

@a-khushal a-khushal commented Apr 19, 2026

This PR adds NIP-45 COUNT support to nostream, including message validation, handler flow, and database counting by filters. It also adds tests for COUNT behavior and updates supported NIPs docs to include NIP-45.

Description

This PR adds NIP-45 COUNT support, so clients can ask the relay for a count directly instead of downloading many events to count on their side. It adds COUNT validation, COUNT/CLOSED handling, database counting by filters, and tests for the new behavior

Related Issue

nostream#341

Motivation and Context

This adds NIP-45 COUNT so clients can ask for a count directly from the relay. It saves bandwidth and is faster than downloading many events just to count them.

How Has This Been Tested?

by running automated test for the new COUNT feature, unit tests for message schema, message handler factory, count message handler, and repository count logic, also ran npm run lint and npm run build:check

manual testing done on Postman by connecting to ws://127.0.0.1:8008

  1. valid count
["COUNT","q1",{"kinds":[1]}] 

received:
["COUNT","q1",{"count":0}]
  1. Oversized count (validation error)
sent:
["COUNT","q3",{"kinds":[1]},{"kinds":[2]},{"kinds":[3]},{"kinds":[4]},{"kinds":[5]},{"kinds":[6]},{"kinds":[7]},{"kinds":[8]},{"kinds":[9]},{"kinds":[10]},{"kinds":[11]}]

received:
["NOTICE","invalid: COUNT message must contain at most 12 elements"]

Screenshots (if appropriate):

COUNT Success Response COUNT Error Case
COUNT Success COUNT Error

Types of changes

  • Non-functional change (docs, style, minor refactor)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my code changes.
  • I added a changeset, or this is docs-only and I added an empty changeset.
  • All new and existing tests passed.

@a-khushal a-khushal marked this pull request as ready for review April 19, 2026 04:29
@coveralls
Copy link
Copy Markdown
Collaborator

coveralls commented Apr 19, 2026

Coverage Status

coverage: 73.738% (+0.4%) from 73.323% — a-khushal:feat/nip45-count into cameri:main

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds NIP-45 COUNT support to nostream so clients can request event counts by filter without fetching full event streams.

Changes:

  • Introduces COUNT/CLOSED message types, validation schema, and outgoing message helpers.
  • Adds CountMessageHandler + message handler factory routing to execute counts and respond with COUNT (or CLOSED on rejection/failure).
  • Implements EventRepository.countByFilters() with unit tests, and documents NIP-45 support (README + package metadata + changeset).

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/unit/schemas/message-schema.spec.ts Adds unit coverage for COUNT message validation rules (required query id, filter presence, max elements).
test/unit/repositories/event-repository.spec.ts Adds unit coverage for countByFilters query construction and return parsing.
test/unit/handlers/count-message-handler.spec.ts New unit tests for COUNT handler behavior (success, dedupe, limits, error -> CLOSED).
test/unit/factories/message-handler-factory.spec.ts Ensures COUNT messages are routed to CountMessageHandler.
src/utils/messages.ts Adds helpers to create NIP-45 COUNT and CLOSED outgoing messages.
src/schemas/message-schema.ts Extends incoming message validation to include COUNT messages (min/max elements + filter schema).
src/repositories/event-repository.ts Implements countByFilters using existing filter-query patterns plus deleted/expired filtering.
src/handlers/count-message-handler.ts New handler to validate COUNT requests against limits and emit COUNT/CLOSED responses.
src/factories/message-handler-factory.ts Routes MessageType.COUNT to the new handler.
src/@types/repositories.ts Extends IEventRepository with countByFilters.
src/@types/messages.ts Adds COUNT/CLOSED message types and payload typings for NIP-45.
package.json Adds NIP-45 to supported NIPs list.
README.md Documents NIP-45 support in the supported NIPs section.
.changeset/full-donuts-allow.md Declares a minor release for adding NIP-45 COUNT support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/handlers/count-message-handler.ts Outdated
Comment thread src/repositories/event-repository.ts
@cameri
Copy link
Copy Markdown
Owner

cameri commented Apr 19, 2026

Could you please test the performance of your implementation with the events I shared here: https://t.me/nostream_sob_2026/1/194

Are indexes properly being used?

}

private canCount(queryId: SubscriptionId, filters: SubscriptionFilter[]): string | undefined {
const subscriptionLimits = this.settings().limits?.client?.subscription
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a setting to enable or disable COUNT. We can have it enabled by default.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed settings to toggle COUNT here; 666f8a6, 1de0a5b

Comment thread src/repositories/event-repository.ts
@a-khushal
Copy link
Copy Markdown
Contributor Author

a-khushal commented Apr 19, 2026

Could you please test the performance of your implementation with the events I shared here: https://t.me/nostream_sob_2026/1/194

Are indexes properly being used?

@cameri I've tested with the events you shared, and yes the indexes are being used here

Dataset size loaded
---
Author COUNT explain and result
---
Tag COUNT explain and result

@cameri
Copy link
Copy Markdown
Owner

cameri commented Apr 20, 2026

CI checks are failing, we are using pino now for logging, not debug

@a-khushal a-khushal force-pushed the feat/nip45-count branch 3 times, most recently from a4dce5d to e77a599 Compare April 20, 2026 11:14
@cameri cameri merged commit 7edd6c3 into cameri:main Apr 21, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants