nostr-core 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,6 +25,7 @@ nwc.close()
25
25
  - **Full NIP-47 coverage** - `pay_invoice`, `get_balance`, `make_invoice`, `list_transactions`, `pay_keysend`, `sign_message`, and more
26
26
  - **Auto-encryption** - detects NIP-04 or NIP-44 support and handles it transparently
27
27
  - **Typed errors** - specific error classes for timeouts, connection failures, wallet rejections, and decryption issues
28
+ - **Signer abstraction** - unified `Signer` interface for secret keys, browser extensions (NIP-07), and remote signers (NIP-46)
28
29
  - **Zero framework deps** - built on audited [noble](https://paulmillr.com/noble/) cryptography libraries only
29
30
  - **ESM-only** - tree-shakeable, modern JavaScript
30
31
 
@@ -177,6 +178,9 @@ import {
177
178
  // Key management
178
179
  generateSecretKey, getPublicKey,
179
180
 
181
+ // Signer abstraction
182
+ createSecretKeySigner, Nip07Signer, NostrConnect,
183
+
180
184
  // Events
181
185
  finalizeEvent, verifyEvent, getEventHash, serializeEvent, validateEvent,
182
186
 
@@ -189,6 +193,9 @@ import {
189
193
  // Bech32 encoding
190
194
  nip19,
191
195
 
196
+ // NIP-07 & NIP-46
197
+ nip07, nip46,
198
+
192
199
  // Filters
193
200
  matchFilter, matchFilters,
194
201
 
@@ -217,6 +224,21 @@ If you've used `@getalby/sdk` before, here's why `nostr-core` is a better fit fo
217
224
 
218
225
  See the full [comparison guide](./docs/guide/comparison.md) for details.
219
226
 
227
+ ## Agent Skills (Claude Code Plugin)
228
+
229
+ nostr-core ships as a [Claude Code plugin](https://code.claude.com/docs/en/plugins) with 4 skills for AI agents building Lightning-enabled apps:
230
+
231
+ | Skill | Description |
232
+ |-------|-------------|
233
+ | `/nwc-integrate` | Set up nostr-core and connect to any NWC wallet |
234
+ | `/lightning-pay` | Pay invoices, Lightning Addresses, fiat, and keysend |
235
+ | `/wallet-monitor` | Real-time notifications, transaction history, analytics |
236
+ | `/nostr-primitives` | Low-level keys, events, relays, encryption, encoding |
237
+
238
+ Install: `/plugin install nostr-core-org/nostr-core`
239
+
240
+ See the [Skills documentation](./docs/skills.md) and [Agent README](./AGENT_README.md) for details.
241
+
220
242
  ## Dependencies
221
243
 
222
244
  | Package | Purpose |
package/dist/index.d.ts CHANGED
@@ -11,6 +11,20 @@ export type { Filter } from './filter.js';
11
11
  export * as nip04 from './nip04.js';
12
12
  export * as nip44 from './nip44.js';
13
13
  export * as nip19 from './nip19.js';
14
+ export * as nip07 from './nip07.js';
15
+ export * as nip46 from './nip46.js';
16
+ export * as nip59 from './nip59.js';
17
+ export * as nip17 from './nip17.js';
18
+ export type { Signer, RelayMap } from './signer.js';
19
+ export { createSecretKeySigner } from './signer.js';
20
+ export { Nip07Signer, getExtension, Nip07Error, Nip07NotAvailableError } from './nip07.js';
21
+ export type { Nip07Extension } from './nip07.js';
22
+ export { NostrConnect, parseConnectionURI, Nip46Error, Nip46TimeoutError, Nip46ConnectionError, Nip46RemoteError } from './nip46.js';
23
+ export type { Nip46ConnectionOptions, Nip46Method, Nip46AppMetadata } from './nip46.js';
24
+ export { createRumor, createSeal, createWrap, unwrap } from './nip59.js';
25
+ export type { Rumor } from './nip59.js';
26
+ export { wrapDirectMessage, unwrapDirectMessage } from './nip17.js';
27
+ export type { DirectMessage } from './nip17.js';
14
28
  export { Relay, Subscription } from './relay.js';
15
29
  export type { SubscriptionParams } from './relay.js';
16
30
  export { RelayPool } from './pool.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG9B,YAAY,EACV,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,QAAQ,EACR,cAAc,GACf,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAGtG,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGnE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG7D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AACpH,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAGzF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAGnC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAG/D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG9B,YAAY,EACV,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,QAAQ,EACR,cAAc,GACf,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAGtG,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGnE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG7D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AACpH,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAGzF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAGnC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAGnD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAC1F,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAGhD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACpI,YAAY,EAAE,sBAAsB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAGvF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxE,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAGvC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACnE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAG/D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -16,6 +16,19 @@ export { matchFilter, matchFilters } from './filter.js';
16
16
  export * as nip04 from './nip04.js';
17
17
  export * as nip44 from './nip44.js';
18
18
  export * as nip19 from './nip19.js';
19
+ export * as nip07 from './nip07.js';
20
+ export * as nip46 from './nip46.js';
21
+ export * as nip59 from './nip59.js';
22
+ export * as nip17 from './nip17.js';
23
+ export { createSecretKeySigner } from './signer.js';
24
+ // NIP-07
25
+ export { Nip07Signer, getExtension, Nip07Error, Nip07NotAvailableError } from './nip07.js';
26
+ // NIP-46
27
+ export { NostrConnect, parseConnectionURI, Nip46Error, Nip46TimeoutError, Nip46ConnectionError, Nip46RemoteError } from './nip46.js';
28
+ // NIP-59
29
+ export { createRumor, createSeal, createWrap, unwrap } from './nip59.js';
30
+ // NIP-17
31
+ export { wrapDirectMessage, unwrapDirectMessage } from './nip17.js';
19
32
  // Networking
20
33
  export { Relay, Subscription } from './relay.js';
21
34
  export { RelayPool } from './pool.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AA2B9B,gBAAgB;AAChB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAEtG,kBAAkB;AAClB,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEnE,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE7D,eAAe;AACf,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAGpH,UAAU;AACV,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAGvD,OAAO;AACP,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGrC,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AA2B9B,gBAAgB;AAChB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAEtG,kBAAkB;AAClB,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEnE,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE7D,eAAe;AACf,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAGpH,UAAU;AACV,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAGvD,OAAO;AACP,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAInC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAG1F,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAGpI,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGxE,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGnE,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGrC,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,44 @@
1
+ import type { EventTemplate, VerifiedEvent } from './event.js';
2
+ import type { Signer, RelayMap } from './signer.js';
3
+ export declare class Nip07Error extends Error {
4
+ code: string;
5
+ constructor(message: string, code?: string);
6
+ }
7
+ export declare class Nip07NotAvailableError extends Nip07Error {
8
+ constructor(message?: string);
9
+ }
10
+ export interface Nip07Extension {
11
+ getPublicKey(): Promise<string>;
12
+ signEvent(event: EventTemplate): Promise<VerifiedEvent>;
13
+ nip04?: {
14
+ encrypt(pubkey: string, plaintext: string): Promise<string>;
15
+ decrypt(pubkey: string, ciphertext: string): Promise<string>;
16
+ };
17
+ nip44?: {
18
+ encrypt(pubkey: string, plaintext: string): Promise<string>;
19
+ decrypt(pubkey: string, ciphertext: string): Promise<string>;
20
+ };
21
+ getRelays?(): Promise<RelayMap>;
22
+ }
23
+ declare global {
24
+ interface Window {
25
+ nostr?: Nip07Extension;
26
+ }
27
+ }
28
+ export declare function getExtension(): Nip07Extension;
29
+ export declare class Nip07Signer implements Signer {
30
+ private ext;
31
+ constructor();
32
+ getPublicKey(): Promise<string>;
33
+ signEvent(event: EventTemplate): Promise<VerifiedEvent>;
34
+ nip04: {
35
+ encrypt: (pubkey: string, plaintext: string) => Promise<string>;
36
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
37
+ };
38
+ nip44: {
39
+ encrypt: (pubkey: string, plaintext: string) => Promise<string>;
40
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
41
+ };
42
+ getRelays(): Promise<RelayMap>;
43
+ }
44
+ //# sourceMappingURL=nip07.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip07.d.ts","sourceRoot":"","sources":["../src/nip07.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAInD,qBAAa,UAAW,SAAQ,KAAK;IACnC,IAAI,EAAE,MAAM,CAAA;gBACA,OAAO,EAAE,MAAM,EAAE,IAAI,SAAgB;CAKlD;AAED,qBAAa,sBAAuB,SAAQ,UAAU;gBACxC,OAAO,SAA+D;CAInF;AAID,MAAM,WAAW,cAAc;IAC7B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/B,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACvD,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QAC3D,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KAC7D,CAAA;IACD,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QAC3D,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KAC7D,CAAA;IACD,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAA;CAChC;AAID,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,KAAK,CAAC,EAAE,cAAc,CAAA;KACvB;CACF;AAID,wBAAgB,YAAY,IAAI,cAAc,CAK7C;AAID,qBAAa,WAAY,YAAW,MAAM;IACxC,OAAO,CAAC,GAAG,CAAgB;;IAMrB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ/B,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAQ7D,KAAK;0BACqB,MAAM,aAAa,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;0BAU3C,MAAM,cAAc,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;MASrE;IAED,KAAK;0BACqB,MAAM,aAAa,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;0BAU3C,MAAM,cAAc,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;MASrE;IAEK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC;CAUrC"}
package/dist/nip07.js ADDED
@@ -0,0 +1,105 @@
1
+ // Error classes
2
+ export class Nip07Error extends Error {
3
+ code;
4
+ constructor(message, code = 'NIP07_ERROR') {
5
+ super(message);
6
+ this.name = 'Nip07Error';
7
+ this.code = code;
8
+ }
9
+ }
10
+ export class Nip07NotAvailableError extends Nip07Error {
11
+ constructor(message = 'NIP-07 extension not available (window.nostr is undefined)') {
12
+ super(message, 'NIP07_NOT_AVAILABLE');
13
+ this.name = 'Nip07NotAvailableError';
14
+ }
15
+ }
16
+ // Helpers
17
+ export function getExtension() {
18
+ if (typeof window === 'undefined' || !window.nostr) {
19
+ throw new Nip07NotAvailableError();
20
+ }
21
+ return window.nostr;
22
+ }
23
+ // Signer implementation
24
+ export class Nip07Signer {
25
+ ext;
26
+ constructor() {
27
+ this.ext = getExtension();
28
+ }
29
+ async getPublicKey() {
30
+ try {
31
+ return await this.ext.getPublicKey();
32
+ }
33
+ catch (err) {
34
+ throw new Nip07Error(`getPublicKey failed: ${err.message}`);
35
+ }
36
+ }
37
+ async signEvent(event) {
38
+ try {
39
+ return await this.ext.signEvent(event);
40
+ }
41
+ catch (err) {
42
+ throw new Nip07Error(`signEvent failed: ${err.message}`);
43
+ }
44
+ }
45
+ nip04 = {
46
+ encrypt: async (pubkey, plaintext) => {
47
+ const nip04 = this.ext.nip04;
48
+ if (!nip04)
49
+ throw new Nip07Error('Extension does not support NIP-04', 'NIP07_NIP04_UNSUPPORTED');
50
+ try {
51
+ return await nip04.encrypt(pubkey, plaintext);
52
+ }
53
+ catch (err) {
54
+ throw new Nip07Error(`nip04.encrypt failed: ${err.message}`);
55
+ }
56
+ },
57
+ decrypt: async (pubkey, ciphertext) => {
58
+ const nip04 = this.ext.nip04;
59
+ if (!nip04)
60
+ throw new Nip07Error('Extension does not support NIP-04', 'NIP07_NIP04_UNSUPPORTED');
61
+ try {
62
+ return await nip04.decrypt(pubkey, ciphertext);
63
+ }
64
+ catch (err) {
65
+ throw new Nip07Error(`nip04.decrypt failed: ${err.message}`);
66
+ }
67
+ },
68
+ };
69
+ nip44 = {
70
+ encrypt: async (pubkey, plaintext) => {
71
+ const nip44 = this.ext.nip44;
72
+ if (!nip44)
73
+ throw new Nip07Error('Extension does not support NIP-44', 'NIP07_NIP44_UNSUPPORTED');
74
+ try {
75
+ return await nip44.encrypt(pubkey, plaintext);
76
+ }
77
+ catch (err) {
78
+ throw new Nip07Error(`nip44.encrypt failed: ${err.message}`);
79
+ }
80
+ },
81
+ decrypt: async (pubkey, ciphertext) => {
82
+ const nip44 = this.ext.nip44;
83
+ if (!nip44)
84
+ throw new Nip07Error('Extension does not support NIP-44', 'NIP07_NIP44_UNSUPPORTED');
85
+ try {
86
+ return await nip44.decrypt(pubkey, ciphertext);
87
+ }
88
+ catch (err) {
89
+ throw new Nip07Error(`nip44.decrypt failed: ${err.message}`);
90
+ }
91
+ },
92
+ };
93
+ async getRelays() {
94
+ if (!this.ext.getRelays) {
95
+ throw new Nip07Error('Extension does not support getRelays', 'NIP07_RELAYS_UNSUPPORTED');
96
+ }
97
+ try {
98
+ return await this.ext.getRelays();
99
+ }
100
+ catch (err) {
101
+ throw new Nip07Error(`getRelays failed: ${err.message}`);
102
+ }
103
+ }
104
+ }
105
+ //# sourceMappingURL=nip07.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip07.js","sourceRoot":"","sources":["../src/nip07.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { NostrEvent } from './event.js';
2
+ export type DirectMessage = {
3
+ sender: string;
4
+ content: string;
5
+ tags: string[][];
6
+ created_at: number;
7
+ id: string;
8
+ };
9
+ export declare function wrapDirectMessage(content: string, senderSecretKey: Uint8Array, recipientPubkey: string, tags?: string[][]): NostrEvent;
10
+ export declare function unwrapDirectMessage(wrap: NostrEvent, recipientSecretKey: Uint8Array): DirectMessage;
11
+ //# sourceMappingURL=nip17.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip17.d.ts","sourceRoot":"","sources":["../src/nip17.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAO5C,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAID,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,UAAU,EAC3B,eAAe,EAAE,MAAM,EACvB,IAAI,GAAE,MAAM,EAAE,EAAO,GACpB,UAAU,CAeZ;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,kBAAkB,EAAE,UAAU,GAC7B,aAAa,CAcf"}
package/dist/nip17.js ADDED
@@ -0,0 +1,30 @@
1
+ import { getPublicKey } from './crypto.js';
2
+ import { createRumor, createSeal, createWrap, unwrap } from './nip59.js';
3
+ // Kind constants
4
+ const DM_KIND = 14;
5
+ // Public API
6
+ export function wrapDirectMessage(content, senderSecretKey, recipientPubkey, tags = []) {
7
+ const senderPubkey = getPublicKey(senderSecretKey);
8
+ const rumor = createRumor({
9
+ kind: DM_KIND,
10
+ tags: [['p', recipientPubkey], ...tags],
11
+ content,
12
+ created_at: Math.floor(Date.now() / 1000),
13
+ }, senderPubkey);
14
+ const seal = createSeal(rumor, senderSecretKey, recipientPubkey);
15
+ return createWrap(seal, recipientPubkey);
16
+ }
17
+ export function unwrapDirectMessage(wrap, recipientSecretKey) {
18
+ const rumor = unwrap(wrap, recipientSecretKey);
19
+ if (rumor.kind !== DM_KIND) {
20
+ throw new Error(`Expected kind ${DM_KIND} direct message, got kind ${rumor.kind}`);
21
+ }
22
+ return {
23
+ sender: rumor.pubkey,
24
+ content: rumor.content,
25
+ tags: rumor.tags,
26
+ created_at: rumor.created_at,
27
+ id: rumor.id,
28
+ };
29
+ }
30
+ //# sourceMappingURL=nip17.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip17.js","sourceRoot":"","sources":["../src/nip17.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGxE,iBAAiB;AACjB,MAAM,OAAO,GAAG,EAAE,CAAA;AAYlB,aAAa;AAEb,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,eAA2B,EAC3B,eAAuB,EACvB,OAAmB,EAAE;IAErB,MAAM,YAAY,GAAG,YAAY,CAAC,eAAe,CAAC,CAAA;IAElD,MAAM,KAAK,GAAG,WAAW,CACvB;QACE,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,GAAG,IAAI,CAAC;QACvC,OAAO;QACP,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;KAC1C,EACD,YAAY,CACb,CAAA;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;IAChE,OAAO,UAAU,CAAC,IAAI,EAAE,eAAe,CAAC,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,IAAgB,EAChB,kBAA8B;IAE9B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;IAE9C,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,6BAA6B,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;IACpF,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,EAAE,EAAE,KAAK,CAAC,EAAE;KACb,CAAA;AACH,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { type EventTemplate, type VerifiedEvent } from './event.js';
2
+ import type { Signer, RelayMap } from './signer.js';
3
+ export declare class Nip46Error extends Error {
4
+ code: string;
5
+ constructor(message: string, code?: string);
6
+ }
7
+ export declare class Nip46TimeoutError extends Nip46Error {
8
+ constructor(message: string);
9
+ }
10
+ export declare class Nip46ConnectionError extends Nip46Error {
11
+ constructor(message: string);
12
+ }
13
+ export declare class Nip46RemoteError extends Nip46Error {
14
+ constructor(message: string);
15
+ }
16
+ export type Nip46Method = 'connect' | 'disconnect' | 'describe' | 'get_public_key' | 'sign_event' | 'nip04_encrypt' | 'nip04_decrypt' | 'nip44_encrypt' | 'nip44_decrypt' | 'get_relays';
17
+ export type Nip46ConnectionOptions = {
18
+ remotePubkey: string;
19
+ relayUrls: string[];
20
+ secretKey?: Uint8Array;
21
+ secret?: string;
22
+ };
23
+ export type Nip46AppMetadata = {
24
+ name?: string;
25
+ url?: string;
26
+ image?: string;
27
+ };
28
+ export declare function parseConnectionURI(uri: string): Nip46ConnectionOptions & {
29
+ appMetadata?: Nip46AppMetadata;
30
+ };
31
+ export declare class NostrConnect implements Signer {
32
+ private remotePubkey;
33
+ private relayUrls;
34
+ private secretKey;
35
+ private publicKey;
36
+ private relay;
37
+ private secret?;
38
+ private _connected;
39
+ private pendingRequests;
40
+ private sub;
41
+ timeout: number;
42
+ constructor(connectionOrOpts: string | Nip46ConnectionOptions);
43
+ get connected(): boolean;
44
+ connect(): Promise<void>;
45
+ disconnect(): Promise<void>;
46
+ close(): void;
47
+ describe(): Promise<string[]>;
48
+ getPublicKey(): Promise<string>;
49
+ signEvent(event: EventTemplate): Promise<VerifiedEvent>;
50
+ nip04: {
51
+ encrypt: (pubkey: string, plaintext: string) => Promise<string>;
52
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
53
+ };
54
+ nip44: {
55
+ encrypt: (pubkey: string, plaintext: string) => Promise<string>;
56
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
57
+ };
58
+ getRelays(): Promise<RelayMap>;
59
+ private _sendRequest;
60
+ private _handleResponse;
61
+ }
62
+ //# sourceMappingURL=nip46.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip46.d.ts","sourceRoot":"","sources":["../src/nip46.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,aAAa,EAAmB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAInG,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAOnD,qBAAa,UAAW,SAAQ,KAAK;IACnC,IAAI,EAAE,MAAM,CAAA;gBACA,OAAO,EAAE,MAAM,EAAE,IAAI,SAAgB;CAKlD;AAED,qBAAa,iBAAkB,SAAQ,UAAU;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,oBAAqB,SAAQ,UAAU;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,gBAAiB,SAAQ,UAAU;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAID,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,YAAY,GACZ,UAAU,GACV,gBAAgB,GAChB,YAAY,GACZ,eAAe,GACf,eAAe,GACf,eAAe,GACf,eAAe,GACf,YAAY,CAAA;AAEhB,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAUD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG;IAAE,WAAW,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAoC3G;AAID,qBAAa,YAAa,YAAW,MAAM;IACzC,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,GAAG,CAAkD;IAEtD,OAAO,SAAQ;gBAEV,gBAAgB,EAAE,MAAM,GAAG,sBAAsB;IAY7D,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoDxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUjC,KAAK,IAAI,IAAI;IAaP,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAO7B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAI/B,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAK7D,KAAK;0BACqB,MAAM,aAAa,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;0BAG3C,MAAM,cAAc,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;MAGrE;IAED,KAAK;0BACqB,MAAM,aAAa,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;0BAG3C,MAAM,cAAc,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;MAGrE;IAEK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC;YAOtB,YAAY;IAoC1B,OAAO,CAAC,eAAe;CA2BxB"}
package/dist/nip46.js ADDED
@@ -0,0 +1,246 @@
1
+ import { randomBytes, bytesToHex } from '@noble/hashes/utils';
2
+ import { getPublicKey } from './crypto.js';
3
+ import { finalizeEvent } from './event.js';
4
+ import * as nip04 from './nip04.js';
5
+ import { Relay } from './relay.js';
6
+ // NIP-46 event kind
7
+ const NIP46_KIND = 24133;
8
+ // Error classes
9
+ export class Nip46Error extends Error {
10
+ code;
11
+ constructor(message, code = 'NIP46_ERROR') {
12
+ super(message);
13
+ this.name = 'Nip46Error';
14
+ this.code = code;
15
+ }
16
+ }
17
+ export class Nip46TimeoutError extends Nip46Error {
18
+ constructor(message) {
19
+ super(message, 'NIP46_TIMEOUT');
20
+ this.name = 'Nip46TimeoutError';
21
+ }
22
+ }
23
+ export class Nip46ConnectionError extends Nip46Error {
24
+ constructor(message) {
25
+ super(message, 'NIP46_CONNECTION_ERROR');
26
+ this.name = 'Nip46ConnectionError';
27
+ }
28
+ }
29
+ export class Nip46RemoteError extends Nip46Error {
30
+ constructor(message) {
31
+ super(message, 'NIP46_REMOTE_ERROR');
32
+ this.name = 'Nip46RemoteError';
33
+ }
34
+ }
35
+ // URI parsing
36
+ export function parseConnectionURI(uri) {
37
+ // Accept both nostrconnect:// and bunker:// prefixes
38
+ let normalized;
39
+ if (uri.startsWith('nostrconnect://')) {
40
+ normalized = uri.replace('nostrconnect://', 'http://');
41
+ }
42
+ else if (uri.startsWith('bunker://')) {
43
+ normalized = uri.replace('bunker://', 'http://');
44
+ }
45
+ else {
46
+ throw new Nip46Error('Invalid connection URI: must start with nostrconnect:// or bunker://', 'INVALID_URI');
47
+ }
48
+ const url = new URL(normalized);
49
+ const remotePubkey = url.host || url.pathname.replace('//', '');
50
+ // Collect all relay params (supports multiple ?relay= params)
51
+ const relayUrls = url.searchParams.getAll('relay');
52
+ if (!remotePubkey) {
53
+ throw new Nip46Error('Invalid connection URI: missing remote pubkey', 'INVALID_URI');
54
+ }
55
+ if (relayUrls.length === 0) {
56
+ throw new Nip46Error('Invalid connection URI: missing relay parameter', 'INVALID_URI');
57
+ }
58
+ // Extract optional secret
59
+ const secret = url.searchParams.get('secret') || undefined;
60
+ // Extract optional app metadata
61
+ const name = url.searchParams.get('name') || undefined;
62
+ const appUrl = url.searchParams.get('url') || undefined;
63
+ const image = url.searchParams.get('image') || undefined;
64
+ const appMetadata = name || appUrl || image ? { name, url: appUrl, image } : undefined;
65
+ return { remotePubkey, relayUrls, secret, ...(appMetadata ? { appMetadata } : {}) };
66
+ }
67
+ // NostrConnect class
68
+ export class NostrConnect {
69
+ remotePubkey;
70
+ relayUrls;
71
+ secretKey;
72
+ publicKey;
73
+ relay;
74
+ secret;
75
+ _connected = false;
76
+ pendingRequests = new Map();
77
+ sub;
78
+ timeout = 60000;
79
+ constructor(connectionOrOpts) {
80
+ const opts = typeof connectionOrOpts === 'string'
81
+ ? parseConnectionURI(connectionOrOpts)
82
+ : connectionOrOpts;
83
+ this.remotePubkey = opts.remotePubkey;
84
+ this.relayUrls = opts.relayUrls;
85
+ this.secretKey = opts.secretKey || randomBytes(32);
86
+ this.publicKey = getPublicKey(this.secretKey);
87
+ this.secret = opts.secret;
88
+ }
89
+ get connected() {
90
+ return this._connected;
91
+ }
92
+ async connect() {
93
+ // Try each relay until one succeeds
94
+ let lastError;
95
+ for (const relayUrl of this.relayUrls) {
96
+ const relay = new Relay(relayUrl);
97
+ try {
98
+ await relay.connect({ timeout: 5000 });
99
+ }
100
+ catch (err) {
101
+ lastError = err;
102
+ continue;
103
+ }
104
+ this.relay = relay;
105
+ // Subscribe to responses from the remote signer
106
+ this.sub = this.relay.subscribe([
107
+ {
108
+ kinds: [NIP46_KIND],
109
+ authors: [this.remotePubkey],
110
+ '#p': [this.publicKey],
111
+ },
112
+ ], {
113
+ onevent: (event) => {
114
+ this._handleResponse(event);
115
+ },
116
+ });
117
+ // Send connect RPC with optional secret
118
+ const params = this.secret
119
+ ? [this.publicKey, this.secret]
120
+ : [this.publicKey];
121
+ try {
122
+ await this._sendRequest('connect', params);
123
+ }
124
+ catch (err) {
125
+ this.relay.close();
126
+ lastError = err;
127
+ continue;
128
+ }
129
+ this._connected = true;
130
+ return;
131
+ }
132
+ throw new Nip46ConnectionError(`Failed to connect to any relay: ${lastError?.message || 'no relays provided'}`);
133
+ }
134
+ async disconnect() {
135
+ if (!this._connected)
136
+ return;
137
+ try {
138
+ await this._sendRequest('disconnect', []);
139
+ }
140
+ catch {
141
+ // Best effort
142
+ }
143
+ this.close();
144
+ }
145
+ close() {
146
+ // Reject all pending requests
147
+ for (const [id, pending] of this.pendingRequests) {
148
+ clearTimeout(pending.timeout);
149
+ pending.reject(new Nip46Error('Connection closed'));
150
+ this.pendingRequests.delete(id);
151
+ }
152
+ this.sub?.close();
153
+ this.sub = undefined;
154
+ this.relay?.close();
155
+ this._connected = false;
156
+ }
157
+ async describe() {
158
+ const result = await this._sendRequest('describe', []);
159
+ return JSON.parse(result);
160
+ }
161
+ // Signer interface
162
+ async getPublicKey() {
163
+ return this._sendRequest('get_public_key', []);
164
+ }
165
+ async signEvent(event) {
166
+ const result = await this._sendRequest('sign_event', [JSON.stringify(event)]);
167
+ return JSON.parse(result);
168
+ }
169
+ nip04 = {
170
+ encrypt: async (pubkey, plaintext) => {
171
+ return this._sendRequest('nip04_encrypt', [pubkey, plaintext]);
172
+ },
173
+ decrypt: async (pubkey, ciphertext) => {
174
+ return this._sendRequest('nip04_decrypt', [pubkey, ciphertext]);
175
+ },
176
+ };
177
+ nip44 = {
178
+ encrypt: async (pubkey, plaintext) => {
179
+ return this._sendRequest('nip44_encrypt', [pubkey, plaintext]);
180
+ },
181
+ decrypt: async (pubkey, ciphertext) => {
182
+ return this._sendRequest('nip44_decrypt', [pubkey, ciphertext]);
183
+ },
184
+ };
185
+ async getRelays() {
186
+ const result = await this._sendRequest('get_relays', []);
187
+ return JSON.parse(result);
188
+ }
189
+ // Private methods
190
+ async _sendRequest(method, params) {
191
+ if (method !== 'connect' && !this._connected) {
192
+ throw new Nip46ConnectionError('Not connected. Call connect() first.');
193
+ }
194
+ const id = bytesToHex(randomBytes(16));
195
+ const request = JSON.stringify({ id, method, params });
196
+ // Encrypt with NIP-04
197
+ const encrypted = nip04.encrypt(this.secretKey, this.remotePubkey, request);
198
+ const eventTemplate = {
199
+ kind: NIP46_KIND,
200
+ created_at: Math.floor(Date.now() / 1000),
201
+ tags: [['p', this.remotePubkey]],
202
+ content: encrypted,
203
+ };
204
+ const event = finalizeEvent(eventTemplate, this.secretKey);
205
+ return new Promise((resolve, reject) => {
206
+ const timeout = setTimeout(() => {
207
+ this.pendingRequests.delete(id);
208
+ reject(new Nip46TimeoutError(`Request timed out: ${method}`));
209
+ }, this.timeout);
210
+ this.pendingRequests.set(id, { resolve, reject, timeout });
211
+ this.relay.publish(event).catch((err) => {
212
+ clearTimeout(timeout);
213
+ this.pendingRequests.delete(id);
214
+ reject(new Nip46Error(`Failed to publish ${method}: ${err.message}`));
215
+ });
216
+ });
217
+ }
218
+ _handleResponse(event) {
219
+ let decrypted;
220
+ try {
221
+ decrypted = nip04.decrypt(this.secretKey, this.remotePubkey, event.content);
222
+ }
223
+ catch {
224
+ return; // Ignore events we can't decrypt
225
+ }
226
+ let response;
227
+ try {
228
+ response = JSON.parse(decrypted);
229
+ }
230
+ catch {
231
+ return; // Ignore malformed responses
232
+ }
233
+ const pending = this.pendingRequests.get(response.id);
234
+ if (!pending)
235
+ return;
236
+ clearTimeout(pending.timeout);
237
+ this.pendingRequests.delete(response.id);
238
+ if (response.error) {
239
+ pending.reject(new Nip46RemoteError(response.error));
240
+ }
241
+ else {
242
+ pending.resolve(response.result || '');
243
+ }
244
+ }
245
+ }
246
+ //# sourceMappingURL=nip46.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip46.js","sourceRoot":"","sources":["../src/nip46.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type EventTemplate, type NostrEvent } from './event.js';
2
+ export type Rumor = {
3
+ id: string;
4
+ kind: number;
5
+ tags: string[][];
6
+ content: string;
7
+ created_at: number;
8
+ pubkey: string;
9
+ };
10
+ export declare function createRumor(event: EventTemplate, senderPubkey: string): Rumor;
11
+ export declare function createSeal(rumor: Rumor, senderSecretKey: Uint8Array, recipientPubkey: string): NostrEvent;
12
+ export declare function createWrap(seal: NostrEvent, recipientPubkey: string): NostrEvent;
13
+ export declare function unwrap(wrap: NostrEvent, recipientSecretKey: Uint8Array): Rumor;
14
+ //# sourceMappingURL=nip59.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip59.d.ts","sourceRoot":"","sources":["../src/nip59.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4C,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAS1G,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAaD,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,KAAK,CAO7E;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,UAAU,EAC3B,eAAe,EAAE,MAAM,GACtB,UAAU,CAaZ;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,UAAU,EAChB,eAAe,EAAE,MAAM,GACtB,UAAU,CAcZ;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,UAAU,EAChB,kBAAkB,EAAE,UAAU,GAC7B,KAAK,CA6BP"}
package/dist/nip59.js ADDED
@@ -0,0 +1,69 @@
1
+ import { generateSecretKey } from './crypto.js';
2
+ import { finalizeEvent, getEventHash, verifyEvent } from './event.js';
3
+ import * as nip44 from './nip44.js';
4
+ // Kind constants
5
+ const SEAL_KIND = 13;
6
+ const GIFT_WRAP_KIND = 1059;
7
+ // Helpers
8
+ function randomTimestamp() {
9
+ // Randomize up to 2 days in the past
10
+ const twoDays = 2 * 24 * 60 * 60;
11
+ const offset = Math.floor(Math.random() * twoDays);
12
+ return Math.floor(Date.now() / 1000) - offset;
13
+ }
14
+ // Public API
15
+ export function createRumor(event, senderPubkey) {
16
+ const rumor = {
17
+ ...event,
18
+ pubkey: senderPubkey,
19
+ };
20
+ const id = getEventHash(rumor);
21
+ return { ...rumor, id };
22
+ }
23
+ export function createSeal(rumor, senderSecretKey, recipientPubkey) {
24
+ const convKey = nip44.getConversationKey(senderSecretKey, recipientPubkey);
25
+ const encrypted = nip44.encrypt(JSON.stringify(rumor), convKey);
26
+ return finalizeEvent({
27
+ kind: SEAL_KIND,
28
+ tags: [],
29
+ content: encrypted,
30
+ created_at: randomTimestamp(),
31
+ }, senderSecretKey);
32
+ }
33
+ export function createWrap(seal, recipientPubkey) {
34
+ const ephemeralKey = generateSecretKey();
35
+ const convKey = nip44.getConversationKey(ephemeralKey, recipientPubkey);
36
+ const encrypted = nip44.encrypt(JSON.stringify(seal), convKey);
37
+ return finalizeEvent({
38
+ kind: GIFT_WRAP_KIND,
39
+ tags: [['p', recipientPubkey]],
40
+ content: encrypted,
41
+ created_at: randomTimestamp(),
42
+ }, ephemeralKey);
43
+ }
44
+ export function unwrap(wrap, recipientSecretKey) {
45
+ if (wrap.kind !== GIFT_WRAP_KIND) {
46
+ throw new Error(`Expected kind ${GIFT_WRAP_KIND} gift wrap, got kind ${wrap.kind}`);
47
+ }
48
+ // Decrypt the gift wrap to get the seal
49
+ const convKey = nip44.getConversationKey(recipientSecretKey, wrap.pubkey);
50
+ const sealJson = nip44.decrypt(wrap.content, convKey);
51
+ const seal = JSON.parse(sealJson);
52
+ // Verify the seal signature
53
+ if (seal.kind !== SEAL_KIND) {
54
+ throw new Error(`Expected kind ${SEAL_KIND} seal, got kind ${seal.kind}`);
55
+ }
56
+ if (!verifyEvent(seal)) {
57
+ throw new Error('Seal signature verification failed');
58
+ }
59
+ // Decrypt the seal to get the rumor
60
+ const sealConvKey = nip44.getConversationKey(recipientSecretKey, seal.pubkey);
61
+ const rumorJson = nip44.decrypt(seal.content, sealConvKey);
62
+ const rumor = JSON.parse(rumorJson);
63
+ // Verify pubkey consistency: seal.pubkey must match rumor.pubkey
64
+ if (seal.pubkey !== rumor.pubkey) {
65
+ throw new Error('Seal pubkey does not match rumor pubkey — possible impersonation');
66
+ }
67
+ return rumor;
68
+ }
69
+ //# sourceMappingURL=nip59.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip59.js","sourceRoot":"","sources":["../src/nip59.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type EventTemplate, type VerifiedEvent } from './event.js';
2
+ export type RelayMap = Record<string, {
3
+ read: boolean;
4
+ write: boolean;
5
+ }>;
6
+ export interface Signer {
7
+ getPublicKey(): Promise<string>;
8
+ signEvent(event: EventTemplate): Promise<VerifiedEvent>;
9
+ nip04?: {
10
+ encrypt(pubkey: string, plaintext: string): Promise<string>;
11
+ decrypt(pubkey: string, ciphertext: string): Promise<string>;
12
+ };
13
+ nip44?: {
14
+ encrypt(pubkey: string, plaintext: string): Promise<string>;
15
+ decrypt(pubkey: string, ciphertext: string): Promise<string>;
16
+ };
17
+ getRelays?(): Promise<RelayMap>;
18
+ }
19
+ export declare function createSecretKeySigner(secretKey: Uint8Array): Signer;
20
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAIlF,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAAA;AAExE,MAAM,WAAW,MAAM;IACrB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/B,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACvD,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QAC3D,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KAC7D,CAAA;IACD,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QAC3D,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KAC7D,CAAA;IACD,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAA;CAChC;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAgCnE"}
package/dist/signer.js ADDED
@@ -0,0 +1,35 @@
1
+ import { bytesToHex } from '@noble/hashes/utils';
2
+ import { schnorr } from '@noble/curves/secp256k1';
3
+ import { finalizeEvent } from './event.js';
4
+ import * as nip04 from './nip04.js';
5
+ import * as nip44 from './nip44.js';
6
+ export function createSecretKeySigner(secretKey) {
7
+ const pubkey = bytesToHex(schnorr.getPublicKey(secretKey));
8
+ return {
9
+ async getPublicKey() {
10
+ return pubkey;
11
+ },
12
+ async signEvent(event) {
13
+ return finalizeEvent(event, secretKey);
14
+ },
15
+ nip04: {
16
+ async encrypt(pubkey, plaintext) {
17
+ return nip04.encrypt(secretKey, pubkey, plaintext);
18
+ },
19
+ async decrypt(pubkey, ciphertext) {
20
+ return nip04.decrypt(secretKey, pubkey, ciphertext);
21
+ },
22
+ },
23
+ nip44: {
24
+ async encrypt(pubkey, plaintext) {
25
+ const conversationKey = nip44.getConversationKey(secretKey, pubkey);
26
+ return nip44.encrypt(plaintext, conversationKey);
27
+ },
28
+ async decrypt(pubkey, ciphertext) {
29
+ const conversationKey = nip44.getConversationKey(secretKey, pubkey);
30
+ return nip44.decrypt(ciphertext, conversationKey);
31
+ },
32
+ },
33
+ };
34
+ }
35
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAEjD,OAAO,EAAE,aAAa,EAA0C,MAAM,YAAY,CAAA;AAClF,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAkBnC,MAAM,UAAU,qBAAqB,CAAC,SAAqB;IACzD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAA;IAE1D,OAAO;QACL,KAAK,CAAC,YAAY;YAChB,OAAO,MAAM,CAAA;QACf,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,KAAoB;YAClC,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QACxC,CAAC;QAED,KAAK,EAAE;YACL,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAiB;gBAC7C,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;YACpD,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,UAAkB;gBAC9C,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;YACrD,CAAC;SACF;QAED,KAAK,EAAE;YACL,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAiB;gBAC7C,MAAM,eAAe,GAAG,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;gBACnE,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,CAAA;YAClD,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,UAAkB;gBAC9C,MAAM,eAAe,GAAG,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;gBACnE,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,eAAe,CAAC,CAAA;YACnD,CAAC;SACF;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nostr-core",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Dead-simple, vendor-neutral NWC (Nostr Wallet Connect) client",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",