• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cameri / nostream / 24592723639

18 Apr 2026 12:37AM UTC coverage: 45.889% (-0.9%) from 46.793%
24592723639

push

github

web-flow
feat: implement NIP-17 & NIP-44 v2 for Modern Direct Messages (#458)

* feat: implement NIP-17 & NIP-44 v2 for Modern Direct Messages

This commit introduces comprehensive support for NIP-17 (Private Direct Messages)
and NIP-44 v2 (Encrypted Payloads), establishing the modern standard for
secure messaging on Nostr.

Changes included:
- **NIP-17 Support**:
  - Added new Event Kinds: Seal (13), Direct Message (14), File Message (15), and Gift Wrap (1059).
  - Implemented `GiftWrapEventStrategy` to handle and validate incoming Gift Wrap events.
  - Added repository-level protections to block direct relay publication of inner events (Kinds 13, 14, 15), mandating they be encrypted inside a Gift Wrap.
- **NIP-44 v2 Crypto**:
  - Implemented `nip44Encrypt` and `nip44Decrypt` functions supporting ChaCha20, HKDF extraction/expansion, and MAC verification as per NIP-44 v2 specifications.
  - Added `validateNip44Payload` to ensure payloads adhere to the exact format requirements without needing to decrypt them.
- **Cleanup**:
  - Removed deprecated `encryptKind4Event` (legacy NIP-04 DM algorithm) from `event.ts`.
  - Updated `package.json` to declare NIPs 17 and 44 in `supportedNipExtensions`.
- **Tests**:
  - Added extensive unit tests across NIP-44 encryption logic, Event Strategies, and Message Handlers.
  - Resolved `sort-imports` ESLint violations in multiple handler specs.

* fix: address NIP-17/NIP-44 security review findings

- nip44: replace dead try/catch with explicit base64 regex + length%4 check
- gift-wrap: validate recipient p tag is a 64-char lowercase hex pubkey; fix error message
- mirroring worker: block inner event kinds (13/14/15) from being persisted directly

433 of 1065 branches covered (40.66%)

Branch coverage included in aggregate %.

118 of 271 new or added lines in 6 files covered. (43.54%)

87 existing lines in 10 files now uncovered.

1258 of 2620 relevant lines covered (48.02%)

3.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

37.5
/src/cache/client.ts
1
import { createClient, RedisClientOptions } from 'redis'
1✔
2
import { CacheClient } from '../@types/cache'
3
import { createLogger } from '../factories/logger-factory'
1✔
4

5

6
const debug = createLogger('cache-client')
1✔
7

8
export const getCacheConfig = (): RedisClientOptions => ({
1✔
9
  url: process.env.REDIS_URI ? process.env.REDIS_URI : `redis://${process.env.REDIS_USER}:${process.env.REDIS_PASSWORD}@${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`,
×
10
  password: process.env.REDIS_PASSWORD,
11
})
12

13
let instance: CacheClient | undefined = undefined
1✔
14

15
export const getCacheClient = (): CacheClient => {
1✔
UNCOV
16
  if (!instance) {
×
UNCOV
17
    const config = getCacheConfig()
×
18
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
UNCOV
19
    const { password: _, ...loggableConfig } = config
×
UNCOV
20
    debug('config: %o', loggableConfig)
×
UNCOV
21
    instance = createClient(config)
×
22
  }
23

UNCOV
24
  return instance
×
25
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc