{"library":"nostr-tools","title":"Nostr Client Development Tools","description":"nostr-tools is a core JavaScript/TypeScript library providing low-level utilities for developing Nostr clients. It enables essential functionalities such as generating Nostr secret and public keys, creating and signing events, verifying event integrity, and interacting with Nostr relays through a `SimplePool` abstraction. The current stable version is 2.23.3, and the project appears to have an active release cadence, evidenced by significant breaking changes in version 2.0.0 and subsequent updates. Key differentiators include its minimalist dependency footprint, relying primarily on `@scure` and `@noble` cryptography packages, and its modular structure which allows importing only necessary components. It specifically focuses on lower-level primitives, suggesting `@nostr/gadgets` for higher-level client features. It also provides robust relay management features like configurable pinging and automatic reconnection.","language":"javascript","status":"active","last_verified":"Tue Apr 21","install":{"commands":["npm install nostr-tools"],"cli":null},"imports":["import { generateSecretKey, getPublicKey } from '@nostr/tools/pure'","import { finalizeEvent, verifyEvent } from '@nostr/tools/pure'","import { SimplePool } from '@nostr/tools/pool'","import { useWebSocketImplementation } from '@nostr/tools/pool'"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import { finalizeEvent, generateSecretKey, getPublicKey } from '@nostr/tools/pure';\nimport { SimplePool, useWebSocketImplementation } from '@nostr/tools/pool';\nimport WebSocket from 'ws'; // For Node.js environments\nimport { bytesToHex } from '@noble/hashes/utils'; // For convenience\n\n// For Node.js, set up the WebSocket implementation\nuseWebSocketImplementation(WebSocket);\n\nasync function runNostrClient() {\n  const pool = new SimplePool({ enablePing: true, enableReconnect: true });\n\n  // Use a real, publicly available relay for testing\n  const relays = ['wss://relay.damus.io', 'wss://nostr.wine', 'wss://eden.nostr.land'];\n\n  // 1. Generate keys\n  let sk = generateSecretKey(); // Uint8Array\n  let pk = getPublicKey(sk); // hex string\n  console.log(`Generated secret key (hex): ${bytesToHex(sk)}`);\n  console.log(`Generated public key (hex): ${pk}`);\n\n  // 2. Create and sign an event\n  let eventTemplate = {\n    kind: 1, // Text Note\n    created_at: Math.floor(Date.now() / 1000),\n    tags: [],\n    content: `Hello Nostr from nostr-tools! This is a test event from a registry quickstart. ${Math.random()}`,\n  };\n  const signedEvent = finalizeEvent(eventTemplate, sk);\n  console.log('Signed event:', signedEvent);\n\n  // 3. Publish the event to a couple of relays\n  console.log(`Publishing event to ${relays.slice(0, 2).join(', ')}...`);\n  try {\n    // Promise.any will resolve as soon as one relay successfully publishes\n    await Promise.any(pool.publish(relays.slice(0, 2), signedEvent));\n    console.log('Event published successfully to at least one relay.');\n  } catch (error) {\n    console.error('Failed to publish event to any relay:', error);\n  }\n\n  // 4. Subscribe to events from our public key\n  console.log(`Subscribing to events from public key ${pk}...`);\n  const sub = pool.subscribe(\n    relays,\n    {\n      kinds: [1],\n      authors: [pk],\n      since: Math.floor(Date.now() / 1000) - 60, // Look for events in the last 60 seconds\n    },\n    {\n      onevent(event) {\n        console.log('Received own event:', event.content);\n        // Once we receive our own event, we can unsubscribe if desired\n        sub.close();\n      },\n      oneose() {\n        console.log('Subscription End of Stored Events (EOSE) received.');\n      },\n      onclose(wasClean: boolean) {\n        console.log(`Subscription closed (wasClean: ${wasClean}).`);\n      }\n    }\n  );\n\n  // Optional: Query for some existing events\n  console.log('Querying for recent text notes (kind 1)...');\n  const recentEvents = await pool.querySync(\n    relays,\n    {\n      kinds: [1],\n      limit: 5,\n    },\n    {\n      onprogress(percent: number) {\n        // console.log(`Query progress: ${Math.round(percent)}%`);\n      }\n    }\n  );\n  if (recentEvents && recentEvents.length > 0) {\n    console.log(`Found ${recentEvents.length} recent events. Example:`, recentEvents[0].content);\n  } else {\n    console.log('No recent events found.');\n  }\n\n  // Allow some time for events to propagate and be received\n  await new Promise(resolve => setTimeout(resolve, 5000));\n\n  pool.close(); // Close all relay connections\n  console.log('Pool closed.');\n}\n\nrunNostrClient().catch(console.error);","lang":"typescript","description":"Demonstrates generating Nostr keys, creating and signing an event, publishing it to relays, subscribing to events from a public key, and configuring the WebSocket implementation for Node.js.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":null}