JSPM

  • Created
  • Published
  • Downloads 32892
  • Score
    100M100P100Q142865F

Tools for making a Nostr client.

Package Exports

  • nostr-tools
  • nostr-tools/lib/nostr.cjs.js
  • nostr-tools/lib/nostr.esm.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (nostr-tools) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

nostr-tools

Tools for developing Nostr clients.

Usage

Generating a private key and a public key

import { generatePrivateKey, getPublicKey } from 'nostr-tools'

let sk = generatePrivateKey() # `sk` is a hex string
let pk = getPublicKey(sk) # `pk` is a hex string

Creating, signing and verifying events

import {
  validateEvent,
  verifySignature,
  signEvent,
  getEventHash,
  getPublicKey
} from 'nostr-tools'

let event = {
  kind: 1,
  created_at: Math.floor(Date.now() / 1000),
  tags: [],
  content: 'hello'
}

event.id = getEventHash(event.id)
event.pubkey = getPublicKey(privateKey)
event.sig = await signEvent(event, privateKey)

let ok = validateEvent(event)
let veryOk = await verifySignature(event)

Interacting with a relay

import {
  relayInit,
  generatePrivateKey,
  getPublicKey,
  getEventHash,
  signEvent
} from 'nostr-tools'

const relay = relayInit('wss://relay.example.com')
relay.connect()

relay.on('connect', () => {
  console.log(`connected to ${relay.url}`)
})
relay.on('error', () => {
  console.log(`failed to connect to ${relay.url}`)
})

// let's query for an event that exists
let sub = relay.sub([
  {
    ids: ['d7dd5eb3ab747e16f8d0212d53032ea2a7cadef53837e5a6c66d42849fcb9027']
  }
])
sub.on('event', event => {
  console.log('we got the event we wanted:', event)
})
sub.on('eose', () => {
  sub.unsub()
})

// let's publish a new event while simultaneously monitoring the relay for it
let sk = generatePrivateKey()
let pk = getPublicKey(sk)

let sub = relay.sub([
  {
    kinds: [1],
    authors: [pk]
  }
])

sub.on('event', event => {
  console.log('got event:', event)
})

let event = {
  kind: 1,
  pubkey: pk,
  created_at: Math.floor(Date.now() / 1000),
  tags: [],
  content: 'hello world'
}
event.id = getEventHash(event)
event.sig = await signEvent(event, sk)

let pub = relay.publish(event)
pub.on('ok', () => {
  console.log(`{relay.url} has accepted our event`)
})
pub.on('seen', () => {
  console.log(`we saw the event on {relay.url}`)
})
pub.on('failed', reason => {
  console.log(`failed to publish to {relay.url}: ${reason}`)
})

await relay.close()

Encrypting and decrypting direct messages

import {nip04, getPublicKey, generatePrivateKey} from 'nostr-tools'

// sender
let sk1 = generatePrivateKey()
let pk1 = getPublicKey(sk1)

// receiver
let sk2 = generatePrivateKey()
let pk2 = getPublicKey(sk2)

// on the sender side
let message = 'hello'
let ciphertext = nip04.encrypt(sk1, pk2, 'hello')

let event = {
  kind: 4,
  pubkey: pk1,
  tags: [['p', pk2]],
  content: ciphertext,
  ...otherProperties
}

sendEvent(event)

// on the receiver side

sub.on('event', (event) => {
  let sender = event.tags.find(([k, v]) => k === 'p' && && v && v !== '')[1]
  pk1 === sender
  let plaintext = nip04.decrypt(sk2, pk1, event.content)
})

Please consult the tests or the source code for more information that isn't available here.

Using from the browser (if you don't want to use a bundler)

<script src="https://unpkg.com/nostr-tools/nostr.bundle.js"></script>
<script>
  window.NostrTools.generatePrivateKey('...') // and so on
</script>

License

Public domain.