From d7730126581b0c2a967f5ab5acbf543d1730c614 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 6 Jun 2025 22:36:07 -0300 Subject: [PATCH] proper auth support on pool.publish(). --- README.md | 2 +- abstract-pool.ts | 55 +++++++++++++++++++++++++++++++++++------------- jsr.json | 2 +- package.json | 2 +- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 99b6c19..b3bc34b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Tools for developing [Nostr](https://github.com/fiatjaf/nostr) clients. Only depends on _@scure_ and _@noble_ packages. -This package is only providing lower-level functionality. If you want more higher-level features, take a look at [Nostrify](https://nostrify.dev), or if you want an easy-to-use fully-fledged solution that abstracts the hard parts of Nostr and makes decisions on your behalf, take a look at [NDK](https://github.com/nostr-dev-kit/ndk) and [@snort/system](https://www.npmjs.com/package/@snort/system). +This package is only providing lower-level functionality. If you want higher-level features, take a look at [@nostr/gadgets](https://jsr.io/@nostr/gadgets) which is based on this library and expands upon it and has other goodies (it's only available on jsr). ## Installation diff --git a/abstract-pool.ts b/abstract-pool.ts index 9ddd031..33bd57e 100644 --- a/abstract-pool.ts +++ b/abstract-pool.ts @@ -19,6 +19,8 @@ export type AbstractPoolConstructorOptions = AbstractRelayConstructorOptions & { export type SubscribeManyParams = Omit & { maxWait?: number onclose?: (reasons: string[]) => void + onauth?: (event: EventTemplate) => Promise + // Deprecated: use onauth instead doauth?: (event: EventTemplate) => Promise id?: string label?: string @@ -63,6 +65,8 @@ export class AbstractSimplePool { } subscribe(relays: string[], filter: Filter, params: SubscribeManyParams): SubCloser { + params.onauth = params.onauth || params.doauth + return this.subscribeMap( relays.map(url => ({ url, filter })), params, @@ -70,6 +74,8 @@ export class AbstractSimplePool { } subscribeMany(relays: string[], filters: Filter[], params: SubscribeManyParams): SubCloser { + params.onauth = params.onauth || params.doauth + return this.subscribeMap( relays.flatMap(url => filters.map(filter => ({ url, filter }))), params, @@ -77,6 +83,8 @@ export class AbstractSimplePool { } subscribeMap(requests: { url: string; filter: Filter }[], params: SubscribeManyParams): SubCloser { + params.onauth = params.onauth || params.doauth + if (this.trackRelays) { params.receivedEvent = (relay: AbstractRelay, id: string) => { let set = this.seenOn.get(id) @@ -141,9 +149,9 @@ export class AbstractSimplePool { ...params, oneose: () => handleEose(i), onclose: reason => { - if (reason.startsWith('auth-required:') && params.doauth) { + if (reason.startsWith('auth-required: ') && params.onauth) { relay - .auth(params.doauth) + .auth(params.onauth) .then(() => { relay.subscribe([filter], { ...params, @@ -183,8 +191,10 @@ export class AbstractSimplePool { subscribeEose( relays: string[], filter: Filter, - params: Pick, + params: Pick, ): SubCloser { + params.onauth = params.onauth || params.doauth + const subcloser = this.subscribe(relays, filter, { ...params, oneose() { @@ -197,8 +207,10 @@ export class AbstractSimplePool { subscribeManyEose( relays: string[], filters: Filter[], - params: Pick, + params: Pick, ): SubCloser { + params.onauth = params.onauth || params.doauth + const subcloser = this.subscribeMany(relays, filters, { ...params, oneose() { @@ -238,7 +250,11 @@ export class AbstractSimplePool { return events[0] || null } - publish(relays: string[], event: Event): Promise[] { + publish( + relays: string[], + event: Event, + options?: { onauth?: (evt: EventTemplate) => Promise }, + ): Promise[] { return relays.map(normalizeURL).map(async (url, i, arr) => { if (arr.indexOf(url) !== i) { // duplicate @@ -246,17 +262,26 @@ export class AbstractSimplePool { } let r = await this.ensureRelay(url) - return r.publish(event).then(reason => { - if (this.trackRelays) { - let set = this.seenOn.get(event.id) - if (!set) { - set = new Set() - this.seenOn.set(event.id, set) + return r + .publish(event) + .catch(async err => { + if (err instanceof Error && err.message.startsWith('auth-required: ') && options?.onauth) { + await r.auth(options.onauth) + return r.publish(event) // retry } - set.add(r) - } - return reason - }) + throw err + }) + .then(reason => { + if (this.trackRelays) { + let set = this.seenOn.get(event.id) + if (!set) { + set = new Set() + this.seenOn.set(event.id, set) + } + set.add(r) + } + return reason + }) }) } diff --git a/jsr.json b/jsr.json index 2199a1d..63e76d4 100644 --- a/jsr.json +++ b/jsr.json @@ -1,6 +1,6 @@ { "name": "@nostr/tools", - "version": "2.14.2", + "version": "2.14.3", "exports": { ".": "./index.ts", "./core": "./core.ts", diff --git a/package.json b/package.json index a335613..890dd85 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "nostr-tools", - "version": "2.14.2", + "version": "2.14.3", "description": "Tools for making a Nostr client.", "repository": { "type": "git",