diff --git a/libraries/nestjs-libraries/src/integrations/social/nostr.provider.ts b/libraries/nestjs-libraries/src/integrations/social/nostr.provider.ts index 3797117c..291dd89d 100644 --- a/libraries/nestjs-libraries/src/integrations/social/nostr.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/nostr.provider.ts @@ -7,7 +7,8 @@ import { import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; import dayjs from 'dayjs'; import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract'; -import { getPublicKey, Relay, finalizeEvent } from 'nostr-tools'; +import { getPublicKey, Relay, finalizeEvent, SimplePool } from 'nostr-tools'; + import WebSocket from 'ws'; import { AuthService } from '@gitroom/helpers/auth/auth.service'; @@ -15,14 +16,15 @@ import { AuthService } from '@gitroom/helpers/auth/auth.service'; global.WebSocket = WebSocket; const list = [ - 'wss://relay.primal.net', + 'wss://nos.lol', 'wss://relay.damus.io', 'wss://relay.snort.social', - 'wss://nostr.wine', - 'wss://nos.lol', - 'wss://relay.primal.net', + 'wss://temp.iris.to', + 'wss://vault.iris.to', ]; +const pool = new SimplePool(); + export class NostrProvider extends SocialAbstract implements SocialProvider { override maxConcurrentJob = 5; // Nostr relays typically have generous limits identifier = 'nostr'; @@ -68,29 +70,25 @@ export class NostrProvider extends SocialAbstract implements SocialProvider { } private async findRelayInformation(pubkey: string) { - for (const relay of list) { - const relayInstance = await Relay.connect(relay); - const value = await new Promise((resolve) => { - console.log('connecting'); - relayInstance.subscribe([{ kinds: [0], authors: [pubkey] }], { - eoseTimeout: 6000, - onevent: (event) => { - resolve(event); - }, - oneose: () => { - resolve({}); - }, - onclose: () => { - resolve({}); - }, - }); - }); + // This queries ALL relays in parallel and resolves with + // the first matching event from ANY relay. + const evt = await pool.get(list, { + kinds: [0], + authors: [pubkey], + limit: 1, + }); - relayInstance.close(); - const content = JSON.parse(value?.content || '{}'); - if (content.name || content.displayName || content.display_name) { - return content; - } + if (!evt) return {}; + + let content: any = {}; + try { + content = JSON.parse(evt.content || '{}'); + } catch { + return {}; + } + + if (content.name || content.displayName || content.display_name) { + return content; } return {}; @@ -146,7 +144,7 @@ export class NostrProvider extends SocialAbstract implements SocialProvider { const user = await this.findRelayInformation(pubkey); return { - id: String(user.pubkey), + id: pubkey, name: user.display_name || user.displayName || 'No Name', accessToken: AuthService.signJWT({ password: body.password }), refreshToken: '', diff --git a/package.json b/package.json index b71b6a96..e94b0c8a 100644 --- a/package.json +++ b/package.json @@ -80,9 +80,9 @@ "@postiz/wallets": "^0.0.1", "@prisma/client": "6.5.0", "@sentry/nestjs": "^10.25.0", - "@sentry/react": "^10.25.0", "@sentry/nextjs": "^10.25.0", "@sentry/profiling-node": "^10.25.0", + "@sentry/react": "^10.25.0", "@solana/wallet-adapter-react": "^0.15.35", "@solana/wallet-adapter-react-ui": "^0.9.35", "@swc/helpers": "0.5.13", @@ -182,7 +182,7 @@ "node-fetch": "^3.3.2", "node-telegram-bot-api": "^0.66.0", "nodemailer": "^6.9.15", - "nostr-tools": "^2.10.4", + "nostr-tools": "^2.18.2", "openai": "^6.2.0", "p-limit": "^3.1.0", "parse5": "^6.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e3d402cc..33b68f5a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -424,8 +424,8 @@ importers: specifier: ^6.9.15 version: 6.10.1 nostr-tools: - specifier: ^2.10.4 - version: 2.17.3(typescript@5.5.4) + specifier: ^2.18.2 + version: 2.18.2(typescript@5.5.4) openai: specifier: ^6.2.0 version: 6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) @@ -13250,8 +13250,8 @@ packages: normalize.css@8.0.1: resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==} - nostr-tools@2.17.3: - resolution: {integrity: sha512-86v635D/0cvUEd0sHkh4h4Mp706UUMa5UHSXZ6YaIsURvyGgah4CwWDieJRzbVHdKBfGsQm4B20e9JFhEpAhxg==} + nostr-tools@2.18.2: + resolution: {integrity: sha512-lUCJQd9YZG3kEvxV5Zgm7qUkBpaeuvFrtqBz4TJLAxHzUn2pE7nmZZRDQmNzp5neEw20tQS3jR16o7XzzF8ncg==} peerDependencies: typescript: '>=5.0.0' peerDependenciesMeta: @@ -23435,8 +23435,8 @@ snapshots: '@scure/bip32@1.3.1': dependencies: '@noble/curves': 1.1.0 - '@noble/hashes': 1.3.1 - '@scure/base': 1.1.1 + '@noble/hashes': 1.3.2 + '@scure/base': 1.1.9 '@scure/bip32@1.4.0': dependencies: @@ -23452,14 +23452,14 @@ snapshots: '@scure/bip32@1.7.0': dependencies: - '@noble/curves': 1.9.1 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@scure/bip39@1.2.1': dependencies: - '@noble/hashes': 1.3.1 - '@scure/base': 1.1.1 + '@noble/hashes': 1.3.2 + '@scure/base': 1.1.9 '@scure/bip39@1.3.0': dependencies: @@ -33500,7 +33500,7 @@ snapshots: normalize.css@8.0.1: {} - nostr-tools@2.17.3(typescript@5.5.4): + nostr-tools@2.18.2(typescript@5.5.4): dependencies: '@noble/ciphers': 0.5.3 '@noble/curves': 1.2.0 @@ -33723,10 +33723,10 @@ snapshots: ox@0.6.7(typescript@5.5.4)(zod@3.25.76): dependencies: '@adraffy/ens-normalize': 1.11.1 - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@scure/bip32': 1.6.2 - '@scure/bip39': 1.5.4 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 abitype: 1.0.8(typescript@5.5.4)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: