@openclaw/nostr 2026.8.1-beta.3 → 2026.8.2
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 +7 -5
- package/dist/{channel-ity6au4a.js → channel-CLybVB2-.js} +11 -12
- package/dist/channel-plugin-api.js +1 -1
- package/dist/doctor-contract-api.js +2 -1
- package/dist/{setup-adapter-ClKW2fkz.js → setup-adapter-KJ_iGKiG.js} +30 -2
- package/dist/setup-api.js +1 -1
- package/dist/setup-plugin-api.js +3 -6
- package/dist/{setup-surface-uA4hN27A.js → setup-surface-mA5PMspO.js} +17 -46
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js +7 -5
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js +6 -4
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/core.js +10 -6
- package/node_modules/nostr-tools/lib/cjs/core.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/index.js +37 -15
- package/node_modules/nostr-tools/lib/cjs/index.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/kinds.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/kinds.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip04.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip10.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip10.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip13.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip17.js +21 -3
- package/node_modules/nostr-tools/lib/cjs/nip17.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip18.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip18.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip19.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip21.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip22.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip22.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip25.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip25.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip27.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip28.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip28.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip29.js +288 -12
- package/node_modules/nostr-tools/lib/cjs/nip29.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip44.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip45.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip45.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip46.js +16 -8
- package/node_modules/nostr-tools/lib/cjs/nip46.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip47.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip47.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip57.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip57.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip59.js +21 -3
- package/node_modules/nostr-tools/lib/cjs/nip59.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip98.js +3 -1
- package/node_modules/nostr-tools/lib/cjs/nip98.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nipad.js +55 -0
- package/node_modules/nostr-tools/lib/cjs/nipad.js.map +7 -0
- package/node_modules/nostr-tools/lib/cjs/nipb0.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nipb0.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nipb7.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nipb7.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/pool.js +9 -5
- package/node_modules/nostr-tools/lib/cjs/pool.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/pure.js +10 -6
- package/node_modules/nostr-tools/lib/cjs/pure.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/references.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/relay.js +8 -4
- package/node_modules/nostr-tools/lib/cjs/relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/signer.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/signer.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/utils.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/utils.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/wasm.js +10 -6
- package/node_modules/nostr-tools/lib/cjs/wasm.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js +7 -5
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js +6 -4
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/core.js +10 -6
- package/node_modules/nostr-tools/lib/esm/core.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/index.js +37 -15
- package/node_modules/nostr-tools/lib/esm/index.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/kinds.js +2 -0
- package/node_modules/nostr-tools/lib/esm/kinds.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip04.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip10.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip10.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip13.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip17.js +21 -3
- package/node_modules/nostr-tools/lib/esm/nip17.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip18.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip18.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip19.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip21.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip22.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip22.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip25.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip25.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip27.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip28.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip28.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip29.js +288 -12
- package/node_modules/nostr-tools/lib/esm/nip29.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip44.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip45.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip45.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip46.js +16 -8
- package/node_modules/nostr-tools/lib/esm/nip46.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip47.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip47.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip57.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip57.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip59.js +21 -3
- package/node_modules/nostr-tools/lib/esm/nip59.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip98.js +3 -1
- package/node_modules/nostr-tools/lib/esm/nip98.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nipad.js +34 -0
- package/node_modules/nostr-tools/lib/esm/nipad.js.map +7 -0
- package/node_modules/nostr-tools/lib/esm/nipb0.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nipb0.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nipb7.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nipb7.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/pool.js +9 -5
- package/node_modules/nostr-tools/lib/esm/pool.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/pure.js +10 -6
- package/node_modules/nostr-tools/lib/esm/pure.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/references.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/relay.js +8 -4
- package/node_modules/nostr-tools/lib/esm/relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/signer.js +2 -0
- package/node_modules/nostr-tools/lib/esm/signer.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/utils.js +2 -0
- package/node_modules/nostr-tools/lib/esm/utils.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/wasm.js +10 -6
- package/node_modules/nostr-tools/lib/esm/wasm.js.map +2 -2
- package/node_modules/nostr-tools/lib/nostr.bundle.js +37 -15
- package/node_modules/nostr-tools/lib/nostr.bundle.js.map +2 -2
- package/node_modules/nostr-tools/lib/types/core.d.ts +5 -0
- package/node_modules/nostr-tools/lib/types/nip29.d.ts +243 -3
- package/node_modules/nostr-tools/lib/types/nip29.test.d.ts +1 -0
- package/node_modules/nostr-tools/lib/types/nip46.test.d.ts +1 -0
- package/node_modules/nostr-tools/lib/types/nip98.d.ts +1 -1
- package/node_modules/nostr-tools/lib/types/nipad.d.ts +16 -0
- package/node_modules/nostr-tools/package.json +7 -1
- package/package.json +5 -5
package/dist/api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { s as resolveNostrAccount } from "./setup-surface-
|
|
1
|
+
import { s as resolveNostrAccount } from "./setup-surface-mA5PMspO.js";
|
|
2
2
|
import { getPluginRuntimeGatewayRequestScope } from "./runtime-api.js";
|
|
3
3
|
import { n as NostrProfileSchema } from "./config-schema-CkYd8ACn.js";
|
|
4
|
-
import { a as getNostrRuntime, i as contentToProfile, n as nostrPlugin, o as setNostrRuntime, r as publishNostrProfile, t as getNostrProfileState } from "./channel-
|
|
4
|
+
import { a as getNostrRuntime, i as contentToProfile, n as nostrPlugin, o as setNostrRuntime, r as publishNostrProfile, t as getNostrProfileState } from "./channel-CLybVB2-.js";
|
|
5
5
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { SimplePool } from "nostr-tools";
|
|
@@ -18,7 +18,8 @@ function validateUrlSafety(urlStr) {
|
|
|
18
18
|
ok: false,
|
|
19
19
|
error: "URL must use https:// protocol"
|
|
20
20
|
};
|
|
21
|
-
|
|
21
|
+
const hostname = url.hostname.trim().toLowerCase();
|
|
22
|
+
if (isBlockedHostnameOrIp(hostname)) return {
|
|
22
23
|
ok: false,
|
|
23
24
|
error: "URL must not point to private/internal addresses"
|
|
24
25
|
};
|
|
@@ -208,7 +209,7 @@ function sendJson(res, status, body) {
|
|
|
208
209
|
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
209
210
|
res.end(JSON.stringify(body));
|
|
210
211
|
}
|
|
211
|
-
async function readJsonBody(req, maxBytes =
|
|
212
|
+
async function readJsonBody(req, maxBytes = 65536, timeoutMs = 3e4) {
|
|
212
213
|
const result = await readJsonBodyWithLimit(req, {
|
|
213
214
|
maxBytes,
|
|
214
215
|
timeoutMs,
|
|
@@ -234,7 +235,8 @@ function isLoopbackRemoteAddress(remoteAddress) {
|
|
|
234
235
|
}
|
|
235
236
|
function isLoopbackOriginLike(value) {
|
|
236
237
|
try {
|
|
237
|
-
|
|
238
|
+
const url = new URL(value);
|
|
239
|
+
return isLoopbackHost(url.hostname);
|
|
238
240
|
} catch {
|
|
239
241
|
return false;
|
|
240
242
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as listNostrAccountIds, c as normalizePubkey,
|
|
1
|
+
import { a as listNostrAccountIds, c as normalizePubkey, n as nostrSetupContract, o as resolveDefaultNostrAccountId, r as nostrSetupWizard, s as resolveNostrAccount } from "./setup-surface-mA5PMspO.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-CkYd8ACn.js";
|
|
3
|
-
import { c as DEFAULT_RELAYS } from "./setup-adapter-
|
|
3
|
+
import { c as validatePrivateKey, l as DEFAULT_RELAYS } from "./setup-adapter-KJ_iGKiG.js";
|
|
4
4
|
import { t as normalizeNostrStateAccountId } from "./state-account-id-CvBZ9s6P.js";
|
|
5
5
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
6
6
|
import { createScopedDmSecurityResolver, createTopLevelChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
@@ -213,9 +213,7 @@ function createMetrics(onMetric) {
|
|
|
213
213
|
case "memory.seen_tracker_size":
|
|
214
214
|
state.memory.seenTrackerSize = value;
|
|
215
215
|
break;
|
|
216
|
-
case "memory.rate_limiter_entries":
|
|
217
|
-
state.memory.rateLimiterEntries = value;
|
|
218
|
-
break;
|
|
216
|
+
case "memory.rate_limiter_entries": state.memory.rateLimiterEntries = value;
|
|
219
217
|
}
|
|
220
218
|
}
|
|
221
219
|
function getSnapshot() {
|
|
@@ -365,9 +363,7 @@ function createNostrCursorStateWriter(options) {
|
|
|
365
363
|
return;
|
|
366
364
|
} catch (error) {
|
|
367
365
|
options.onBackgroundError?.(error);
|
|
368
|
-
await
|
|
369
|
-
setTimeout(resolve, options.recoveryRetryMs ?? CURSOR_RECOVERY_RETRY_MS);
|
|
370
|
-
});
|
|
366
|
+
await sleepWithAbort(CURSOR_RECOVERY_RETRY_MS);
|
|
371
367
|
}
|
|
372
368
|
})().finally(() => {
|
|
373
369
|
recoveryFlush = void 0;
|
|
@@ -679,11 +675,12 @@ function createProfileEvent(sk, profile, lastPublishedAt) {
|
|
|
679
675
|
const content = profileToContent(profile);
|
|
680
676
|
const contentJson = JSON.stringify(content);
|
|
681
677
|
const now = Math.floor(Date.now() / 1e3);
|
|
678
|
+
const createdAt = lastPublishedAt !== void 0 ? Math.max(now, lastPublishedAt + 1) : now;
|
|
682
679
|
return finalizeEvent({
|
|
683
680
|
kind: 0,
|
|
684
681
|
content: contentJson,
|
|
685
682
|
tags: [],
|
|
686
|
-
created_at:
|
|
683
|
+
created_at: createdAt
|
|
687
684
|
}, sk);
|
|
688
685
|
}
|
|
689
686
|
/** Per-relay publish timeout (ms) */
|
|
@@ -862,7 +859,7 @@ async function writeNostrProfileState(params) {
|
|
|
862
859
|
//#region extensions/nostr/src/nostr-bus.ts
|
|
863
860
|
const STARTUP_LOOKBACK_SEC = 120;
|
|
864
861
|
const STATE_PERSIST_DEBOUNCE_MS = 5e3;
|
|
865
|
-
const NOSTR_INGRESS_ENVELOPE_OVERHEAD_BYTES =
|
|
862
|
+
const NOSTR_INGRESS_ENVELOPE_OVERHEAD_BYTES = 16384;
|
|
866
863
|
const NOSTR_INGRESS_MAX_PENDING_EVENTS = 1e3;
|
|
867
864
|
const DEFAULT_INBOUND_GUARD_POLICY = createDirectDmPreCryptoGuardPolicy();
|
|
868
865
|
const CIRCUIT_BREAKER_THRESHOLD = 5;
|
|
@@ -1447,7 +1444,8 @@ const startNostrGatewayAccount = async (ctx) => {
|
|
|
1447
1444
|
commandAuthorized: resolvedAccess.commandAccess.requested ? resolvedAccess.commandAccess.authorized : void 0,
|
|
1448
1445
|
turnAdoptionLifecycle: bindIngressLifecycleToReplyOptions(lifecycle).turnAdoptionLifecycle,
|
|
1449
1446
|
deliver: async (payload) => {
|
|
1450
|
-
const
|
|
1447
|
+
const outboundText = payload && typeof payload === "object" && "text" in payload ? payload.text ?? "" : "";
|
|
1448
|
+
const sanitizedText = sanitizeAssistantVisibleText(outboundText);
|
|
1451
1449
|
if (!sanitizedText) return;
|
|
1452
1450
|
const tableMode = runtime.channel.text.resolveMarkdownTableMode({
|
|
1453
1451
|
cfg: ctx.cfg,
|
|
@@ -1542,9 +1540,10 @@ const nostrOutboundAdapter = {
|
|
|
1542
1540
|
const message = stripMarkdown(core.channel.text.convertMarkdownTables(text ?? "", tableMode));
|
|
1543
1541
|
if (!message) throw new Error("Nostr send requires non-empty text after markdown stripping.");
|
|
1544
1542
|
const normalizedTo = normalizePubkey(to);
|
|
1543
|
+
const eventId = await bus.sendDm(normalizedTo, message);
|
|
1545
1544
|
return attachChannelToResult("nostr", {
|
|
1546
1545
|
to: normalizedTo,
|
|
1547
|
-
messageId:
|
|
1546
|
+
messageId: eventId
|
|
1548
1547
|
});
|
|
1549
1548
|
}
|
|
1550
1549
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as nostrPlugin } from "./channel-
|
|
1
|
+
import { n as nostrPlugin } from "./channel-CLybVB2-.js";
|
|
2
2
|
export { nostrPlugin };
|
|
@@ -49,7 +49,8 @@ async function listLegacyFiles(params) {
|
|
|
49
49
|
const files = [];
|
|
50
50
|
for (const entry of entries) {
|
|
51
51
|
if (!entry.isFile() || !entry.name.startsWith(params.prefix) || !entry.name.endsWith(suffix)) continue;
|
|
52
|
-
const
|
|
52
|
+
const rawAccountId = entry.name.slice(params.prefix.length, -5);
|
|
53
|
+
const accountId = normalizeNostrStateAccountId(rawAccountId);
|
|
53
54
|
const filePath = path.join(dir, entry.name);
|
|
54
55
|
try {
|
|
55
56
|
const value = params.parse(await readJsonFile(filePath));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
2
|
import { hasConfiguredSecretInput, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
3
|
+
import { decode } from "nostr-tools/nip19";
|
|
3
4
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
|
|
4
5
|
import { createSetupTranslator, createStandardChannelSetupStatus, patchTopLevelChannelConfigSection, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
5
6
|
import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
|
|
@@ -8,6 +9,29 @@ const DEFAULT_RELAYS = ["wss://relay.damus.io", "wss://nos.lol"];
|
|
|
8
9
|
//#endregion
|
|
9
10
|
//#region extensions/nostr/src/private-key.ts
|
|
10
11
|
const NOSTR_PRIVATE_KEY_ENV_VAR = "NOSTR_PRIVATE_KEY";
|
|
12
|
+
const SECP256K1_ORDER = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
|
13
|
+
/** Validate and normalize a private key (hex or NIP-19 nsec). */
|
|
14
|
+
function validatePrivateKey(key) {
|
|
15
|
+
const trimmed = key.trim();
|
|
16
|
+
let bytes;
|
|
17
|
+
if (trimmed.startsWith("nsec1") || trimmed.startsWith("NSEC1")) {
|
|
18
|
+
let decoded;
|
|
19
|
+
try {
|
|
20
|
+
decoded = decode(trimmed);
|
|
21
|
+
} catch {
|
|
22
|
+
throw new Error("Invalid nsec private key");
|
|
23
|
+
}
|
|
24
|
+
if (decoded.type !== "nsec") throw new Error("Invalid nsec key type");
|
|
25
|
+
bytes = decoded.data;
|
|
26
|
+
} else {
|
|
27
|
+
if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) throw new Error("Private key must be 64 hex characters or nsec bech32 format");
|
|
28
|
+
bytes = Uint8Array.from({ length: 32 }, (_, index) => Number.parseInt(trimmed.slice(index * 2, index * 2 + 2), 16));
|
|
29
|
+
}
|
|
30
|
+
if (bytes.length !== 32) throw new Error("Private key must decode to 32 bytes");
|
|
31
|
+
const scalar = Array.from(bytes).reduce((value, byte) => value << 8n | BigInt(byte), 0n);
|
|
32
|
+
if (scalar === 0n || scalar >= SECP256K1_ORDER) throw new Error("Private key scalar is out of range");
|
|
33
|
+
return bytes;
|
|
34
|
+
}
|
|
11
35
|
function hasConfiguredNostrPrivateKey(value) {
|
|
12
36
|
return hasConfiguredSecretInput(value) || Boolean(process.env["NOSTR_PRIVATE_KEY"]?.trim());
|
|
13
37
|
}
|
|
@@ -56,7 +80,11 @@ function createNostrSetupAdapter(params) {
|
|
|
56
80
|
if (!input.useEnv) {
|
|
57
81
|
const privateKey = input.privateKey?.trim();
|
|
58
82
|
if (!privateKey) return "Nostr requires --private-key or --use-env.";
|
|
59
|
-
|
|
83
|
+
try {
|
|
84
|
+
validatePrivateKey(privateKey);
|
|
85
|
+
} catch {
|
|
86
|
+
return "Nostr private key must be valid nsec or 64-character hex.";
|
|
87
|
+
}
|
|
60
88
|
}
|
|
61
89
|
if (input.relayUrls?.trim()) return parseRelayUrls(input.relayUrls).error ?? null;
|
|
62
90
|
return null;
|
|
@@ -127,4 +155,4 @@ function createNostrSetupStatus(resolveAccount) {
|
|
|
127
155
|
});
|
|
128
156
|
}
|
|
129
157
|
//#endregion
|
|
130
|
-
export { parseRelayUrls as a,
|
|
158
|
+
export { parseRelayUrls as a, validatePrivateKey as c, createNostrSetupStatus as i, DEFAULT_RELAYS as l, createNostrSetupAdapter as n, hasConfiguredNostrPrivateKey as o, createNostrSetupContract as r, resolveNostrPrivateKey as s, buildNostrSetupPatch as t };
|
package/dist/setup-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { r as nostrSetupWizard, t as nostrSetupAdapter } from "./setup-surface-
|
|
1
|
+
import { r as nostrSetupWizard, t as nostrSetupAdapter } from "./setup-surface-mA5PMspO.js";
|
|
2
2
|
export { nostrSetupAdapter, nostrSetupWizard };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as buildChannelConfigSchema, t as NostrConfigSchema } from "./config-schema-CkYd8ACn.js";
|
|
2
|
-
import {
|
|
2
|
+
import { i as createNostrSetupStatus, l as DEFAULT_RELAYS, n as createNostrSetupAdapter, o as hasConfiguredNostrPrivateKey, r as createNostrSetupContract, s as resolveNostrPrivateKey } from "./setup-adapter-KJ_iGKiG.js";
|
|
3
3
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
4
4
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
5
5
|
import { createDelegatedSetupWizardProxy } from "openclaw/plugin-sdk/setup-runtime";
|
|
@@ -38,7 +38,7 @@ function resolveSetupNostrAccount(params) {
|
|
|
38
38
|
}
|
|
39
39
|
const nostrSetupWizard = createDelegatedSetupWizardProxy({
|
|
40
40
|
channel,
|
|
41
|
-
loadWizard: async () => (await import("./setup-surface-
|
|
41
|
+
loadWizard: async () => (await import("./setup-surface-mA5PMspO.js").then((n) => n.i)).nostrSetupWizard,
|
|
42
42
|
status: createNostrSetupStatus(resolveSetupNostrAccount),
|
|
43
43
|
resolveShouldPromptAccountIds: () => false,
|
|
44
44
|
delegatePrepare: true,
|
|
@@ -61,10 +61,7 @@ const nostrSetupPlugin = {
|
|
|
61
61
|
},
|
|
62
62
|
reload: { configPrefixes: ["channels.nostr"] },
|
|
63
63
|
configSchema: buildChannelConfigSchema(NostrConfigSchema),
|
|
64
|
-
setupContract: createNostrSetupContract(createNostrSetupAdapter({
|
|
65
|
-
resolveAccountId: (cfg, accountId) => accountId?.trim() || resolveDefaultSetupNostrAccountId(cfg),
|
|
66
|
-
validatePrivateKey: (privateKey) => /^(?:nsec1|NSEC1)|^[0-9a-fA-F]{64}$/u.test(privateKey)
|
|
67
|
-
})),
|
|
64
|
+
setupContract: createNostrSetupContract(createNostrSetupAdapter({ resolveAccountId: (cfg, accountId) => accountId?.trim() || resolveDefaultSetupNostrAccountId(cfg) })),
|
|
68
65
|
setupWizard: nostrSetupWizard,
|
|
69
66
|
config: {
|
|
70
67
|
listAccountIds: (cfg) => resolveSetupNostrAccount({ cfg }).configured ? [resolveDefaultSetupNostrAccountId(cfg)] : [],
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as parseRelayUrls, c as
|
|
1
|
+
import { a as parseRelayUrls, c as validatePrivateKey, i as createNostrSetupStatus, l as DEFAULT_RELAYS, n as createNostrSetupAdapter, o as hasConfiguredNostrPrivateKey, r as createNostrSetupContract, s as resolveNostrPrivateKey, t as buildNostrSetupPatch } from "./setup-adapter-KJ_iGKiG.js";
|
|
2
2
|
import { createAccountListHelpers } from "openclaw/plugin-sdk/account-helpers";
|
|
3
3
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { hasConfiguredSecretInput, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
5
|
-
import {
|
|
5
|
+
import { decode } from "nostr-tools/nip19";
|
|
6
|
+
import { getPublicKey } from "nostr-tools/pure";
|
|
6
7
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId, normalizeOptionalAccountId } from "openclaw/plugin-sdk/account-id";
|
|
7
8
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/routing";
|
|
8
9
|
import { createSetupTranslator, createTopLevelChannelDmPolicy, createTopLevelChannelParsedAllowFromPrompt, defineTokenCredential, formatDocsLink, mergeAllowFromEntries, parseSetupEntriesWithParser, patchTopLevelChannelConfigSection, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
|
@@ -19,34 +20,13 @@ var __exportAll = (all, no_symbols) => {
|
|
|
19
20
|
};
|
|
20
21
|
//#endregion
|
|
21
22
|
//#region extensions/nostr/src/nostr-key-utils.ts
|
|
22
|
-
/**
|
|
23
|
-
* Validate and normalize a private key (accepts hex or nsec format)
|
|
24
|
-
*/
|
|
25
|
-
function validatePrivateKey(key) {
|
|
26
|
-
const trimmed = key.trim();
|
|
27
|
-
if (trimmed.startsWith("nsec1") || trimmed.startsWith("NSEC1")) {
|
|
28
|
-
const decoded = nip19.decode(trimmed);
|
|
29
|
-
if (decoded.type !== "nsec") throw new Error("Invalid nsec key: wrong type");
|
|
30
|
-
return decoded.data;
|
|
31
|
-
}
|
|
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 = /* @__PURE__ */ new Uint8Array(32);
|
|
34
|
-
for (let i = 0; i < 32; i++) bytes[i] = Number.parseInt(trimmed.slice(i * 2, i * 2 + 2), 16);
|
|
35
|
-
return bytes;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Get public key from private key (hex or nsec format)
|
|
39
|
-
*/
|
|
40
23
|
function getPublicKeyFromPrivate(privateKey) {
|
|
41
24
|
return getPublicKey(validatePrivateKey(privateKey));
|
|
42
25
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Normalize a pubkey to hex format (accepts npub or hex)
|
|
45
|
-
*/
|
|
46
26
|
function normalizePubkey(input) {
|
|
47
27
|
const trimmed = input.trim();
|
|
48
28
|
if (trimmed.startsWith("npub1") || trimmed.startsWith("NPUB1")) {
|
|
49
|
-
const decoded =
|
|
29
|
+
const decoded = decode(trimmed);
|
|
50
30
|
if (decoded.type !== "npub" || typeof decoded.data !== "string") throw new Error("Invalid npub key");
|
|
51
31
|
return decoded.data.toLowerCase();
|
|
52
32
|
}
|
|
@@ -129,34 +109,25 @@ function parseNostrAllowFrom(raw) {
|
|
|
129
109
|
}
|
|
130
110
|
});
|
|
131
111
|
}
|
|
112
|
+
const promptNostrAllowFrom = createTopLevelChannelParsedAllowFromPrompt({
|
|
113
|
+
channel,
|
|
114
|
+
defaultAccountId: resolveDefaultNostrAccountId,
|
|
115
|
+
noteTitle: t("wizard.nostr.allowlistTitle"),
|
|
116
|
+
noteLines: NOSTR_ALLOW_FROM_HELP_LINES,
|
|
117
|
+
message: t("wizard.nostr.allowFromPrompt"),
|
|
118
|
+
placeholder: "npub1..., 0123abcd...",
|
|
119
|
+
parseEntries: parseNostrAllowFrom,
|
|
120
|
+
mergeEntries: ({ existing, parsed }) => mergeAllowFromEntries(existing, parsed)
|
|
121
|
+
});
|
|
132
122
|
const nostrDmPolicy = createTopLevelChannelDmPolicy({
|
|
133
123
|
label: "Nostr",
|
|
134
124
|
channel,
|
|
135
125
|
policyKey: "channels.nostr.dmPolicy",
|
|
136
126
|
allowFromKey: "channels.nostr.allowFrom",
|
|
137
127
|
getCurrent: (cfg) => cfg.channels?.nostr?.dmPolicy ?? "pairing",
|
|
138
|
-
promptAllowFrom:
|
|
139
|
-
channel,
|
|
140
|
-
defaultAccountId: resolveDefaultNostrAccountId,
|
|
141
|
-
noteTitle: t("wizard.nostr.allowlistTitle"),
|
|
142
|
-
noteLines: NOSTR_ALLOW_FROM_HELP_LINES,
|
|
143
|
-
message: t("wizard.nostr.allowFromPrompt"),
|
|
144
|
-
placeholder: "npub1..., 0123abcd...",
|
|
145
|
-
parseEntries: parseNostrAllowFrom,
|
|
146
|
-
mergeEntries: ({ existing, parsed }) => mergeAllowFromEntries(existing, parsed)
|
|
147
|
-
})
|
|
148
|
-
});
|
|
149
|
-
const nostrSetupAdapter = createNostrSetupAdapter({
|
|
150
|
-
resolveAccountId: (cfg, accountId) => accountId?.trim() || resolveDefaultNostrAccountId(cfg),
|
|
151
|
-
validatePrivateKey: (privateKey) => {
|
|
152
|
-
try {
|
|
153
|
-
getPublicKeyFromPrivate(privateKey);
|
|
154
|
-
return true;
|
|
155
|
-
} catch {
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
128
|
+
promptAllowFrom: promptNostrAllowFrom
|
|
159
129
|
});
|
|
130
|
+
const nostrSetupAdapter = createNostrSetupAdapter({ resolveAccountId: (cfg, accountId) => accountId?.trim() || resolveDefaultNostrAccountId(cfg) });
|
|
160
131
|
const nostrSetupContract = createNostrSetupContract(nostrSetupAdapter);
|
|
161
132
|
const nostrSetupWizard = {
|
|
162
133
|
channel,
|
|
@@ -244,4 +215,4 @@ const nostrSetupWizard = {
|
|
|
244
215
|
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false)
|
|
245
216
|
};
|
|
246
217
|
//#endregion
|
|
247
|
-
export { listNostrAccountIds as a, normalizePubkey as c, setup_surface_exports as i,
|
|
218
|
+
export { listNostrAccountIds as a, normalizePubkey as c, setup_surface_exports as i, nostrSetupContract as n, resolveDefaultNostrAccountId as o, nostrSetupWizard as r, resolveNostrAccount as s, nostrSetupAdapter as t };
|
|
@@ -650,10 +650,12 @@ var Subscription = class {
|
|
|
650
650
|
this.closed = true;
|
|
651
651
|
}
|
|
652
652
|
this.relay.openSubs.delete(this.id);
|
|
653
|
-
this.
|
|
654
|
-
|
|
655
|
-
this.relay.
|
|
656
|
-
|
|
653
|
+
if (!this.id.startsWith("<forced-ping>")) {
|
|
654
|
+
this.relay.ongoingOperations--;
|
|
655
|
+
if (this.relay.ongoingOperations === 0) {
|
|
656
|
+
this.relay.idleSince = Date.now();
|
|
657
|
+
this.relay.scheduleIdleClose();
|
|
658
|
+
}
|
|
657
659
|
}
|
|
658
660
|
this.onclose?.(reason);
|
|
659
661
|
}
|
|
@@ -1004,7 +1006,7 @@ var AbstractSimplePool = class {
|
|
|
1004
1006
|
});
|
|
1005
1007
|
} catch (err) {
|
|
1006
1008
|
this.onRelayConnectionFailure?.(url);
|
|
1007
|
-
return
|
|
1009
|
+
return Promise.reject("connection failure: " + String(err));
|
|
1008
1010
|
}
|
|
1009
1011
|
return r.publish(event).catch(async (err) => {
|
|
1010
1012
|
if (err instanceof Error && err.message.startsWith("auth-required: ") && params?.onauth) {
|