@openclaw/nostr 2026.5.2 → 2026.5.3-beta.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.
Files changed (59) hide show
  1. package/dist/api.js +532 -0
  2. package/dist/channel-DfEqBtUh.js +1466 -0
  3. package/dist/channel-plugin-api.js +2 -0
  4. package/dist/config-schema-DIk4jlBg.js +64 -0
  5. package/dist/default-relays-DLwdWOTu.js +4 -0
  6. package/dist/inbound-direct-dm-runtime-22bZWcIW.js +2 -0
  7. package/dist/index.js +84 -0
  8. package/dist/runtime-api.js +2 -0
  9. package/dist/setup-api.js +2 -0
  10. package/dist/setup-entry.js +11 -0
  11. package/dist/setup-plugin-api.js +165 -0
  12. package/dist/setup-surface-DxAaUTyC.js +336 -0
  13. package/dist/test-api.js +2 -0
  14. package/package.json +15 -6
  15. package/api.ts +0 -10
  16. package/channel-plugin-api.ts +0 -1
  17. package/index.ts +0 -97
  18. package/runtime-api.ts +0 -6
  19. package/setup-api.ts +0 -1
  20. package/setup-entry.ts +0 -9
  21. package/setup-plugin-api.ts +0 -3
  22. package/src/channel-api.ts +0 -15
  23. package/src/channel.inbound.test.ts +0 -176
  24. package/src/channel.outbound.test.ts +0 -128
  25. package/src/channel.setup.ts +0 -231
  26. package/src/channel.test.ts +0 -519
  27. package/src/channel.ts +0 -207
  28. package/src/config-schema.ts +0 -98
  29. package/src/default-relays.ts +0 -1
  30. package/src/gateway.ts +0 -302
  31. package/src/inbound-direct-dm-runtime.ts +0 -1
  32. package/src/metrics.ts +0 -458
  33. package/src/nostr-bus.fuzz.test.ts +0 -360
  34. package/src/nostr-bus.inbound.test.ts +0 -526
  35. package/src/nostr-bus.integration.test.ts +0 -472
  36. package/src/nostr-bus.test.ts +0 -190
  37. package/src/nostr-bus.ts +0 -789
  38. package/src/nostr-key-utils.ts +0 -94
  39. package/src/nostr-profile-core.ts +0 -134
  40. package/src/nostr-profile-http-runtime.ts +0 -6
  41. package/src/nostr-profile-http.test.ts +0 -632
  42. package/src/nostr-profile-http.ts +0 -594
  43. package/src/nostr-profile-import.test.ts +0 -119
  44. package/src/nostr-profile-import.ts +0 -262
  45. package/src/nostr-profile-url-safety.ts +0 -21
  46. package/src/nostr-profile.fuzz.test.ts +0 -430
  47. package/src/nostr-profile.test.ts +0 -412
  48. package/src/nostr-profile.ts +0 -144
  49. package/src/nostr-state-store.test.ts +0 -237
  50. package/src/nostr-state-store.ts +0 -223
  51. package/src/runtime.ts +0 -9
  52. package/src/seen-tracker.ts +0 -289
  53. package/src/session-route.ts +0 -25
  54. package/src/setup-surface.ts +0 -265
  55. package/src/test-fixtures.ts +0 -45
  56. package/src/types.ts +0 -117
  57. package/test/setup.ts +0 -5
  58. package/test-api.ts +0 -1
  59. package/tsconfig.json +0 -16
@@ -1,94 +0,0 @@
1
- import { getPublicKey, nip19 } from "nostr-tools";
2
-
3
- /**
4
- * Validate and normalize a private key (accepts hex or nsec format)
5
- */
6
- export function validatePrivateKey(key: string): Uint8Array {
7
- const trimmed = key.trim();
8
-
9
- // Handle nsec (bech32) format
10
- if (trimmed.startsWith("nsec1")) {
11
- const decoded = nip19.decode(trimmed);
12
- if (decoded.type !== "nsec") {
13
- throw new Error("Invalid nsec key: wrong type");
14
- }
15
- return decoded.data;
16
- }
17
-
18
- // Handle hex format
19
- if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) {
20
- throw new Error("Private key must be 64 hex characters or nsec bech32 format");
21
- }
22
-
23
- // Convert hex string to Uint8Array
24
- const bytes = new Uint8Array(32);
25
- for (let i = 0; i < 32; i++) {
26
- bytes[i] = Number.parseInt(trimmed.slice(i * 2, i * 2 + 2), 16);
27
- }
28
- return bytes;
29
- }
30
-
31
- /**
32
- * Get public key from private key (hex or nsec format)
33
- */
34
- export function getPublicKeyFromPrivate(privateKey: string): string {
35
- const sk = validatePrivateKey(privateKey);
36
- return getPublicKey(sk);
37
- }
38
-
39
- /**
40
- * Check if a string looks like a valid Nostr pubkey (hex or npub)
41
- */
42
- export function isValidPubkey(input: string): boolean {
43
- if (typeof input !== "string") {
44
- return false;
45
- }
46
- const trimmed = input.trim();
47
-
48
- // npub format
49
- if (trimmed.startsWith("npub1")) {
50
- try {
51
- const decoded = nip19.decode(trimmed);
52
- return decoded.type === "npub";
53
- } catch {
54
- return false;
55
- }
56
- }
57
-
58
- // Hex format
59
- return /^[0-9a-fA-F]{64}$/.test(trimmed);
60
- }
61
-
62
- /**
63
- * Normalize a pubkey to hex format (accepts npub or hex)
64
- */
65
- export function normalizePubkey(input: string): string {
66
- const trimmed = input.trim();
67
-
68
- // npub format - decode to hex
69
- if (trimmed.startsWith("npub1")) {
70
- const decoded = nip19.decode(trimmed);
71
- if (decoded.type !== "npub") {
72
- throw new Error("Invalid npub key");
73
- }
74
- // Convert Uint8Array to hex string
75
- return Array.from(decoded.data as unknown as Uint8Array)
76
- .map((b) => b.toString(16).padStart(2, "0"))
77
- .join("");
78
- }
79
-
80
- // Already hex - validate and return lowercase
81
- if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) {
82
- throw new Error("Pubkey must be 64 hex characters or npub format");
83
- }
84
- return trimmed.toLowerCase();
85
- }
86
-
87
- /**
88
- * Convert a hex pubkey to npub format
89
- */
90
- export function pubkeyToNpub(hexPubkey: string): string {
91
- const normalized = normalizePubkey(hexPubkey);
92
- // npubEncode expects a hex string, not Uint8Array
93
- return nip19.npubEncode(normalized);
94
- }
@@ -1,134 +0,0 @@
1
- import { type NostrProfile, NostrProfileSchema } from "./config-schema.js";
2
-
3
- /** NIP-01 profile content (JSON inside kind:0 event). */
4
- export interface ProfileContent {
5
- name?: string;
6
- display_name?: string;
7
- about?: string;
8
- picture?: string;
9
- banner?: string;
10
- website?: string;
11
- nip05?: string;
12
- lud16?: string;
13
- }
14
-
15
- /**
16
- * Convert our config profile schema to NIP-01 content format.
17
- * Strips undefined fields and validates URLs.
18
- */
19
- export function profileToContent(profile: NostrProfile): ProfileContent {
20
- const validated = NostrProfileSchema.parse(profile);
21
-
22
- const content: ProfileContent = {};
23
-
24
- if (validated.name !== undefined) {
25
- content.name = validated.name;
26
- }
27
- if (validated.displayName !== undefined) {
28
- content.display_name = validated.displayName;
29
- }
30
- if (validated.about !== undefined) {
31
- content.about = validated.about;
32
- }
33
- if (validated.picture !== undefined) {
34
- content.picture = validated.picture;
35
- }
36
- if (validated.banner !== undefined) {
37
- content.banner = validated.banner;
38
- }
39
- if (validated.website !== undefined) {
40
- content.website = validated.website;
41
- }
42
- if (validated.nip05 !== undefined) {
43
- content.nip05 = validated.nip05;
44
- }
45
- if (validated.lud16 !== undefined) {
46
- content.lud16 = validated.lud16;
47
- }
48
-
49
- return content;
50
- }
51
-
52
- /**
53
- * Convert NIP-01 content format back to our config profile schema.
54
- * Useful for importing existing profiles from relays.
55
- */
56
- export function contentToProfile(content: ProfileContent): NostrProfile {
57
- const profile: NostrProfile = {};
58
-
59
- if (content.name !== undefined) {
60
- profile.name = content.name;
61
- }
62
- if (content.display_name !== undefined) {
63
- profile.displayName = content.display_name;
64
- }
65
- if (content.about !== undefined) {
66
- profile.about = content.about;
67
- }
68
- if (content.picture !== undefined) {
69
- profile.picture = content.picture;
70
- }
71
- if (content.banner !== undefined) {
72
- profile.banner = content.banner;
73
- }
74
- if (content.website !== undefined) {
75
- profile.website = content.website;
76
- }
77
- if (content.nip05 !== undefined) {
78
- profile.nip05 = content.nip05;
79
- }
80
- if (content.lud16 !== undefined) {
81
- profile.lud16 = content.lud16;
82
- }
83
-
84
- return profile;
85
- }
86
-
87
- /**
88
- * Validate a profile without throwing (returns result object).
89
- */
90
- export function validateProfile(profile: unknown): {
91
- valid: boolean;
92
- profile?: NostrProfile;
93
- errors?: string[];
94
- } {
95
- const result = NostrProfileSchema.safeParse(profile);
96
-
97
- if (result.success) {
98
- return { valid: true, profile: result.data };
99
- }
100
-
101
- return {
102
- valid: false,
103
- errors: result.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`),
104
- };
105
- }
106
-
107
- /**
108
- * Sanitize profile text fields to prevent XSS when displaying in UI.
109
- * Escapes HTML special characters.
110
- */
111
- export function sanitizeProfileForDisplay(profile: NostrProfile): NostrProfile {
112
- const escapeHtml = (str: string | undefined): string | undefined => {
113
- if (str === undefined) {
114
- return undefined;
115
- }
116
- return str
117
- .replace(/&/g, "&amp;")
118
- .replace(/</g, "&lt;")
119
- .replace(/>/g, "&gt;")
120
- .replace(/"/g, "&quot;")
121
- .replace(/'/g, "&#039;");
122
- };
123
-
124
- return {
125
- name: escapeHtml(profile.name),
126
- displayName: escapeHtml(profile.displayName),
127
- about: escapeHtml(profile.about),
128
- picture: profile.picture,
129
- banner: profile.banner,
130
- website: profile.website,
131
- nip05: escapeHtml(profile.nip05),
132
- lud16: escapeHtml(profile.lud16),
133
- };
134
- }
@@ -1,6 +0,0 @@
1
- export {
2
- readJsonBodyWithLimit,
3
- requestBodyErrorToText,
4
- } from "openclaw/plugin-sdk/webhook-request-guards";
5
- export { createFixedWindowRateLimiter } from "openclaw/plugin-sdk/webhook-ingress";
6
- export { getPluginRuntimeGatewayRequestScope } from "../runtime-api.js";