mirror of
https://github.com/nbd-wtf/nostr-tools.git
synced 2025-12-09 00:28:51 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01f13292bb | ||
|
|
7b0458db72 | ||
|
|
3aab7121f7 |
41
README.md
41
README.md
@@ -19,7 +19,7 @@ If using TypeScript, this package requires TypeScript >= 5.0.
|
||||
### Generating a private key and a public key
|
||||
|
||||
```js
|
||||
import { generateSecretKey, getPublicKey } from 'nostr-tools'
|
||||
import { generateSecretKey, getPublicKey } from 'nostr-tools/pure'
|
||||
|
||||
let sk = generateSecretKey() // `sk` is a Uint8Array
|
||||
let pk = getPublicKey(sk) // `pk` is a hex string
|
||||
@@ -28,7 +28,7 @@ let pk = getPublicKey(sk) // `pk` is a hex string
|
||||
### Creating, signing and verifying events
|
||||
|
||||
```js
|
||||
import { finalizeEvent, verifyEvent } from 'nostr-tools'
|
||||
import { finalizeEvent, verifyEvent } from 'nostr-tools/pure'
|
||||
|
||||
let event = finalizeEvent({
|
||||
kind: 1,
|
||||
@@ -43,7 +43,8 @@ let isGood = verifyEvent(event)
|
||||
### Interacting with a relay
|
||||
|
||||
```js
|
||||
import { Relay, finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools'
|
||||
import { finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools/pure'
|
||||
import { Relay } from 'nostr-tools/relay'
|
||||
|
||||
const relay = await Relay.connect('wss://relay.example.com')
|
||||
console.log(`connected to ${relay.url}`)
|
||||
@@ -91,16 +92,17 @@ await relay.publish(signedEvent)
|
||||
relay.close()
|
||||
```
|
||||
|
||||
To use this on Node.js you first must install `websocket-polyfill` and import it:
|
||||
To use this on Node.js you first must install `ws` and call something like this:
|
||||
|
||||
```js
|
||||
import 'websocket-polyfill'
|
||||
import { useWebSocketImplementation } from 'nostr-tools/relay'
|
||||
useWebSocketImplementation(require('ws'))
|
||||
```
|
||||
|
||||
### Interacting with multiple relays
|
||||
|
||||
```js
|
||||
import { SimplePool } from 'nostr-tools'
|
||||
import { SimplePool } from 'nostr-tools/pool'
|
||||
|
||||
const pool = new SimplePool()
|
||||
|
||||
@@ -136,7 +138,7 @@ let event = await pool.get(relays, {
|
||||
### Parsing references (mentions) from a content using NIP-10 and NIP-27
|
||||
|
||||
```js
|
||||
import { parseReferences } from 'nostr-tools'
|
||||
import { parseReferences } from 'nostr-tools/references'
|
||||
|
||||
let references = parseReferences(event)
|
||||
let simpleAugmentedContent = event.content
|
||||
@@ -156,9 +158,9 @@ for (let i = 0; i < references.length; i++) {
|
||||
### Querying profile data from a NIP-05 address
|
||||
|
||||
```js
|
||||
import { nip05 } from 'nostr-tools'
|
||||
import { queryProfile } from 'nostr-tools/nip05'
|
||||
|
||||
let profile = await nip05.queryProfile('jb55.com')
|
||||
let profile = await queryProfile('jb55.com')
|
||||
console.log(profile.pubkey)
|
||||
// prints: 32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245
|
||||
console.log(profile.relays)
|
||||
@@ -168,13 +170,15 @@ console.log(profile.relays)
|
||||
To use this on Node.js < v18, you first must install `node-fetch@2` and call something like this:
|
||||
|
||||
```js
|
||||
nip05.useFetchImplementation(require('node-fetch'))
|
||||
import { useFetchImplementation } from 'nostr-tools/nip05'
|
||||
useFetchImplementation(require('node-fetch'))
|
||||
```
|
||||
|
||||
### Encoding and decoding NIP-19 codes
|
||||
|
||||
```js
|
||||
import { nip19, generateSecretKey, getPublicKey } from 'nostr-tools'
|
||||
import { generateSecretKey, getPublicKey } from 'nostr-tools/pure'
|
||||
import * as nip19 from 'nostr-tools/nip19'
|
||||
|
||||
let sk = generateSecretKey()
|
||||
let nsec = nip19.nsecEncode(sk)
|
||||
@@ -197,21 +201,6 @@ assert(data.pubkey === pk)
|
||||
assert(data.relays.length === 2)
|
||||
```
|
||||
|
||||
## Import modes
|
||||
|
||||
### Using just the packages you want
|
||||
|
||||
Importing the entirety of `nostr-tools` may bloat your build, so you should probably import individual packages instead:
|
||||
|
||||
```js
|
||||
import { generateSecretKey, finalizeEvent, verifyEvent } from 'nostr-tools/pure'
|
||||
import { SimplePool } from 'nostr-tools/pool'
|
||||
import { Relay, Subscription } from 'nostr-tools/relay'
|
||||
import { matchFilter } from 'nostr-tools/filter'
|
||||
import { decode, nprofileEncode, neventEncode, npubEncode } from 'nostr-tools/nip19'
|
||||
// and so on and so forth
|
||||
```
|
||||
|
||||
### Using it with `nostr-wasm`
|
||||
|
||||
[`nostr-wasm`](https://github.com/fiatjaf/nostr-wasm) is a thin wrapper over [libsecp256k1](https://github.com/bitcoin-core/secp256k1) compiled to WASM just for hashing, signing and verifying Nostr events.
|
||||
|
||||
@@ -7,6 +7,16 @@ import { Queue, normalizeURL } from './utils.ts'
|
||||
import { makeAuthEvent } from './nip42.ts'
|
||||
import { yieldThread } from './helpers.ts'
|
||||
|
||||
var _WebSocket: typeof WebSocket
|
||||
|
||||
try {
|
||||
_WebSocket = WebSocket
|
||||
} catch {}
|
||||
|
||||
export function useWebSocketImplementation(websocketImplementation: any) {
|
||||
_WebSocket = websocketImplementation
|
||||
}
|
||||
|
||||
export class AbstractRelay {
|
||||
public readonly url: string
|
||||
private _connected: boolean = false
|
||||
@@ -74,7 +84,7 @@ export class AbstractRelay {
|
||||
}, this.connectionTimeout)
|
||||
|
||||
try {
|
||||
this.ws = new WebSocket(this.url)
|
||||
this.ws = new _WebSocket(this.url)
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
return
|
||||
|
||||
28
nip46.ts
28
nip46.ts
@@ -74,7 +74,6 @@ export type BunkerSignerParams = {
|
||||
export class BunkerSigner {
|
||||
private pool: AbstractSimplePool
|
||||
private subCloser: SubCloser
|
||||
private relays: string[]
|
||||
private isOpen: boolean
|
||||
private serial: number
|
||||
private idPrefix: string
|
||||
@@ -85,8 +84,7 @@ export class BunkerSigner {
|
||||
}
|
||||
}
|
||||
private secretKey: Uint8Array
|
||||
private connectionSecret: string
|
||||
public remotePubkey: string
|
||||
public bp: BunkerPointer
|
||||
|
||||
/**
|
||||
* Creates a new instance of the Nip46 class.
|
||||
@@ -101,9 +99,7 @@ export class BunkerSigner {
|
||||
|
||||
this.pool = params.pool || new SimplePool()
|
||||
this.secretKey = clientSecretKey
|
||||
this.relays = bp.relays
|
||||
this.remotePubkey = bp.pubkey
|
||||
this.connectionSecret = bp.secret || ''
|
||||
this.bp = bp
|
||||
this.isOpen = false
|
||||
this.idPrefix = Math.random().toString(36).substring(7)
|
||||
this.serial = 0
|
||||
@@ -112,7 +108,7 @@ export class BunkerSigner {
|
||||
const listeners = this.listeners
|
||||
|
||||
this.subCloser = this.pool.subscribeMany(
|
||||
this.relays,
|
||||
this.bp.relays,
|
||||
[{ kinds: [NostrConnect, NostrConnectAdmin], '#p': [getPublicKey(this.secretKey)] }],
|
||||
{
|
||||
async onevent(event: NostrEvent) {
|
||||
@@ -154,17 +150,13 @@ export class BunkerSigner {
|
||||
this.serial++
|
||||
const id = `${this.idPrefix}-${this.serial}`
|
||||
|
||||
const encryptedContent = await encrypt(
|
||||
this.secretKey,
|
||||
this.remotePubkey,
|
||||
JSON.stringify({ id, method, params }),
|
||||
)
|
||||
const encryptedContent = await encrypt(this.secretKey, this.bp.pubkey, JSON.stringify({ id, method, params }))
|
||||
|
||||
// the request event
|
||||
const verifiedEvent: VerifiedEvent = finalizeEvent(
|
||||
{
|
||||
kind: method === 'create_account' ? NostrConnectAdmin : NostrConnect,
|
||||
tags: [['p', this.remotePubkey]],
|
||||
tags: [['p', this.bp.pubkey]],
|
||||
content: encryptedContent,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
},
|
||||
@@ -175,7 +167,7 @@ export class BunkerSigner {
|
||||
this.listeners[id] = { resolve, reject }
|
||||
|
||||
// publish the event
|
||||
await Promise.any(this.pool.publish(this.relays, verifiedEvent))
|
||||
await Promise.any(this.pool.publish(this.bp.relays, verifiedEvent))
|
||||
} catch (err) {
|
||||
reject(err)
|
||||
}
|
||||
@@ -195,7 +187,7 @@ export class BunkerSigner {
|
||||
* Calls the "connect" method on the bunker.
|
||||
*/
|
||||
async connect(): Promise<void> {
|
||||
await this.sendRequest('connect', [getPublicKey(this.secretKey), this.connectionSecret])
|
||||
await this.sendRequest('connect', [getPublicKey(this.secretKey), this.bp.secret || ''])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,7 +195,7 @@ export class BunkerSigner {
|
||||
* but instead we just returns the public key we already know.
|
||||
*/
|
||||
async getPublicKey(): Promise<string> {
|
||||
return this.remotePubkey
|
||||
return this.bp.pubkey
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +213,7 @@ export class BunkerSigner {
|
||||
async signEvent(event: UnsignedEvent): Promise<VerifiedEvent> {
|
||||
let resp = await this.sendRequest('sign_event', [JSON.stringify(event)])
|
||||
let signed: NostrEvent = JSON.parse(resp)
|
||||
if (signed.pubkey === this.remotePubkey && verifyEvent(signed)) {
|
||||
if (signed.pubkey === this.bp.pubkey && verifyEvent(signed)) {
|
||||
return signed
|
||||
} else {
|
||||
throw new Error(`event returned from bunker is improperly signed: ${JSON.stringify(signed)}`)
|
||||
@@ -275,7 +267,7 @@ export async function createAccount(
|
||||
|
||||
// once we get the newly created pubkey back, we hijack this signer instance
|
||||
// and turn it into the main instance for this newly created pubkey
|
||||
rpc.remotePubkey = pubkey
|
||||
rpc.bp.pubkey = pubkey
|
||||
await rpc.connect()
|
||||
|
||||
return rpc
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "module",
|
||||
"name": "nostr-tools",
|
||||
"version": "2.1.8",
|
||||
"version": "2.1.9",
|
||||
"description": "Tools for making a Nostr client.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user