Compare commits
6 Commits
eb73d2a34b
...
282b41d2a6
Author | SHA1 | Date |
---|---|---|
|
282b41d2a6 | |
|
23aebbd341 | |
|
a3fcd79545 | |
|
0e6e7af934 | |
|
8866042edf | |
|
57f297be52 |
|
@ -169,8 +169,10 @@ for (let block of nip27.parse(evt.content)) {
|
||||||
case 'video':
|
case 'video':
|
||||||
case 'audio':
|
case 'audio':
|
||||||
console.log("it's a media url:", block.url)
|
console.log("it's a media url:", block.url)
|
||||||
|
break
|
||||||
case 'relay':
|
case 'relay':
|
||||||
console.log("it's a websocket url, probably a relay address:", block.url)
|
console.log("it's a websocket url, probably a relay address:", block.url)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -191,7 +193,7 @@ const localSecretKey = generateSecretKey()
|
||||||
|
|
||||||
### Method 1: Using a Bunker URI (`bunker://`)
|
### Method 1: Using a Bunker URI (`bunker://`)
|
||||||
|
|
||||||
This is the bunker-initiated flow. Your client receives a `bunker://` string or a NIP-05 identifier from the user. You use `BunkerSigner.fromBunker()` to create an instance, which returns immediately. You must then explicitly call `await bunker.connect()` to establish the connection with the bunker.
|
This is the bunker-initiated flow. Your client receives a `bunker://` string or a NIP-05 identifier from the user. You use `BunkerSigner.fromBunker()` to create an instance, which returns immediately. For the **initial connection** with a new bunker, you must explicitly call `await bunker.connect()` to establish the connection and receive authorization.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { BunkerSigner, parseBunkerInput } from '@nostr/tools/nip46'
|
import { BunkerSigner, parseBunkerInput } from '@nostr/tools/nip46'
|
||||||
|
@ -221,6 +223,7 @@ const event = await bunker.signEvent({
|
||||||
await signer.close()
|
await signer.close()
|
||||||
pool.close([])
|
pool.close([])
|
||||||
```
|
```
|
||||||
|
> **Note on Reconnecting:** Once a connection has been successfully established and the `BunkerPointer` is stored, you do **not** need to call `await bunker.connect()` on subsequent sessions.
|
||||||
|
|
||||||
### Method 2: Using a Client-generated URI (`nostrconnect://`)
|
### Method 2: Using a Client-generated URI (`nostrconnect://`)
|
||||||
|
|
||||||
|
@ -260,6 +263,7 @@ const event = await signer.signEvent({
|
||||||
await signer.close()
|
await signer.close()
|
||||||
pool.close([])
|
pool.close([])
|
||||||
```
|
```
|
||||||
|
> **Note on Persistence:** This method is ideal for the initial sign-in. To allow users to stay logged in across sessions, you should store the connection details and use `Method 1` for subsequent reconnections.
|
||||||
|
|
||||||
### Parsing thread from any note based on NIP-10
|
### Parsing thread from any note based on NIP-10
|
||||||
|
|
||||||
|
|
|
@ -121,23 +121,19 @@ export class AbstractRelay {
|
||||||
this.ws.onerror = ev => {
|
this.ws.onerror = ev => {
|
||||||
clearTimeout(this.connectionTimeoutHandle)
|
clearTimeout(this.connectionTimeoutHandle)
|
||||||
reject((ev as any).message || 'websocket error')
|
reject((ev as any).message || 'websocket error')
|
||||||
if (this._connected) {
|
this._connected = false
|
||||||
this._connected = false
|
this.connectionPromise = undefined
|
||||||
this.connectionPromise = undefined
|
this.onclose?.()
|
||||||
this.onclose?.()
|
this.closeAllSubscriptions('relay connection errored')
|
||||||
this.closeAllSubscriptions('relay connection errored')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ws.onclose = ev => {
|
this.ws.onclose = ev => {
|
||||||
clearTimeout(this.connectionTimeoutHandle)
|
clearTimeout(this.connectionTimeoutHandle)
|
||||||
reject((ev as any).message || 'websocket closed')
|
reject((ev as any).message || 'websocket closed')
|
||||||
if (this._connected) {
|
this._connected = false
|
||||||
this._connected = false
|
this.connectionPromise = undefined
|
||||||
this.connectionPromise = undefined
|
this.onclose?.()
|
||||||
this.onclose?.()
|
this.closeAllSubscriptions('relay connection closed')
|
||||||
this.closeAllSubscriptions('relay connection closed')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ws.onmessage = this._onmessage.bind(this)
|
this.ws.onmessage = this._onmessage.bind(this)
|
||||||
|
@ -187,8 +183,8 @@ export class AbstractRelay {
|
||||||
// pingpong closing socket
|
// pingpong closing socket
|
||||||
this.closeAllSubscriptions('pingpong timed out')
|
this.closeAllSubscriptions('pingpong timed out')
|
||||||
this._connected = false
|
this._connected = false
|
||||||
this.ws?.close()
|
|
||||||
this.onclose?.()
|
this.onclose?.()
|
||||||
|
this.ws?.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,8 +374,8 @@ export class AbstractRelay {
|
||||||
public close() {
|
public close() {
|
||||||
this.closeAllSubscriptions('relay connection closed by us')
|
this.closeAllSubscriptions('relay connection closed by us')
|
||||||
this._connected = false
|
this._connected = false
|
||||||
this.ws?.close()
|
|
||||||
this.onclose?.()
|
this.onclose?.()
|
||||||
|
this.ws?.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is the function assigned to this.ws.onmessage
|
// this is the function assigned to this.ws.onmessage
|
||||||
|
@ -430,7 +426,7 @@ export class Subscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
public fire() {
|
public fire() {
|
||||||
this.relay.send('["REQ","' + this.id + '",' + JSON.stringify(this.filters).substring(1))
|
this.relay.send(JSON.stringify(['REQ', this.id, ...this.filters]))
|
||||||
|
|
||||||
// only now we start counting the eoseTimeout
|
// only now we start counting the eoseTimeout
|
||||||
this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout)
|
this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout)
|
||||||
|
|
2
jsr.json
2
jsr.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@nostr/tools",
|
"name": "@nostr/tools",
|
||||||
"version": "2.16.2",
|
"version": "2.17.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./index.ts",
|
".": "./index.ts",
|
||||||
"./core": "./core.ts",
|
"./core": "./core.ts",
|
||||||
|
|
22
nip27.ts
22
nip27.ts
|
@ -90,35 +90,19 @@ export function* parse(content: string): Iterable<Block> {
|
||||||
yield { type: 'text', text: content.substring(prevIndex, u - prefixLen) }
|
yield { type: 'text', text: content.substring(prevIndex, u - prefixLen) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (/\.(png|jpe?g|gif|webp)$/i.test(url.pathname)) {
|
||||||
url.pathname.endsWith('.png') ||
|
|
||||||
url.pathname.endsWith('.jpg') ||
|
|
||||||
url.pathname.endsWith('.jpeg') ||
|
|
||||||
url.pathname.endsWith('.gif') ||
|
|
||||||
url.pathname.endsWith('.webp')
|
|
||||||
) {
|
|
||||||
yield { type: 'image', url: url.toString() }
|
yield { type: 'image', url: url.toString() }
|
||||||
index = end
|
index = end
|
||||||
prevIndex = index
|
prevIndex = index
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (
|
if (/\.(mp4|avi|webm|mkv)$/i.test(url.pathname)) {
|
||||||
url.pathname.endsWith('.mp4') ||
|
|
||||||
url.pathname.endsWith('.avi') ||
|
|
||||||
url.pathname.endsWith('.webm') ||
|
|
||||||
url.pathname.endsWith('.mkv')
|
|
||||||
) {
|
|
||||||
yield { type: 'video', url: url.toString() }
|
yield { type: 'video', url: url.toString() }
|
||||||
index = end
|
index = end
|
||||||
prevIndex = index
|
prevIndex = index
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (
|
if (/\.(mp3|aac|ogg|opus)$/i.test(url.pathname)) {
|
||||||
url.pathname.endsWith('.mp3') ||
|
|
||||||
url.pathname.endsWith('.aac') ||
|
|
||||||
url.pathname.endsWith('.ogg') ||
|
|
||||||
url.pathname.endsWith('.opus')
|
|
||||||
) {
|
|
||||||
yield { type: 'audio', url: url.toString() }
|
yield { type: 'audio', url: url.toString() }
|
||||||
index = end
|
index = end
|
||||||
prevIndex = index
|
prevIndex = index
|
||||||
|
|
8
nip46.ts
8
nip46.ts
|
@ -97,7 +97,7 @@ export type ParsedNostrConnectURI = {
|
||||||
name?: string
|
name?: string
|
||||||
url?: string
|
url?: string
|
||||||
image?: string
|
image?: string
|
||||||
};
|
}
|
||||||
originalString: string
|
originalString: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,6 @@ export function parseNostrConnectURI(uri: string): ParsedNostrConnectURI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type BunkerSignerParams = {
|
export type BunkerSignerParams = {
|
||||||
pool?: AbstractSimplePool
|
pool?: AbstractSimplePool
|
||||||
onauth?: (url: string) => void
|
onauth?: (url: string) => void
|
||||||
|
@ -236,7 +235,7 @@ export class BunkerSigner implements Signer {
|
||||||
public static fromBunker(
|
public static fromBunker(
|
||||||
clientSecretKey: Uint8Array,
|
clientSecretKey: Uint8Array,
|
||||||
bp: BunkerPointer,
|
bp: BunkerPointer,
|
||||||
params: BunkerSignerParams = {}
|
params: BunkerSignerParams = {},
|
||||||
): BunkerSigner {
|
): BunkerSigner {
|
||||||
if (bp.relays.length === 0) {
|
if (bp.relays.length === 0) {
|
||||||
throw new Error('No relays specified for this bunker')
|
throw new Error('No relays specified for this bunker')
|
||||||
|
@ -304,12 +303,11 @@ export class BunkerSigner implements Signer {
|
||||||
reject(new Error('Subscription closed before connection was established.'))
|
reject(new Error('Subscription closed before connection was established.'))
|
||||||
},
|
},
|
||||||
maxWait,
|
maxWait,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private setupSubscription(params: BunkerSignerParams) {
|
private setupSubscription(params: BunkerSignerParams) {
|
||||||
const listeners = this.listeners
|
const listeners = this.listeners
|
||||||
const waitingForAuth = this.waitingForAuth
|
const waitingForAuth = this.waitingForAuth
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"name": "nostr-tools",
|
"name": "nostr-tools",
|
||||||
"version": "2.16.2",
|
"version": "2.17.0",
|
||||||
"description": "Tools for making a Nostr client.",
|
"description": "Tools for making a Nostr client.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
Loading…
Reference in New Issue