@openclaw/nostr 2026.7.1-beta.2 → 2026.7.1-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +5 -16
- package/dist/{channel-CV0aX1uq.js → channel-B2Y66pl3.js} +11 -4
- package/dist/channel-plugin-api.js +1 -1
- package/dist/doctor-contract-api.js +3 -22
- package/dist/setup-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BqBa2C0K.js → setup-surface-CKamwGa3.js} +1 -1
- package/node_modules/nostr-tools/README.md +37 -15
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js +134 -6
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js +35 -6
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/filter.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/index.js +401 -72
- package/node_modules/nostr-tools/lib/cjs/index.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/kinds.js +196 -4
- package/node_modules/nostr-tools/lib/cjs/kinds.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip10.js +5 -4
- package/node_modules/nostr-tools/lib/cjs/nip10.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip17.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip18.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip19.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip19.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip21.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip21.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip22.js +11 -5
- package/node_modules/nostr-tools/lib/cjs/nip22.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip25.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip27.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip27.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip28.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip29.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip29.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip42.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip45.js +183 -0
- package/node_modules/nostr-tools/lib/cjs/nip45.js.map +7 -0
- package/node_modules/nostr-tools/lib/cjs/nip46.js +149 -9
- package/node_modules/nostr-tools/lib/cjs/nip46.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip47.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip49.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip57.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip58.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip59.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip75.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip94.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip98.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip99.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nipb0.js +1064 -0
- package/node_modules/nostr-tools/lib/cjs/nipb0.js.map +7 -0
- package/node_modules/nostr-tools/lib/cjs/pool.js +134 -6
- package/node_modules/nostr-tools/lib/cjs/pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/references.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/references.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/relay.js +35 -6
- package/node_modules/nostr-tools/lib/cjs/relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js +134 -6
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js +35 -6
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/filter.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/index.js +377 -48
- package/node_modules/nostr-tools/lib/esm/index.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/kinds.js +196 -4
- package/node_modules/nostr-tools/lib/esm/kinds.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip10.js +5 -4
- package/node_modules/nostr-tools/lib/esm/nip10.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip17.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip18.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip19.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip19.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip21.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip21.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip22.js +11 -5
- package/node_modules/nostr-tools/lib/esm/nip22.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip25.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip27.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip27.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip28.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip29.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip29.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip42.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip45.js +162 -0
- package/node_modules/nostr-tools/lib/esm/nip45.js.map +7 -0
- package/node_modules/nostr-tools/lib/esm/nip46.js +149 -9
- package/node_modules/nostr-tools/lib/esm/nip46.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip47.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip49.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip57.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip58.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip59.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip75.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip94.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip98.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip99.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nipb0.js +1049 -0
- package/node_modules/nostr-tools/lib/esm/nipb0.js.map +7 -0
- package/node_modules/nostr-tools/lib/esm/pool.js +134 -6
- package/node_modules/nostr-tools/lib/esm/pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/references.js +2 -0
- package/node_modules/nostr-tools/lib/esm/references.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/relay.js +35 -6
- package/node_modules/nostr-tools/lib/esm/relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/nostr.bundle.js +350 -23
- package/node_modules/nostr-tools/lib/nostr.bundle.js.map +4 -4
- package/node_modules/nostr-tools/lib/types/abstract-pool.d.ts +9 -0
- package/node_modules/nostr-tools/lib/types/abstract-relay.d.ts +10 -1
- package/node_modules/nostr-tools/lib/types/kinds.d.ts +200 -8
- package/node_modules/nostr-tools/lib/types/nip45.d.ts +13 -0
- package/node_modules/nostr-tools/lib/types/nip45.test.d.ts +1 -0
- package/node_modules/nostr-tools/lib/types/nip46.d.ts +12 -5
- package/node_modules/nostr-tools/lib/types/nipb0.d.ts +129 -0
- package/node_modules/nostr-tools/package.json +13 -1
- package/npm-shrinkwrap.json +7 -7
- package/package.json +5 -5
package/dist/api.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { o as resolveNostrAccount } from "./setup-surface-
|
|
1
|
+
import { o as resolveNostrAccount } from "./setup-surface-CKamwGa3.js";
|
|
2
2
|
import { getPluginRuntimeGatewayRequestScope } from "./runtime-api.js";
|
|
3
3
|
import { n as NostrProfileSchema } from "./config-schema-DIiXiBKr.js";
|
|
4
|
-
import { a as setNostrRuntime, i as getNostrRuntime, n as nostrPlugin, o as contentToProfile, r as publishNostrProfile, t as getNostrProfileState } from "./channel-
|
|
4
|
+
import { a as setNostrRuntime, i as getNostrRuntime, n as nostrPlugin, o as contentToProfile, r as publishNostrProfile, t as getNostrProfileState } from "./channel-B2Y66pl3.js";
|
|
5
5
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { SimplePool, verifyEvent } from "nostr-tools";
|
|
8
8
|
import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
9
|
+
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
9
10
|
import { readJsonBodyWithLimit, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-request-guards";
|
|
10
11
|
import { createFixedWindowRateLimiter } from "openclaw/plugin-sdk/webhook-ingress";
|
|
11
12
|
import { isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
@@ -199,21 +200,9 @@ const profileRateLimiter = createFixedWindowRateLimiter({
|
|
|
199
200
|
function checkRateLimit(accountId) {
|
|
200
201
|
return !profileRateLimiter.isRateLimited(accountId);
|
|
201
202
|
}
|
|
202
|
-
const publishLocks =
|
|
203
|
+
const publishLocks = new KeyedAsyncQueue();
|
|
203
204
|
async function withPublishLock(accountId, fn) {
|
|
204
|
-
|
|
205
|
-
let resolve;
|
|
206
|
-
const next = new Promise((r) => {
|
|
207
|
-
resolve = r;
|
|
208
|
-
});
|
|
209
|
-
publishLocks.set(accountId, next);
|
|
210
|
-
await prev.catch(() => {});
|
|
211
|
-
try {
|
|
212
|
-
return await fn();
|
|
213
|
-
} finally {
|
|
214
|
-
resolve();
|
|
215
|
-
if (publishLocks.get(accountId) === next) publishLocks.delete(accountId);
|
|
216
|
-
}
|
|
205
|
+
return await publishLocks.enqueue(accountId, fn);
|
|
217
206
|
}
|
|
218
207
|
const nip05FormatSchema = z.string().regex(/^[a-z0-9._-]+@[a-z0-9.-]+\.[a-z]{2,}$/i, "Invalid NIP-05 format (user@domain.com)").optional();
|
|
219
208
|
const lud16FormatSchema = z.string().regex(/^[a-z0-9._-]+@[a-z0-9.-]+\.[a-z]{2,}$/i, "Invalid Lightning address format").optional();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveDefaultNostrAccountId, c as validatePrivateKey, i as listNostrAccountIds, n as nostrSetupWizard, o as resolveNostrAccount, s as normalizePubkey, t as nostrSetupAdapter } from "./setup-surface-
|
|
1
|
+
import { a as resolveDefaultNostrAccountId, c as validatePrivateKey, i as listNostrAccountIds, n as nostrSetupWizard, o as resolveNostrAccount, s as normalizePubkey, t as nostrSetupAdapter } from "./setup-surface-CKamwGa3.js";
|
|
2
2
|
import { a as collectStatusIssuesFromLastError, i as buildChannelConfigSchema, n as NostrProfileSchema, o as createDefaultChannelRuntimeState, r as DEFAULT_ACCOUNT_ID, s as formatPairingApproveHint, t as NostrConfigSchema } from "./config-schema-DIiXiBKr.js";
|
|
3
3
|
import { i as DEFAULT_RELAYS } from "./setup-adapter-DEU3o8MF.js";
|
|
4
4
|
import { t as normalizeNostrStateAccountId } from "./state-account-id-CvBZ9s6P.js";
|
|
@@ -969,7 +969,8 @@ async function startNostrBus(options) {
|
|
|
969
969
|
await sendEncryptedDm(pool, sk, toPubkey, text, relays, metrics, circuitBreakers, healthTracker, onError);
|
|
970
970
|
};
|
|
971
971
|
const publishProfile$1 = async (profile) => {
|
|
972
|
-
const
|
|
972
|
+
const lastPublishedAt = (await readNostrProfileState({ accountId }))?.lastPublishedAt ?? void 0;
|
|
973
|
+
const result = await publishProfile(pool, sk, relays, profile, lastPublishedAt);
|
|
973
974
|
const publishResults = {};
|
|
974
975
|
for (const relay of result.successes) publishResults[relay] = "ok";
|
|
975
976
|
for (const { relay, error } of result.failures) publishResults[relay] = error === "timeout" ? "timeout" : "failed";
|
|
@@ -1276,13 +1277,19 @@ function getActiveNostrBuses() {
|
|
|
1276
1277
|
//#endregion
|
|
1277
1278
|
//#region extensions/nostr/src/session-route.ts
|
|
1278
1279
|
function resolveNostrOutboundSessionRoute(params) {
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1280
|
+
const rawTarget = stripChannelTargetPrefix(params.target, "nostr");
|
|
1281
|
+
let target;
|
|
1282
|
+
try {
|
|
1283
|
+
target = normalizePubkey(rawTarget);
|
|
1284
|
+
} catch {
|
|
1285
|
+
return null;
|
|
1286
|
+
}
|
|
1281
1287
|
return buildChannelOutboundSessionRoute({
|
|
1282
1288
|
cfg: params.cfg,
|
|
1283
1289
|
agentId: params.agentId,
|
|
1284
1290
|
channel: "nostr",
|
|
1285
1291
|
accountId: params.accountId,
|
|
1292
|
+
recipientSessionExact: true,
|
|
1286
1293
|
peer: {
|
|
1287
1294
|
kind: "direct",
|
|
1288
1295
|
id: target
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as nostrPlugin } from "./channel-
|
|
1
|
+
import { n as nostrPlugin } from "./channel-B2Y66pl3.js";
|
|
2
2
|
export { nostrPlugin };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as normalizeNostrStateAccountId } from "./state-account-id-CvBZ9s6P.js";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { archiveLegacyStateSource } from "openclaw/plugin-sdk/runtime-doctor";
|
|
4
5
|
//#region extensions/nostr/doctor-contract-api.ts
|
|
5
6
|
const BUS_STATE_NAMESPACE = "bus-state";
|
|
6
7
|
const PROFILE_STATE_NAMESPACE = "profile-state";
|
|
@@ -35,13 +36,6 @@ function parseProfileState(value) {
|
|
|
35
36
|
lastPublishResults: rawResults === null || Object.keys(lastPublishResults).length === 0 ? null : lastPublishResults
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
|
-
async function fileExists(filePath) {
|
|
39
|
-
try {
|
|
40
|
-
return (await fs.stat(filePath)).isFile();
|
|
41
|
-
} catch {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
39
|
async function readJsonFile(filePath) {
|
|
46
40
|
return JSON.parse(await fs.readFile(filePath, "utf8"));
|
|
47
41
|
}
|
|
@@ -70,19 +64,6 @@ async function listLegacyFiles(params) {
|
|
|
70
64
|
}
|
|
71
65
|
return files;
|
|
72
66
|
}
|
|
73
|
-
async function archiveLegacySource(params) {
|
|
74
|
-
const archivedPath = `${params.filePath}.migrated`;
|
|
75
|
-
if (await fileExists(archivedPath)) {
|
|
76
|
-
params.warnings.push(`Left migrated ${params.label} source in place because ${archivedPath} already exists`);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
await fs.rename(params.filePath, archivedPath);
|
|
81
|
-
params.changes.push(`Archived ${params.label} legacy source -> ${archivedPath}`);
|
|
82
|
-
} catch (err) {
|
|
83
|
-
params.warnings.push(`Failed archiving ${params.label} legacy source: ${String(err)}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
67
|
async function ensureStoreCapacity(params) {
|
|
87
68
|
const existingKeys = new Set((await params.store.entries()).map((entry) => entry.key));
|
|
88
69
|
const missingKeys = new Set(params.files.map((file) => file.accountId).filter((key) => !existingKeys.has(key)));
|
|
@@ -134,7 +115,7 @@ const stateMigrations = [{
|
|
|
134
115
|
existingKeys.add(file.accountId);
|
|
135
116
|
imported++;
|
|
136
117
|
}
|
|
137
|
-
await
|
|
118
|
+
await archiveLegacyStateSource({
|
|
138
119
|
filePath: file.filePath,
|
|
139
120
|
label: "Nostr bus state",
|
|
140
121
|
changes,
|
|
@@ -189,7 +170,7 @@ const stateMigrations = [{
|
|
|
189
170
|
existingKeys.add(file.accountId);
|
|
190
171
|
imported++;
|
|
191
172
|
}
|
|
192
|
-
await
|
|
173
|
+
await archiveLegacyStateSource({
|
|
193
174
|
filePath: file.filePath,
|
|
194
175
|
label: "Nostr profile state",
|
|
195
176
|
changes,
|
package/dist/setup-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as nostrSetupWizard, t as nostrSetupAdapter } from "./setup-surface-
|
|
1
|
+
import { n as nostrSetupWizard, t as nostrSetupAdapter } from "./setup-surface-CKamwGa3.js";
|
|
2
2
|
export { nostrSetupAdapter, nostrSetupWizard };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -51,7 +51,7 @@ const nostrSetupAdapter = createNostrSetupAdapter({
|
|
|
51
51
|
});
|
|
52
52
|
const nostrSetupWizard = createDelegatedSetupWizardProxy({
|
|
53
53
|
channel,
|
|
54
|
-
loadWizard: async () => (await import("./setup-surface-
|
|
54
|
+
loadWizard: async () => (await import("./setup-surface-CKamwGa3.js").then((n) => n.r)).nostrSetupWizard,
|
|
55
55
|
status: { ...createStandardChannelSetupStatus({
|
|
56
56
|
channelLabel: "Nostr",
|
|
57
57
|
configuredLabel: t("wizard.channels.statusConfigured"),
|
|
@@ -30,7 +30,7 @@ function validatePrivateKey(key) {
|
|
|
30
30
|
return decoded.data;
|
|
31
31
|
}
|
|
32
32
|
if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) throw new Error("Private key must be 64 hex characters or nsec bech32 format");
|
|
33
|
-
const bytes = new Uint8Array(32);
|
|
33
|
+
const bytes = /* @__PURE__ */ new Uint8Array(32);
|
|
34
34
|
for (let i = 0; i < 32; i++) bytes[i] = Number.parseInt(trimmed.slice(i * 2, i * 2 + 2), 16);
|
|
35
35
|
return bytes;
|
|
36
36
|
}
|
|
@@ -130,34 +130,56 @@ import WebSocket from 'ws'
|
|
|
130
130
|
useWebSocketImplementation(WebSocket)
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
### Authenticating with relays (NIP-42)
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
Some relays will return a `CLOSED` message with an `"auth-required:"` prefix in order to signal that such request requires authentication.
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
import { SimplePool } from '@nostr/tools/pool'
|
|
139
|
-
|
|
140
|
-
const pool = new SimplePool({ enablePing: true })
|
|
141
|
-
```
|
|
137
|
+
Upon receiving that you're supposed to send an `AUTH` message and restart the subscription.
|
|
142
138
|
|
|
143
|
-
|
|
139
|
+
**Using `SimplePool`:**
|
|
144
140
|
|
|
145
|
-
|
|
141
|
+
`subscribeMany`, `subscribeManyEose` and `subscribeEose` accept `onauth` option. It signs challenge and resubscribes automatically for you:
|
|
146
142
|
|
|
147
143
|
```js
|
|
148
144
|
import { SimplePool } from '@nostr/tools/pool'
|
|
149
145
|
|
|
150
|
-
const pool = new SimplePool(
|
|
146
|
+
const pool = new SimplePool()
|
|
147
|
+
|
|
148
|
+
pool.subscribeMany(
|
|
149
|
+
['wss://myrelay.com'],
|
|
150
|
+
[{ '#t': ['restricted'] }],
|
|
151
|
+
{
|
|
152
|
+
onevent(event) { console.log('got event:', event) },
|
|
153
|
+
onauth: (eventTemplate) => window.nostr.signEvent(eventTemplate),
|
|
154
|
+
}
|
|
155
|
+
)
|
|
151
156
|
```
|
|
152
157
|
|
|
153
|
-
Using
|
|
158
|
+
**Using `Relay` directly:**
|
|
159
|
+
|
|
160
|
+
Unrecommended unless you really need fine-grained control over each `Relay` object:
|
|
154
161
|
|
|
155
162
|
```js
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
import { Relay } from '@nostr/tools/relay'
|
|
164
|
+
|
|
165
|
+
const relay = await Relay.connect('wss://myrelay.com')
|
|
166
|
+
let alreadyAuthenticatedOnce = false
|
|
167
|
+
const subscribe = () => {
|
|
168
|
+
relay.subscribe([{ '#t': ['restricted'] }], {
|
|
169
|
+
onevent(event) { console.log(event) },
|
|
170
|
+
onclose(reason) {
|
|
171
|
+
if (reason.startsWith('auth-required:')) {
|
|
172
|
+
if (alreadyAuthenticatedOnce) return
|
|
173
|
+
await relay.auth((eventTemplate) = window.nostr.signEvent(eventTemplate))
|
|
174
|
+
alreadyAuthenticatedOnce = true
|
|
175
|
+
subscribe()
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
}
|
|
159
180
|
|
|
160
|
-
|
|
181
|
+
subscribe()
|
|
182
|
+
```
|
|
161
183
|
|
|
162
184
|
### Parsing references (mentions) from a content based on NIP-27
|
|
163
185
|
|
|
@@ -227,7 +227,9 @@ var AbstractRelay = class {
|
|
|
227
227
|
connectionTimeoutHandle = setTimeout(() => {
|
|
228
228
|
reject("connection timed out");
|
|
229
229
|
this.connectionPromise = void 0;
|
|
230
|
-
this.
|
|
230
|
+
if (this.reconnectAttempts === 0) {
|
|
231
|
+
this.skipReconnection = true;
|
|
232
|
+
}
|
|
231
233
|
this.onclose?.();
|
|
232
234
|
this.handleHardClose("relay connection timed out");
|
|
233
235
|
}, opts.timeout);
|
|
@@ -271,7 +273,9 @@ var AbstractRelay = class {
|
|
|
271
273
|
clearTimeout(connectionTimeoutHandle);
|
|
272
274
|
reject("connection failed");
|
|
273
275
|
this.connectionPromise = void 0;
|
|
274
|
-
this.
|
|
276
|
+
if (this.reconnectAttempts === 0) {
|
|
277
|
+
this.skipReconnection = true;
|
|
278
|
+
}
|
|
275
279
|
this.onclose?.();
|
|
276
280
|
this.handleHardClose("relay connection failed");
|
|
277
281
|
};
|
|
@@ -372,19 +376,38 @@ var AbstractRelay = class {
|
|
|
372
376
|
}, this.publishTimeout);
|
|
373
377
|
this.openEventPublishes.set(event.id, { resolve, reject, timeout });
|
|
374
378
|
});
|
|
375
|
-
|
|
379
|
+
try {
|
|
380
|
+
await this.send('["EVENT",' + JSON.stringify(event) + "]");
|
|
381
|
+
} catch (err) {
|
|
382
|
+
const ep = this.openEventPublishes.get(event.id);
|
|
383
|
+
if (ep) {
|
|
384
|
+
ep.reject(err);
|
|
385
|
+
this.openEventPublishes.delete(event.id);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
376
388
|
this.ongoingOperations--;
|
|
377
389
|
if (this.ongoingOperations === 0)
|
|
378
390
|
this.idleSince = Date.now();
|
|
379
391
|
return ret;
|
|
380
392
|
}
|
|
381
393
|
async count(filters, params) {
|
|
394
|
+
return (await this.countWithHLL(filters, params)).count;
|
|
395
|
+
}
|
|
396
|
+
async countWithHLL(filters, params) {
|
|
382
397
|
this.serial++;
|
|
383
398
|
const id = params?.id || "count:" + this.serial;
|
|
384
399
|
const ret = new Promise((resolve, reject) => {
|
|
385
400
|
this.openCountRequests.set(id, { resolve, reject });
|
|
386
401
|
});
|
|
387
|
-
|
|
402
|
+
try {
|
|
403
|
+
await this.send('["COUNT","' + id + '",' + JSON.stringify(filters).substring(1));
|
|
404
|
+
} catch (err) {
|
|
405
|
+
const cr = this.openCountRequests.get(id);
|
|
406
|
+
if (cr) {
|
|
407
|
+
cr.reject(err);
|
|
408
|
+
this.openCountRequests.delete(id);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
388
411
|
return ret;
|
|
389
412
|
}
|
|
390
413
|
subscribe(filters, params) {
|
|
@@ -462,7 +485,7 @@ var AbstractRelay = class {
|
|
|
462
485
|
const payload = data[2];
|
|
463
486
|
const cr = this.openCountRequests.get(id);
|
|
464
487
|
if (cr) {
|
|
465
|
-
cr.resolve(payload
|
|
488
|
+
cr.resolve(payload);
|
|
466
489
|
this.openCountRequests.delete(id);
|
|
467
490
|
}
|
|
468
491
|
return;
|
|
@@ -492,8 +515,14 @@ var AbstractRelay = class {
|
|
|
492
515
|
case "CLOSED": {
|
|
493
516
|
const id = data[1];
|
|
494
517
|
const so = this.openSubs.get(id);
|
|
495
|
-
if (!so)
|
|
518
|
+
if (!so) {
|
|
519
|
+
const cr = this.openCountRequests.get(id);
|
|
520
|
+
if (cr) {
|
|
521
|
+
cr.reject(new Error(data[2]));
|
|
522
|
+
this.openCountRequests.delete(id);
|
|
523
|
+
}
|
|
496
524
|
return;
|
|
525
|
+
}
|
|
497
526
|
so.closed = true;
|
|
498
527
|
so.close(data[2]);
|
|
499
528
|
return;
|
|
@@ -602,6 +631,63 @@ var alwaysTrue = (t) => {
|
|
|
602
631
|
return true;
|
|
603
632
|
};
|
|
604
633
|
|
|
634
|
+
// nip45.ts
|
|
635
|
+
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
636
|
+
var import_utils3 = require("@noble/hashes/utils.js");
|
|
637
|
+
var M = 256;
|
|
638
|
+
var HLL_HEX_LENGTH = M * 2;
|
|
639
|
+
var utf8Encoder2 = new TextEncoder();
|
|
640
|
+
function getCountManyFilter(target, directive) {
|
|
641
|
+
switch (directive) {
|
|
642
|
+
case "reactions":
|
|
643
|
+
return { "#e": [target], kinds: [7] };
|
|
644
|
+
case "reposts":
|
|
645
|
+
return { "#e": [target], kinds: [6] };
|
|
646
|
+
case "quotes":
|
|
647
|
+
return { "#q": [target], kinds: [1, 1111] };
|
|
648
|
+
case "replies":
|
|
649
|
+
return { "#e": [target], kinds: [1] };
|
|
650
|
+
case "comments":
|
|
651
|
+
return { "#E": [target], kinds: [1111] };
|
|
652
|
+
case "followers":
|
|
653
|
+
return { "#p": [target], kinds: [3] };
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
function newHll() {
|
|
657
|
+
return new Uint8Array(M);
|
|
658
|
+
}
|
|
659
|
+
function hllDecode(hex) {
|
|
660
|
+
if (hex.length !== HLL_HEX_LENGTH || !/^[0-9a-fA-F]+$/.test(hex))
|
|
661
|
+
return void 0;
|
|
662
|
+
const registers = new Uint8Array(M);
|
|
663
|
+
for (let i = 0; i < M; i++) {
|
|
664
|
+
registers[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
665
|
+
}
|
|
666
|
+
return registers;
|
|
667
|
+
}
|
|
668
|
+
function hllEncode(registers) {
|
|
669
|
+
if (registers.length !== M)
|
|
670
|
+
throw new Error(`invalid number of registers ${registers.length}`);
|
|
671
|
+
let hex = "";
|
|
672
|
+
for (let i = 0; i < M; i++) {
|
|
673
|
+
hex += registers[i].toString(16).padStart(2, "0");
|
|
674
|
+
}
|
|
675
|
+
return hex;
|
|
676
|
+
}
|
|
677
|
+
function mergeHll(target, source) {
|
|
678
|
+
if (target.length === 0)
|
|
679
|
+
target = newHll();
|
|
680
|
+
if (target.length !== M)
|
|
681
|
+
throw new Error(`invalid number of registers ${target.length}`);
|
|
682
|
+
if (source.length !== M)
|
|
683
|
+
throw new Error(`invalid number of registers ${source.length}`);
|
|
684
|
+
for (let i = 0; i < M; i++) {
|
|
685
|
+
if (source[i] > target[i])
|
|
686
|
+
target[i] = source[i];
|
|
687
|
+
}
|
|
688
|
+
return target;
|
|
689
|
+
}
|
|
690
|
+
|
|
605
691
|
// abstract-pool.ts
|
|
606
692
|
var AbstractSimplePool = class {
|
|
607
693
|
relays = /* @__PURE__ */ new Map();
|
|
@@ -829,6 +915,48 @@ var AbstractSimplePool = class {
|
|
|
829
915
|
events.sort((a, b) => b.created_at - a.created_at);
|
|
830
916
|
return events[0] || null;
|
|
831
917
|
}
|
|
918
|
+
async countMany(relays, target, directive, params) {
|
|
919
|
+
const filter = getCountManyFilter(target, directive);
|
|
920
|
+
const urls = [];
|
|
921
|
+
for (let i = 0; i < relays.length; i++) {
|
|
922
|
+
const url = normalizeURL(relays[i]);
|
|
923
|
+
if (urls.indexOf(url) === -1)
|
|
924
|
+
urls.push(url);
|
|
925
|
+
}
|
|
926
|
+
const responses = await Promise.all(
|
|
927
|
+
urls.map(async (url) => {
|
|
928
|
+
if (this.allowConnectingToRelay?.(url, ["read", [filter]]) === false)
|
|
929
|
+
return null;
|
|
930
|
+
let relay;
|
|
931
|
+
try {
|
|
932
|
+
relay = await this.ensureRelay(url, {
|
|
933
|
+
connectionTimeout: this.maxWaitForConnection < (params?.maxWait || 0) ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : this.maxWaitForConnection,
|
|
934
|
+
abort: params?.abort
|
|
935
|
+
});
|
|
936
|
+
} catch (err) {
|
|
937
|
+
this.onRelayConnectionFailure?.(url);
|
|
938
|
+
return null;
|
|
939
|
+
}
|
|
940
|
+
this.onRelayConnectionSuccess?.(url);
|
|
941
|
+
return relay.countWithHLL([filter], { id: params?.id }).catch(() => null);
|
|
942
|
+
})
|
|
943
|
+
);
|
|
944
|
+
let count = 0;
|
|
945
|
+
let hll;
|
|
946
|
+
for (const response of responses) {
|
|
947
|
+
if (!response)
|
|
948
|
+
continue;
|
|
949
|
+
if (response.count > count)
|
|
950
|
+
count = response.count;
|
|
951
|
+
if (!response.hll || response.hll.length !== 512)
|
|
952
|
+
continue;
|
|
953
|
+
const registers = hllDecode(response.hll);
|
|
954
|
+
if (!registers)
|
|
955
|
+
continue;
|
|
956
|
+
hll = mergeHll(hll || new Uint8Array(0), registers);
|
|
957
|
+
}
|
|
958
|
+
return hll ? { count, hll: hllEncode(hll) } : { count };
|
|
959
|
+
}
|
|
832
960
|
publish(relays, event, params) {
|
|
833
961
|
return relays.map(normalizeURL).map(async (url, i, arr) => {
|
|
834
962
|
if (arr.indexOf(url) !== i) {
|