402-announce 2.1.0 → 2.1.1

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
@@ -47,7 +47,7 @@ const handle = await announceService({
47
47
  pricing: [
48
48
  { capability: 'get_joke', price: 1, currency: 'sats' },
49
49
  ],
50
- paymentMethods: ['bitcoin-lightning-bolt11', 'bitcoin-cashu', 'bitcoin-cashu-xcashu'],
50
+ paymentMethods: [['l402', 'lightning'], ['cashu'], ['xcashu']],
51
51
  topics: ['comedy', 'ai'],
52
52
  capabilities: [
53
53
  { name: 'get_joke', description: 'Returns a random joke' },
@@ -77,7 +77,7 @@ const handle = await announceService({
77
77
  ],
78
78
  about: 'A joke-telling service behind an L402 paywall',
79
79
  pricing: [{ capability: 'get_joke', price: 1, currency: 'sats' }],
80
- paymentMethods: ['bitcoin-lightning-bolt11'],
80
+ paymentMethods: [['l402', 'lightning']],
81
81
  topics: ['comedy', 'ai'],
82
82
  })
83
83
  ```
@@ -162,7 +162,7 @@ Lower-level function that builds and signs the event without publishing. Useful
162
162
  | `urls` | `string[]` | yes | HTTP endpoints for the service (1–10 entries, any parseable URL) |
163
163
  | `about` | `string` | yes | Short description |
164
164
  | `pricing` | `PricingDef[]` | yes | Per-capability pricing |
165
- | `paymentMethods` | `string[]` | yes | Accepted payment methods |
165
+ | `paymentMethods` | `string[][]` | yes | Accepted payment methods (each entry is `[rail, ...params]`) |
166
166
  | `picture` | `string` | no | Icon URL |
167
167
  | `topics` | `string[]` | no | Topic tags for filtering |
168
168
  | `capabilities` | `CapabilityDef[]` | no | Capability details (stored in event content) |
@@ -200,8 +200,8 @@ graph TB
200
200
  U1["url: https://jokes.example.com"]
201
201
  U2["url: https://jokesapi.example.onion (optional)"]
202
202
  AB["about: A joke-telling service"]
203
- PMI1["pmi: bitcoin-lightning-bolt11"]
204
- PMI2["pmi: bitcoin-cashu"]
203
+ PMI1["pmi: l402, lightning"]
204
+ PMI2["pmi: cashu"]
205
205
  P["price: get_joke, 1, sats"]
206
206
  T["t: comedy"]
207
207
  end
@@ -223,19 +223,22 @@ graph TB
223
223
  | `name` | yes | Human-readable service name | `Jokes API` |
224
224
  | `url` | yes | HTTP endpoint (one tag per URL; repeatable) | `https://jokes.example.com` |
225
225
  | `about` | yes | Short description | `A joke-telling service` |
226
- | `pmi` | yes | Payment method identifier (repeatable) | `bitcoin-lightning-bolt11` |
226
+ | `pmi` | yes | Payment method identifier (repeatable, multi-element) | `l402`, `lightning` |
227
227
  | `price` | yes | Capability pricing (repeatable) | `get_joke`, `1`, `sats` |
228
228
  | `t` | no | Topic tag for search/filtering (repeatable) | `comedy` |
229
229
  | `picture` | no | Icon URL | `https://example.com/icon.png` |
230
230
 
231
- ### Recognised Payment Method Identifiers
231
+ ### Recognised Payment Method Rails
232
232
 
233
- | Identifier | Description |
234
- |------------|-------------|
235
- | `bitcoin-lightning-bolt11` | Lightning Network (BOLT-11 invoices) |
236
- | `bitcoin-cashu` | Cashu ecash (generic) |
237
- | `bitcoin-cashu-xcashu` | Cashu ecash via NUT-24 (X-Cashu header) |
238
- | `x402-evm` | x402 stablecoin payments (EVM chains) |
233
+ Each `paymentMethods` entry is an array where the first element is the rail identifier and subsequent elements are rail-specific parameters.
234
+
235
+ | Rail | Example | Description |
236
+ |------|---------|-------------|
237
+ | `l402` | `['l402', 'lightning']` | L402 protocol (Lightning BOLT-11 invoices) |
238
+ | `cashu` | `['cashu']` | Cashu ecash (generic) |
239
+ | `xcashu` | `['xcashu']` | Cashu ecash via NUT-24 (X-Cashu header) |
240
+ | `x402` | `['x402', 'base', 'usdc', '0xabc...']` | x402 stablecoin payments (chain, token, receiver address) |
241
+ | `payment` | `['payment', 'lightning']` | IETF Payment protocol |
239
242
 
240
243
  ### Content
241
244
 
@@ -277,6 +280,23 @@ In short: same service + different network paths → one event with multiple `ur
277
280
  | [402-mcp](https://github.com/forgesworn/402-mcp) | MCP server for AI agents to discover, pay, and consume 402 APIs |
278
281
  | [Live Dashboard](https://402.pub) | See every service announcing on the network |
279
282
 
283
+ ## Part of the ForgeSworn Toolkit
284
+
285
+ [ForgeSworn](https://forgesworn.dev) builds open-source cryptographic identity, payments, and coordination tools for Nostr.
286
+
287
+ | Library | What it does |
288
+ |---------|-------------|
289
+ | [nsec-tree](https://github.com/forgesworn/nsec-tree) | Deterministic sub-identity derivation |
290
+ | [ring-sig](https://github.com/forgesworn/ring-sig) | SAG/LSAG ring signatures on secp256k1 |
291
+ | [range-proof](https://github.com/forgesworn/range-proof) | Pedersen commitment range proofs |
292
+ | [canary-kit](https://github.com/forgesworn/canary-kit) | Coercion-resistant spoken verification |
293
+ | [spoken-token](https://github.com/forgesworn/spoken-token) | Human-speakable verification tokens |
294
+ | [toll-booth](https://github.com/forgesworn/toll-booth) | L402 payment middleware |
295
+ | [geohash-kit](https://github.com/forgesworn/geohash-kit) | Geohash toolkit with polygon coverage |
296
+ | [nostr-attestations](https://github.com/forgesworn/nostr-attestations) | NIP-VA verifiable attestations |
297
+ | [dominion](https://github.com/forgesworn/dominion) | Epoch-based encrypted access control |
298
+ | [nostr-veil](https://github.com/forgesworn/nostr-veil) | Privacy-preserving Web of Trust |
299
+
280
300
  ## Licence
281
301
 
282
302
  [MIT](./LICENSE)
package/context7.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "url": "https://context7.com/forgesworn/402-announce",
3
+ "public_key": "pk_vdoXns3QEblb1693KnlDH"
4
+ }
package/llms-full.txt CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  The library handles event construction, signing, and multi-relay publication. Secret key material is zeroised after use.
12
12
 
13
+ ## Kind 31402 — disambiguation
14
+
15
+ This library uses kind 31402 for **L402/x402 service announcements** (paid API discovery). This is distinct from any SARA (Simple Autonomous Revenue Agreement) proposals that may also reference kind 31402. The 402-announce definition: a parameterised replaceable event (NIP-33) where pubkey + d-tag uniquely identifies one service listing.
16
+
13
17
  ## Installation
14
18
 
15
19
  ```bash
@@ -28,13 +32,13 @@ High-level function: builds a kind 31402 event, signs it, connects to relays in
28
32
 
29
33
  AnnounceConfig:
30
34
  - secretKey (string, required): 64-character hex-encoded Nostr secret key
31
- - relays (string[], required): Relay URLs (must start with wss:// or ws://)
35
+ - relays (string[], required): Relay URLs (must start with wss:// or ws://). Maximum 50.
32
36
  - identifier (string, required): Unique listing ID, used as the Nostr `d` tag. Same pubkey + identifier = same listing.
33
37
  - name (string, required): Human-readable service name
34
- - urls (string[], required): Transport endpoint URLs (1–10 entries, each max 2048 characters)
38
+ - urls (string[], required): Transport endpoint URLs (1–10 entries, each max 2048 characters). One `url` tag per entry in the event. Clients try in order.
35
39
  - about (string, required): Short description of the service
36
40
  - pricing (PricingDef[], required): Per-capability pricing. Each entry: { capability, price, currency }
37
- - paymentMethods (string[], required): Accepted payment method identifiers
41
+ - paymentMethods (string[][], required): Accepted payment methods. Each entry is [rail, ...params]
38
42
  - picture (string, optional): Icon URL
39
43
  - topics (string[], optional): Topic tags for search/filtering
40
44
  - capabilities (CapabilityDef[], optional): Capability details stored in event content
@@ -42,31 +46,37 @@ AnnounceConfig:
42
46
 
43
47
  PricingDef:
44
48
  - capability (string): Capability name (e.g. "get_joke", "chat", "inference")
45
- - price (number): Price amount
49
+ - price (number): Price amount (integer or fractional)
46
50
  - currency (string): Currency unit (e.g. "sats", "USD")
47
51
 
48
52
  CapabilityDef:
49
53
  - name (string): Capability name
50
54
  - description (string): Human-readable description
51
- - schema (unknown, optional): JSON Schema describing the capability's input parameters
52
- - outputSchema (unknown, optional): JSON Schema describing the capability's output
55
+ - endpoint (string, optional): Endpoint path or full URL for this capability (e.g. '/api/joke')
56
+ - schema (unknown, optional): JSON Schema describing the capability's input parameters (max depth 10)
57
+ - outputSchema (unknown, optional): JSON Schema describing the capability's output (max depth 10)
53
58
 
54
59
  **Returns** Announcement:
55
60
  - eventId (string): The published Nostr event ID
56
61
  - pubkey (string): Nostr pubkey derived from the secret key
57
- - close(): void — Disconnect from all connected relays
62
+ - close(): void — Disconnect from all connected relays (synchronous; call on shutdown to avoid WebSocket leaks)
58
63
 
59
64
  **Behaviour:**
60
65
  - Validates secretKey (must be 64-char hex) and relay URLs (must be wss:// or ws://)
66
+ - Rejects relay URLs pointing to private/loopback addresses (SSRF prevention)
67
+ - Rejects service configs where all urls are private/loopback (at least one public URL required)
61
68
  - Connects to all relays in parallel with a 10-second timeout per relay
62
69
  - Individual relay failures are logged as warnings but do not reject the promise
63
70
  - If no relay accepts the event, a warning is emitted (but the promise still resolves)
64
71
  - Secret key bytes are zeroised after signing
72
+ - Warns on insecure ws:// relay URLs
65
73
 
66
74
  **Throws:**
67
75
  - If secretKey is not a 64-character hex string
68
- - If relays array is empty
76
+ - If relays array is empty or contains more than 50 entries
69
77
  - If any relay URL does not start with wss:// or ws://
78
+ - If any relay URL points to a private/loopback address
79
+ - If all service URLs are private/loopback addresses
70
80
 
71
81
  ### buildAnnounceEvent(secretKeyHex: string, config: Omit<AnnounceConfig, 'relays'>): VerifiedEvent
72
82
 
@@ -74,7 +84,11 @@ Lower-level function: builds and signs the kind 31402 event without publishing.
74
84
 
75
85
  **Returns** a nostr-tools VerifiedEvent ready for relay publication.
76
86
 
77
- Secret key bytes are zeroised after signing (via try/finally).
87
+ Secret key bytes are zeroised after signing (via try/finally). Unlike announceService(), this function does not enforce the "at least one public URL" rule — it is a pure serialisation utility.
88
+
89
+ ### isPrivateHost(hostname: string): boolean
90
+
91
+ Utility export. Returns true if the hostname is a private, loopback, link-local, or reserved address (IPv4 or IPv6). Used internally for SSRF prevention; exported for consumers who need the same guard.
78
92
 
79
93
  ### Constants
80
94
 
@@ -85,7 +99,7 @@ Secret key bytes are zeroised after signing (via try/finally).
85
99
  - AnnounceConfig — Configuration for announceService()
86
100
  - Announcement — Handle returned by announceService()
87
101
  - PricingDef — Pricing for a specific capability
88
- - CapabilityDef — Capability with description
102
+ - CapabilityDef — Capability with description, optional endpoint and schemas
89
103
 
90
104
  ## Event Format Specification
91
105
 
@@ -99,12 +113,12 @@ A kind 31402 event is a Nostr parameterised replaceable event (NIP-33). This mea
99
113
  ### Tag structure
100
114
 
101
115
  Required tags:
102
- ["d", "<identifier>"] — Unique listing identifier
103
- ["name", "<service name>"] — Human-readable name
104
- ["url", "<endpoint URL>"] — HTTP endpoint
105
- ["about", "<description>"] — Short description
106
- ["pmi", "<payment method>"] — Payment method identifier (one tag per method)
107
- ["price", "<capability>", "<amount>", "<currency>"] — Pricing (one tag per capability)
116
+ ["d", "<identifier>"] — Unique listing identifier
117
+ ["name", "<service name>"] — Human-readable name
118
+ ["url", "<endpoint URL>"] — HTTP endpoint (one tag per URL; 1–10 allowed)
119
+ ["about", "<description>"] — Short description
120
+ ["pmi", "<rail>", ...params] — Payment method identifier (one tag per method)
121
+ ["price", "<capability>", "<amount>", "<currency>"] — Pricing (one tag per capability)
108
122
 
109
123
  Optional tags:
110
124
  ["t", "<topic>"] — Topic tag for filtering (one tag per topic)
@@ -115,7 +129,13 @@ Optional tags:
115
129
  JSON object with optional fields:
116
130
  {
117
131
  "capabilities": [
118
- { "name": "get_joke", "description": "Returns a random joke" }
132
+ {
133
+ "name": "get_joke",
134
+ "description": "Returns a random joke",
135
+ "endpoint": "/api/joke",
136
+ "schema": { "type": "object", "properties": { "category": { "type": "string" } } },
137
+ "outputSchema": { "type": "object", "properties": { "joke": { "type": "string" } } }
138
+ }
119
139
  ],
120
140
  "version": "1.0.0"
121
141
  }
@@ -130,9 +150,10 @@ JSON object with optional fields:
130
150
  ["d", "jokes-api"],
131
151
  ["name", "Jokes API"],
132
152
  ["url", "https://jokes.example.com"],
153
+ ["url", "http://jokesxyz...onion"],
133
154
  ["about", "A joke-telling service behind an L402 paywall"],
134
- ["pmi", "bitcoin-lightning-bolt11"],
135
- ["pmi", "bitcoin-cashu"],
155
+ ["pmi", "l402", "lightning"],
156
+ ["pmi", "cashu"],
136
157
  ["price", "get_joke", "1", "sats"],
137
158
  ["t", "comedy"],
138
159
  ["t", "ai"]
@@ -144,19 +165,25 @@ JSON object with optional fields:
144
165
 
145
166
  ## Payment Method Identifiers
146
167
 
147
- Known payment method identifiers for the `pmi` tag and `paymentMethods` config:
168
+ Each `paymentMethods` entry is an array where the first element is the rail identifier and subsequent elements are rail-specific parameters. Known rails:
148
169
 
149
- bitcoin-lightning-bolt11 — Lightning Network BOLT-11 invoices
150
- bitcoin-cashu — Cashu ecash tokens
151
- bitcoin-onchain On-chain Bitcoin
152
- x402-evm — x402 protocol on EVM chains
153
- x402-solana x402 protocol on Solana
170
+ l402 L402 protocol (Lightning BOLT-11 invoices). Example: ['l402', 'lightning']
171
+ cashu — Cashu ecash. Example: ['cashu']
172
+ xcashu Cashu ecash via NUT-24 (X-Cashu header). Example: ['xcashu']
173
+ x402 — x402 stablecoin payments. Example: ['x402', 'base', 'usdc', '0xabc...']
174
+ payment IETF Payment protocol. Example: ['payment', 'lightning']
154
175
 
155
- ## Integration Patterns
176
+ ## Multiple URLs vs Multiple Events
177
+
178
+ **Multiple URLs in one event** — use `urls: ['...', '...']` when the URLs represent the **same service** on different transports (clearnet, Tor, Handshake). Pricing, credentials, and macaroon signing key are identical. Clients try in order and use whichever they can reach. This is for censorship resistance and redundancy.
156
179
 
157
- ### Producer side: toll-booth + 402-announce
180
+ **Separate kind 31402 events** publish a new event (different `identifier`) when you have **genuinely different services**: different pricing tiers, different capabilities, or services that operate independently.
158
181
 
159
- A typical server setup protects an API with toll-booth and announces it with 402-announce:
182
+ Rule: same service + different network paths → one event with multiple `url` tags. Different services → separate events.
183
+
184
+ ## Integration Patterns
185
+
186
+ ### Producer: toll-booth + 402-announce
160
187
 
161
188
  ```typescript
162
189
  import { createTollBooth } from 'toll-booth'
@@ -175,16 +202,31 @@ const handle = await announceService({
175
202
  urls: ['https://api.example.com'],
176
203
  about: 'A paid API service',
177
204
  pricing: [{ capability: 'query', price: 10, currency: 'sats' }],
178
- paymentMethods: ['bitcoin-lightning-bolt11'],
205
+ paymentMethods: [['l402', 'lightning']],
179
206
  })
180
207
 
181
208
  // 3. Clean up on shutdown
182
209
  process.on('SIGTERM', () => handle.close())
183
210
  ```
184
211
 
185
- ### Consumer side: 402-mcp
212
+ ### Producer shortcut: toll-booth-announce
213
+
214
+ If you're using toll-booth, [toll-booth-announce](https://github.com/forgesworn/toll-booth-announce) maps booth config to 402-announce automatically — pricing and payment methods are derived from your booth config:
215
+
216
+ ```typescript
217
+ import { announce } from 'toll-booth-announce'
218
+
219
+ const handle = await announce(boothConfig, {
220
+ secretKey: process.env.NOSTR_SECRET_KEY,
221
+ relays: ['wss://relay.damus.io'],
222
+ urls: ['https://api.example.com'],
223
+ about: 'My toll-booth API',
224
+ })
225
+ ```
226
+
227
+ ### Consumer: 402-mcp
186
228
 
187
- AI agents use 402-mcp to discover and consume announced services:
229
+ AI agents use [402-mcp](https://github.com/forgesworn/402-mcp) to discover and consume announced services:
188
230
 
189
231
  1. 402-mcp subscribes to kind 31402 events on configured relays
190
232
  2. Agent searches for services by topic, capability, or payment method
@@ -197,20 +239,39 @@ The agent never needs to know about Nostr or payment protocols — 402-mcp abstr
197
239
 
198
240
  Because kind 31402 is a parameterised replaceable event, calling announceService() again with the same identifier and pubkey replaces the previous listing. Use this to update pricing, add capabilities, or change the endpoint URL.
199
241
 
242
+ ### Verify on relays
243
+
244
+ ```bash
245
+ # Using nak (Nostr Army Knife)
246
+ nak req -k 31402 wss://relay.damus.io
247
+
248
+ # Filter by topic
249
+ nak req -k 31402 -t t=ai wss://relay.damus.io
250
+ ```
251
+
252
+ ### Live dashboard
253
+
254
+ [402.pub](https://402.pub) shows every service announcing on the network in real time.
255
+
200
256
  ## Security Considerations
201
257
 
202
258
  - **Key zeroisation**: Secret key bytes (Uint8Array) are filled with zeros immediately after signing, in both announceService() and buildAnnounceEvent(). This limits the window during which key material exists in memory.
203
- - **Key handling**: Pass the secret key as a hex string. The library converts to bytes, signs, and zeroises. Never log or persist the key yourself.
259
+ - **Key handling**: Pass the secret key as a hex string. The library converts to bytes, signs, and zeroises. Never log or persist the key yourself. Note: JavaScript strings are immutable and cannot be erased — minimise the lifetime of the string in your application.
260
+ - **SSRF prevention**: Relay URLs and service URLs are checked against private/loopback address patterns. DNS rebinding (hostname resolves to private IP at connection time) is not caught — deploy behind network-level egress controls in production.
204
261
  - **Relay trust**: Relays are untrusted infrastructure. Events are cryptographically signed — relay operators cannot forge announcements. However, relays can choose not to store or serve your events.
205
262
  - **Connection timeouts**: Relay connections time out after 10 seconds to prevent indefinite hangs.
206
263
  - **Graceful degradation**: If some relays fail, the event is still published to the others. A warning is emitted only if no relay accepts the event.
264
+ - **Input limits**: URLs max 2048 chars, max 10 service URLs, max 50 relays, JSON schema depth capped at 10, control characters rejected in all string fields.
207
265
 
208
266
  ## Error Handling
209
267
 
210
268
  The library throws synchronously for invalid configuration:
211
269
  - secretKey not 64-char hex → Error
212
- - Empty relays array → Error
270
+ - Empty relays array or more than 50 relays → Error
213
271
  - Invalid relay URL (not wss:// or ws://) → Error
272
+ - Relay URL with credentials → Error
273
+ - Relay URL pointing to private/loopback address → Error
274
+ - All service URLs pointing to private/loopback addresses → Error
214
275
 
215
276
  Relay-level failures during publication are handled gracefully:
216
277
  - Connection timeouts → warning logged, other relays still tried
@@ -220,5 +281,7 @@ Relay-level failures during publication are handled gracefully:
220
281
  ## Source
221
282
 
222
283
  Repository: https://github.com/forgesworn/402-announce
284
+ npm: https://www.npmjs.com/package/402-announce
285
+ Live dashboard: https://402.pub
223
286
  Licence: MIT
224
287
  Runtime dependency: nostr-tools
package/llms.txt CHANGED
@@ -6,26 +6,36 @@
6
6
 
7
7
  402-announce publishes kind 31402 parameterised replaceable Nostr events that describe paid HTTP APIs. AI agents and Nostr clients discover these announcements to find services they can pay for and consume — no central registry needed.
8
8
 
9
+ ## Kind 31402 — disambiguation
10
+
11
+ This library uses kind 31402 for **L402/x402 service announcements** (paid API discovery). This is distinct from any SARA (revenue share) proposals that may also reference kind 31402. The 402-announce definition: a parameterised replaceable event (NIP-33) where pubkey + d-tag uniquely identifies one service listing.
12
+
9
13
  ## Key concepts
10
14
 
11
15
  - **Kind 31402**: Nostr event kind for L402/x402 service announcements. Parameterised replaceable — same pubkey + identifier updates the existing listing.
12
- - **Payment methods**: Services declare accepted payment methods via `pmi` tags (e.g. `bitcoin-lightning-bolt11`, `bitcoin-cashu`).
16
+ - **Payment methods**: Services declare accepted payment methods via multi-element `pmi` tags. Each `paymentMethods` entry is `[rail, ...params]` (e.g. `['l402', 'lightning']`, `['cashu']`, `['x402', 'base', 'usdc', '<addr>']`, `['payment', 'lightning']`).
13
17
  - **Pricing**: Per-capability pricing via `price` tags (capability name, amount, currency).
14
18
  - **Decentralised discovery**: Events are published to standard Nostr relays. Any client can subscribe and filter.
19
+ - **Multi-transport**: A single event can carry multiple `url` tags (1–10). Use this when the same service is reachable via clearnet, Tor (.onion), or Handshake domains.
15
20
 
16
21
  ## API surface
17
22
 
18
- Two exports:
23
+ Three exports:
19
24
 
20
25
  - `announceService(config)` — build, sign, and publish to relays. Returns `{ eventId, pubkey, close() }`.
21
26
  - `buildAnnounceEvent(secretKey, config)` — build and sign without publishing. Returns a `VerifiedEvent`.
27
+ - `isPrivateHost(hostname)` — utility: returns true if hostname is a private/loopback address (SSRF guard).
28
+
29
+ Exported constant: `L402_ANNOUNCE_KIND = 31402`
22
30
 
23
31
  ## Ecosystem position
24
32
 
25
33
  ```
26
- toll-booth (paywall) → protects your API
27
- 402-announce (this) tells the world your API exists
28
- 402-mcp (discovery) AI agents find, pay, and consume your API
34
+ toll-booth (paywall) → protects your API with L402
35
+ toll-booth-announce (bridge) maps toll-booth config to 402-announce automatically
36
+ 402-announce (this) tells the world your API exists via kind 31402
37
+ 402-mcp (discovery) → AI agents find, pay, and consume your API
38
+ 402.pub (dashboard) → live view of all announcing services
29
39
  ```
30
40
 
31
41
  ## Details
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "402-announce",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "type": "module",
5
5
  "description": "Announce HTTP 402 services (L402 and x402) on Nostr for decentralised discovery. Kind 31402 parameterised replaceable events.",
6
6
  "license": "MIT",
@@ -17,7 +17,8 @@
17
17
  "LICENSE",
18
18
  "README.md",
19
19
  "llms.txt",
20
- "llms-full.txt"
20
+ "llms-full.txt",
21
+ "context7.json"
21
22
  ],
22
23
  "scripts": {
23
24
  "build": "tsc",
@@ -62,5 +63,9 @@
62
63
  },
63
64
  "engines": {
64
65
  "node": ">=18"
66
+ },
67
+ "funding": {
68
+ "type": "lightning",
69
+ "url": "lightning:thedonkey@strike.me"
65
70
  }
66
71
  }