mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-03-11 05:18:32 +00:00
3.3 KiB
3.3 KiB
Nostr Wallet Connect Coverage
This note cross-references Bitvid's current Nostr Wallet Connect (NIP-47) implementation with the official specification so we can quickly spot regressions or missing features.
URI handling
parseNwcUri()accepts all aliases we see in the wild (nostr+walletconnect://,walletconnect://, andnwc://) and rejects unknown schemes before continuing. It extracts the wallet pubkey, all relay query parameters, and the 32-byte secret required for signing. The helper lowercases the secret, reserializes the URI in canonical form, and derives the client public key from the secret so downstream calls can sign events without leaking user keys.
Connection lifecycle
ensureActiveState()caches the parsed connection and keeps WebSocket state so repeated actions reuse the same subscription. When a new URI is supplied we tear down the previous socket, update the relay list, and reset encryption state before reconnecting.connectSocket()opens a WebSocket to the relay, subscribes to kind23195responses authored by the wallet and addressed to the client pubkey, and hooks message/error/close callbacks so we can retry or surface failures.
Request flow
ensureWallet()validates that the user configured an NWC URI, connects to the relay if needed, and negotiates an encryption scheme before returning the active context.encryptRequestPayload()serializes the JSON-RPC payload, encrypts it with the selected scheme, and creates the Nostr event with kind23194,pubkeyset to the client key, aptag pointing at the wallet, and anencryptiontag mirroring the algorithm that was used. Events are signed with the secret from the connection URI so relays will accept them.sendPayment()constructs thepay_invoicerequest, attaches a uniqueid, and dispatches it over the relay.
Response flow
subscribeToResponses()issues aREQfor kind23195events authored by the wallet and tagged for the client.handleSocketMessage()decrypts responses, matches them against pendingids (or theetag), clears pending timeouts, and surfaces either theresultorerror.code/error.messageback to callers.
Encryption negotiation
requestInfoEvent()fetches the wallet's replaceable kind13194info note and passes the result togetWalletSupportedEncryption()so we only pick schemes advertised by the wallet service.getEncryptionCandidates()prefers NIP-44 (nip44_v2) when both sides support it and falls back to NIP-04 when necessary. We also remember schemes that failed so future retries skip them.
Current gaps
- We only connect to the first relay supplied by the URI. If a wallet publishes multiple relays we should consider retrying additional ones when the primary is offline.
- The client currently implements the
pay_invoicecommand. Other optional commands (make_invoice,get_balance,multi_pay_invoice, etc.) and notification handling (kinds23196/23197) would require follow-up work. - Wallet responses that signal
UNSUPPORTED_ENCRYPTIONas an error today bubble straight back to the caller. The transport already retries once when we encounter that error during submission, but we could add richer UX (e.g. prompting the user to reconnect) in the future.