nostr-core 0.1.0 → 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pratik Patel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Dead-simple, vendor-neutral [Nostr Wallet Connect (NWC)](https://github.com/nostr-protocol/nips/blob/master/47.md) client for JavaScript and TypeScript.
4
4
 
5
+ [Demo](https://nostr-core-demo.netlify.app/)
6
+
5
7
  ```ts
6
8
  import { NWC } from 'nostr-core'
7
9
 
@@ -23,6 +25,7 @@ nwc.close()
23
25
  - **Full NIP-47 coverage** - `pay_invoice`, `get_balance`, `make_invoice`, `list_transactions`, `pay_keysend`, `sign_message`, and more
24
26
  - **Auto-encryption** - detects NIP-04 or NIP-44 support and handles it transparently
25
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)
26
29
  - **Zero framework deps** - built on audited [noble](https://paulmillr.com/noble/) cryptography libraries only
27
30
  - **ESM-only** - tree-shakeable, modern JavaScript
28
31
 
@@ -175,6 +178,9 @@ import {
175
178
  // Key management
176
179
  generateSecretKey, getPublicKey,
177
180
 
181
+ // Signer abstraction
182
+ createSecretKeySigner, Nip07Signer, NostrConnect,
183
+
178
184
  // Events
179
185
  finalizeEvent, verifyEvent, getEventHash, serializeEvent, validateEvent,
180
186
 
@@ -187,6 +193,9 @@ import {
187
193
  // Bech32 encoding
188
194
  nip19,
189
195
 
196
+ // NIP-07 & NIP-46
197
+ nip07, nip46,
198
+
190
199
  // Filters
191
200
  matchFilter, matchFilters,
192
201
 
@@ -207,14 +216,29 @@ If you've used `@getalby/sdk` before, here's why `nostr-core` is a better fit fo
207
216
  | **Vendor lock-in** | None - pure NIP-47 protocol | Coupled to Alby (OAuth, webhooks, branding) | |
208
217
  | **Error handling** | Typed hierarchy (8 specific classes) | Generic errors | |
209
218
  | **Encryption** | Auto-detects NIP-04 / NIP-44 | Manual configuration | |
210
- | **Fiat conversion** | Built-in (zero extra deps) | Via `@getalby/lightning-tools` | |
211
- | **Runtime support** | Node 18+, Deno, Bun, Cloudflare Workers | Primarily Node.js | |
212
- | **API surface** | One class (`NWC`) | Multiple overlapping abstractions | |
219
+ | **Fiat conversion** | Built-in (zero extra deps) | `USD()` via `LN` client (v7+), backed by `@getalby/lightning-tools` | |
220
+ | **Runtime support** | Node 18+, Deno, Bun, Cloudflare Workers | Node.js (requires websocket polyfill pre-v18) | |
221
+ | **API surface** | One class (`NWC`) | `LN` + `NWCClient` + `NWAClient` + `NostrWebLNProvider` + `OAuthWebLNProvider` | |
213
222
 
214
223
  **Use `@getalby/sdk`** if you need Alby OAuth or WebLN compatibility. **Use `nostr-core`** for everything else - including Lightning Address payments and fiat currency conversion, which are now supported natively.
215
224
 
216
225
  See the full [comparison guide](./docs/guide/comparison.md) for details.
217
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
+
218
242
  ## Dependencies
219
243
 
220
244
  | Package | Purpose |
@@ -226,4 +250,4 @@ See the full [comparison guide](./docs/guide/comparison.md) for details.
226
250
 
227
251
  ## License
228
252
 
229
- MIT
253
+ [MIT](./LICENSE)
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 } 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,MAAM,YAAY,CAAA;AAGrE,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,36 @@
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
+ getRelays?(): Promise<RelayMap>;
18
+ }
19
+ declare global {
20
+ interface Window {
21
+ nostr?: Nip07Extension;
22
+ }
23
+ }
24
+ export declare function getExtension(): Nip07Extension;
25
+ export declare class Nip07Signer implements Signer {
26
+ private ext;
27
+ constructor();
28
+ getPublicKey(): Promise<string>;
29
+ signEvent(event: EventTemplate): Promise<VerifiedEvent>;
30
+ nip04: {
31
+ encrypt: (pubkey: string, plaintext: string) => Promise<string>;
32
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
33
+ };
34
+ getRelays(): Promise<RelayMap>;
35
+ }
36
+ //# 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,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;IAEK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC;CAUrC"}
package/dist/nip07.js ADDED
@@ -0,0 +1,81 @@
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
+ async getRelays() {
70
+ if (!this.ext.getRelays) {
71
+ throw new Nip07Error('Extension does not support getRelays', 'NIP07_RELAYS_UNSUPPORTED');
72
+ }
73
+ try {
74
+ return await this.ext.getRelays();
75
+ }
76
+ catch (err) {
77
+ throw new Nip07Error(`getRelays failed: ${err.message}`);
78
+ }
79
+ }
80
+ }
81
+ //# 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,49 @@
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' | 'get_relays';
17
+ export type Nip46ConnectionOptions = {
18
+ remotePubkey: string;
19
+ relayUrl: string;
20
+ secretKey?: Uint8Array;
21
+ };
22
+ export declare function parseConnectionURI(uri: string): Nip46ConnectionOptions;
23
+ export declare class NostrConnect implements Signer {
24
+ private remotePubkey;
25
+ private relayUrl;
26
+ private secretKey;
27
+ private publicKey;
28
+ private relay;
29
+ private _connected;
30
+ private pendingRequests;
31
+ private sub;
32
+ timeout: number;
33
+ constructor(connectionOrOpts: string | Nip46ConnectionOptions);
34
+ get connected(): boolean;
35
+ connect(): Promise<void>;
36
+ disconnect(): Promise<void>;
37
+ close(): void;
38
+ describe(): Promise<string[]>;
39
+ getPublicKey(): Promise<string>;
40
+ signEvent(event: EventTemplate): Promise<VerifiedEvent>;
41
+ nip04: {
42
+ encrypt: (pubkey: string, plaintext: string) => Promise<string>;
43
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
44
+ };
45
+ getRelays(): Promise<RelayMap>;
46
+ private _sendRequest;
47
+ private _handleResponse;
48
+ }
49
+ //# 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,YAAY,CAAA;AAEhB,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,UAAU,CAAA;CACvB,CAAA;AAUD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CActE;AAID,qBAAa,YAAa,YAAW,MAAM;IACzC,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAO;IACpB,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;IAkCxB,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;IAEK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC;YAOtB,YAAY;IAoC1B,OAAO,CAAC,eAAe;CA2BxB"}
package/dist/nip46.js ADDED
@@ -0,0 +1,206 @@
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
+ const normalized = uri.replace('nostrconnect://', 'http://');
38
+ const url = new URL(normalized);
39
+ const remotePubkey = url.host || url.pathname.replace('//', '');
40
+ const relayUrl = url.searchParams.get('relay');
41
+ if (!remotePubkey) {
42
+ throw new Nip46Error('Invalid nostrconnect URI: missing remote pubkey', 'INVALID_URI');
43
+ }
44
+ if (!relayUrl) {
45
+ throw new Nip46Error('Invalid nostrconnect URI: missing relay parameter', 'INVALID_URI');
46
+ }
47
+ return { remotePubkey, relayUrl };
48
+ }
49
+ // NostrConnect class
50
+ export class NostrConnect {
51
+ remotePubkey;
52
+ relayUrl;
53
+ secretKey;
54
+ publicKey;
55
+ relay;
56
+ _connected = false;
57
+ pendingRequests = new Map();
58
+ sub;
59
+ timeout = 60000;
60
+ constructor(connectionOrOpts) {
61
+ const opts = typeof connectionOrOpts === 'string'
62
+ ? parseConnectionURI(connectionOrOpts)
63
+ : connectionOrOpts;
64
+ this.remotePubkey = opts.remotePubkey;
65
+ this.relayUrl = opts.relayUrl;
66
+ this.secretKey = opts.secretKey || randomBytes(32);
67
+ this.publicKey = getPublicKey(this.secretKey);
68
+ this.relay = new Relay(this.relayUrl);
69
+ }
70
+ get connected() {
71
+ return this._connected;
72
+ }
73
+ async connect() {
74
+ try {
75
+ await this.relay.connect({ timeout: 5000 });
76
+ }
77
+ catch (err) {
78
+ throw new Nip46ConnectionError(`Failed to connect to relay ${this.relayUrl}: ${err.message}`);
79
+ }
80
+ // Subscribe to responses from the remote signer
81
+ this.sub = this.relay.subscribe([
82
+ {
83
+ kinds: [NIP46_KIND],
84
+ authors: [this.remotePubkey],
85
+ '#p': [this.publicKey],
86
+ },
87
+ ], {
88
+ onevent: (event) => {
89
+ this._handleResponse(event);
90
+ },
91
+ });
92
+ // Send connect RPC
93
+ try {
94
+ await this._sendRequest('connect', [this.publicKey]);
95
+ }
96
+ catch (err) {
97
+ this.relay.close();
98
+ throw new Nip46ConnectionError(`NIP-46 connect handshake failed: ${err.message}`);
99
+ }
100
+ this._connected = true;
101
+ }
102
+ async disconnect() {
103
+ if (!this._connected)
104
+ return;
105
+ try {
106
+ await this._sendRequest('disconnect', []);
107
+ }
108
+ catch {
109
+ // Best effort
110
+ }
111
+ this.close();
112
+ }
113
+ close() {
114
+ // Reject all pending requests
115
+ for (const [id, pending] of this.pendingRequests) {
116
+ clearTimeout(pending.timeout);
117
+ pending.reject(new Nip46Error('Connection closed'));
118
+ this.pendingRequests.delete(id);
119
+ }
120
+ this.sub?.close();
121
+ this.sub = undefined;
122
+ this.relay.close();
123
+ this._connected = false;
124
+ }
125
+ async describe() {
126
+ const result = await this._sendRequest('describe', []);
127
+ return JSON.parse(result);
128
+ }
129
+ // Signer interface
130
+ async getPublicKey() {
131
+ return this._sendRequest('get_public_key', []);
132
+ }
133
+ async signEvent(event) {
134
+ const result = await this._sendRequest('sign_event', [JSON.stringify(event)]);
135
+ return JSON.parse(result);
136
+ }
137
+ nip04 = {
138
+ encrypt: async (pubkey, plaintext) => {
139
+ return this._sendRequest('nip04_encrypt', [pubkey, plaintext]);
140
+ },
141
+ decrypt: async (pubkey, ciphertext) => {
142
+ return this._sendRequest('nip04_decrypt', [pubkey, ciphertext]);
143
+ },
144
+ };
145
+ async getRelays() {
146
+ const result = await this._sendRequest('get_relays', []);
147
+ return JSON.parse(result);
148
+ }
149
+ // Private methods
150
+ async _sendRequest(method, params) {
151
+ if (method !== 'connect' && !this._connected) {
152
+ throw new Nip46ConnectionError('Not connected. Call connect() first.');
153
+ }
154
+ const id = bytesToHex(randomBytes(16));
155
+ const request = JSON.stringify({ id, method, params });
156
+ // Encrypt with NIP-04
157
+ const encrypted = nip04.encrypt(this.secretKey, this.remotePubkey, request);
158
+ const eventTemplate = {
159
+ kind: NIP46_KIND,
160
+ created_at: Math.floor(Date.now() / 1000),
161
+ tags: [['p', this.remotePubkey]],
162
+ content: encrypted,
163
+ };
164
+ const event = finalizeEvent(eventTemplate, this.secretKey);
165
+ return new Promise((resolve, reject) => {
166
+ const timeout = setTimeout(() => {
167
+ this.pendingRequests.delete(id);
168
+ reject(new Nip46TimeoutError(`Request timed out: ${method}`));
169
+ }, this.timeout);
170
+ this.pendingRequests.set(id, { resolve, reject, timeout });
171
+ this.relay.publish(event).catch((err) => {
172
+ clearTimeout(timeout);
173
+ this.pendingRequests.delete(id);
174
+ reject(new Nip46Error(`Failed to publish ${method}: ${err.message}`));
175
+ });
176
+ });
177
+ }
178
+ _handleResponse(event) {
179
+ let decrypted;
180
+ try {
181
+ decrypted = nip04.decrypt(this.secretKey, this.remotePubkey, event.content);
182
+ }
183
+ catch {
184
+ return; // Ignore events we can't decrypt
185
+ }
186
+ let response;
187
+ try {
188
+ response = JSON.parse(decrypted);
189
+ }
190
+ catch {
191
+ return; // Ignore malformed responses
192
+ }
193
+ const pending = this.pendingRequests.get(response.id);
194
+ if (!pending)
195
+ return;
196
+ clearTimeout(pending.timeout);
197
+ this.pendingRequests.delete(response.id);
198
+ if (response.error) {
199
+ pending.reject(new Nip46RemoteError(response.error));
200
+ }
201
+ else {
202
+ pending.resolve(response.result || '');
203
+ }
204
+ }
205
+ }
206
+ //# sourceMappingURL=nip46.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip46.js","sourceRoot":"","sources":["../src/nip46.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAA2D,MAAM,YAAY,CAAA;AAEnG,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAGlC,oBAAoB;AACpB,MAAM,UAAU,GAAG,KAAK,CAAA;AAExB,gBAAgB;AAEhB,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,IAAI,CAAQ;IACZ,YAAY,OAAe,EAAE,IAAI,GAAG,aAAa;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,YAAY,CAAA;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;QAC/B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAA;IACjC,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IAClD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,UAAU;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAA;QACpC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;IAChC,CAAC;CACF;AA0BD,cAAc;AAEd,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAA;IAC5D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAA;IAC/B,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IAC/D,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAE9C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,UAAU,CAAC,iDAAiD,EAAE,aAAa,CAAC,CAAA;IACxF,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,UAAU,CAAC,mDAAmD,EAAE,aAAa,CAAC,CAAA;IAC1F,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAA;AACnC,CAAC;AAED,qBAAqB;AAErB,MAAM,OAAO,YAAY;IACf,YAAY,CAAQ;IACpB,QAAQ,CAAQ;IAChB,SAAS,CAAY;IACrB,SAAS,CAAQ;IACjB,KAAK,CAAO;IACZ,UAAU,GAAG,KAAK,CAAA;IAClB,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAA;IACnD,GAAG,CAAkD;IAEtD,OAAO,GAAG,KAAK,CAAA;IAEtB,YAAY,gBAAiD;QAC3D,MAAM,IAAI,GAAG,OAAO,gBAAgB,KAAK,QAAQ;YAC/C,CAAC,CAAC,kBAAkB,CAAC,gBAAgB,CAAC;YACtC,CAAC,CAAC,gBAAgB,CAAA;QAEpB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAA;QACrC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,WAAW,CAAC,EAAE,CAAC,CAAA;QAClD,IAAI,CAAC,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACvC,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,oBAAoB,CAAC,8BAA8B,IAAI,CAAC,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;QAC1G,CAAC;QAED,gDAAgD;QAChD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAC7B;YACE;gBACE,KAAK,EAAE,CAAC,UAAU,CAAC;gBACnB,OAAO,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC;gBAC5B,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;aACb;SACZ,EACD;YACE,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;gBAC7B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;YAC7B,CAAC;SACF,CACF,CAAA;QAED,mBAAmB;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;YAClB,MAAM,IAAI,oBAAoB,CAAC,oCAAqC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;QAC9F,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAM;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,KAAK;QACH,8BAA8B;QAC9B,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACjD,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YAC7B,OAAO,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAA;YACnD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACjC,CAAC;QACD,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAA;QACjB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAA;QACpB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QAClB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC3B,CAAC;IAED,mBAAmB;IAEnB,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,KAAoB;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC7E,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC3B,CAAC;IAED,KAAK,GAAG;QACN,OAAO,EAAE,KAAK,EAAE,MAAc,EAAE,SAAiB,EAAmB,EAAE;YACpE,OAAO,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;QAChE,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,MAAc,EAAE,UAAkB,EAAmB,EAAE;YACrE,OAAO,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAA;QACjE,CAAC;KACF,CAAA;IAED,KAAK,CAAC,SAAS;QACb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC3B,CAAC;IAED,kBAAkB;IAEV,KAAK,CAAC,YAAY,CAAC,MAAmB,EAAE,MAAgB;QAC9D,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7C,MAAM,IAAI,oBAAoB,CAAC,sCAAsC,CAAC,CAAA;QACxE,CAAC;QAED,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QAEtD,sBAAsB;QACtB,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QAE3E,MAAM,aAAa,GAAkB;YACnC,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACzC,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAChC,OAAO,EAAE,SAAS;SACnB,CAAA;QAED,MAAM,KAAK,GAAG,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QAE1D,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC9B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAC/B,MAAM,CAAC,IAAI,iBAAiB,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC,CAAA;YAC/D,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;YAEhB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;YAE1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACtC,YAAY,CAAC,OAAO,CAAC,CAAA;gBACrB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAC/B,MAAM,CAAC,IAAI,UAAU,CAAC,qBAAqB,MAAM,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YAClF,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,eAAe,CAAC,KAAiB;QACvC,IAAI,SAAiB,CAAA;QACrB,IAAI,CAAC;YACH,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;QAC7E,CAAC;QAAC,MAAM,CAAC;YACP,OAAM,CAAC,iCAAiC;QAC1C,CAAC;QAED,IAAI,QAAyD,CAAA;QAC7D,IAAI,CAAC;YACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,OAAM,CAAC,6BAA6B;QACtC,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QACrD,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC7B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QAExC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;QACtD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;CACF"}
@@ -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,16 @@
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
+ getRelays?(): Promise<RelayMap>;
14
+ }
15
+ export declare function createSecretKeySigner(secretKey: Uint8Array): Signer;
16
+ //# 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;AAGlF,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,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAA;CAChC;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAqBnE"}
package/dist/signer.js ADDED
@@ -0,0 +1,24 @@
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
+ export function createSecretKeySigner(secretKey) {
6
+ const pubkey = bytesToHex(schnorr.getPublicKey(secretKey));
7
+ return {
8
+ async getPublicKey() {
9
+ return pubkey;
10
+ },
11
+ async signEvent(event) {
12
+ return finalizeEvent(event, secretKey);
13
+ },
14
+ nip04: {
15
+ async encrypt(pubkey, plaintext) {
16
+ return nip04.encrypt(secretKey, pubkey, plaintext);
17
+ },
18
+ async decrypt(pubkey, ciphertext) {
19
+ return nip04.decrypt(secretKey, pubkey, ciphertext);
20
+ },
21
+ },
22
+ };
23
+ }
24
+ //# 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,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;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nostr-core",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Dead-simple, vendor-neutral NWC (Nostr Wallet Connect) client",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",