Second increment of the NDK -> nostr-tools transport swap. The daemon's backend
signing path no longer uses NDK at all.
- nip46/transport.ts: the NIP-46 RPC wire layer over the RelayPool, replacing
NDKNostrRpc. Same crypto + framing so existing clients (lnbits, the spire) are
unaffected byte-for-byte: adaptive nip04/nip44 envelope (nip04 iff content has
`?iv=`, fallback to the other), verify the kind:24133 signature, JSON
`{id,method,params}` in / `{id,result,error}` out, signed as the held key and
`#p`-tagged to the client.
- backend/index.ts: the Backend is rebuilt on that transport instead of
`extends NDKNip46Backend`. The dispatch + response strings match NDK's
strategies exactly (connect->ack, ping->pong, get_public_key, sign_event->
signed event JSON, nip04/44 encrypt/decrypt, reject->error/"Not authorized").
The ACL hook (pubkeyAllowed -> permitCallback) is unchanged; the ACL only
reads `.kind` off the sign_event payload, so a plain parsed event suffices.
- backend/token-store.ts: the prisma-backed connection-token redemption
(validateToken/applyToken) split out of the Backend and injected, so the
protocol layer has no database dependency and is unit-testable. Logic
unchanged (#24/#25 live-lifecycle semantics preserved).
- run.ts: the daemon now drives a RelayPool (heartbeat on) for the backend
transport instead of an NDK instance + attachIndefiniteReconnect; startKey
wires the prisma applyToken.
- relay-pool.ts: publish() now retries across a reconnect window — a publish
that lands mid-flap rejects ("relay connection errored"), so we wait for the
pool to recover and retry (relays dedupe by id; clients match by request id).
Test (tests/nip46-backend.test.ts): a real nostr-tools NIP-46 client drives
connect/ping/get_public_key/sign_event/nip44_encrypt through a mock relay,
asserts each response, FLAPS the relay, and asserts the backend still answers —
then checks the deny path returns "Not authorized". Green. lifecycle + relay
suites unchanged.
The admin interface (NDKRpc) + the getKeys listing still use NDK; that's the
next increment. NDK remains a dependency until then.
Refs: #42, #41, #25, #24, #21, #9