@unicitylabs/nostr-js-sdk 0.0.1

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 (124) hide show
  1. package/README.md +290 -0
  2. package/dist/browser/index.js +8444 -0
  3. package/dist/browser/index.js.map +1 -0
  4. package/dist/browser/index.min.js +12 -0
  5. package/dist/browser/index.min.js.map +1 -0
  6. package/dist/browser/index.umd.js +8524 -0
  7. package/dist/browser/index.umd.js.map +1 -0
  8. package/dist/browser/index.umd.min.js +12 -0
  9. package/dist/browser/index.umd.min.js.map +1 -0
  10. package/dist/cjs/NostrKeyManager.js +265 -0
  11. package/dist/cjs/NostrKeyManager.js.map +1 -0
  12. package/dist/cjs/client/NostrClient.js +518 -0
  13. package/dist/cjs/client/NostrClient.js.map +1 -0
  14. package/dist/cjs/client/NostrEventListener.js +31 -0
  15. package/dist/cjs/client/NostrEventListener.js.map +1 -0
  16. package/dist/cjs/client/WebSocketAdapter.js +90 -0
  17. package/dist/cjs/client/WebSocketAdapter.js.map +1 -0
  18. package/dist/cjs/client/index.js +18 -0
  19. package/dist/cjs/client/index.js.map +1 -0
  20. package/dist/cjs/crypto/bech32.js +201 -0
  21. package/dist/cjs/crypto/bech32.js.map +1 -0
  22. package/dist/cjs/crypto/index.js +49 -0
  23. package/dist/cjs/crypto/index.js.map +1 -0
  24. package/dist/cjs/crypto/nip04.js +327 -0
  25. package/dist/cjs/crypto/nip04.js.map +1 -0
  26. package/dist/cjs/crypto/schnorr.js +101 -0
  27. package/dist/cjs/crypto/schnorr.js.map +1 -0
  28. package/dist/cjs/index.js +57 -0
  29. package/dist/cjs/index.js.map +1 -0
  30. package/dist/cjs/nametag/NametagBinding.js +196 -0
  31. package/dist/cjs/nametag/NametagBinding.js.map +1 -0
  32. package/dist/cjs/nametag/NametagUtils.js +156 -0
  33. package/dist/cjs/nametag/NametagUtils.js.map +1 -0
  34. package/dist/cjs/nametag/index.js +47 -0
  35. package/dist/cjs/nametag/index.js.map +1 -0
  36. package/dist/cjs/protocol/Event.js +209 -0
  37. package/dist/cjs/protocol/Event.js.map +1 -0
  38. package/dist/cjs/protocol/EventKinds.js +126 -0
  39. package/dist/cjs/protocol/EventKinds.js.map +1 -0
  40. package/dist/cjs/protocol/Filter.js +202 -0
  41. package/dist/cjs/protocol/Filter.js.map +1 -0
  42. package/dist/cjs/protocol/index.js +50 -0
  43. package/dist/cjs/protocol/index.js.map +1 -0
  44. package/dist/cjs/token/TokenTransferProtocol.js +196 -0
  45. package/dist/cjs/token/TokenTransferProtocol.js.map +1 -0
  46. package/dist/cjs/token/index.js +45 -0
  47. package/dist/cjs/token/index.js.map +1 -0
  48. package/dist/esm/NostrKeyManager.js +228 -0
  49. package/dist/esm/NostrKeyManager.js.map +1 -0
  50. package/dist/esm/client/NostrClient.js +481 -0
  51. package/dist/esm/client/NostrClient.js.map +1 -0
  52. package/dist/esm/client/NostrEventListener.js +27 -0
  53. package/dist/esm/client/NostrEventListener.js.map +1 -0
  54. package/dist/esm/client/WebSocketAdapter.js +52 -0
  55. package/dist/esm/client/WebSocketAdapter.js.map +1 -0
  56. package/dist/esm/client/index.js +7 -0
  57. package/dist/esm/client/index.js.map +1 -0
  58. package/dist/esm/crypto/bech32.js +193 -0
  59. package/dist/esm/crypto/bech32.js.map +1 -0
  60. package/dist/esm/crypto/index.js +10 -0
  61. package/dist/esm/crypto/index.js.map +1 -0
  62. package/dist/esm/crypto/nip04.js +286 -0
  63. package/dist/esm/crypto/nip04.js.map +1 -0
  64. package/dist/esm/crypto/schnorr.js +93 -0
  65. package/dist/esm/crypto/schnorr.js.map +1 -0
  66. package/dist/esm/index.js +32 -0
  67. package/dist/esm/index.js.map +1 -0
  68. package/dist/esm/nametag/NametagBinding.js +155 -0
  69. package/dist/esm/nametag/NametagBinding.js.map +1 -0
  70. package/dist/esm/nametag/NametagUtils.js +149 -0
  71. package/dist/esm/nametag/NametagUtils.js.map +1 -0
  72. package/dist/esm/nametag/index.js +8 -0
  73. package/dist/esm/nametag/index.js.map +1 -0
  74. package/dist/esm/protocol/Event.js +172 -0
  75. package/dist/esm/protocol/Event.js.map +1 -0
  76. package/dist/esm/protocol/EventKinds.js +119 -0
  77. package/dist/esm/protocol/EventKinds.js.map +1 -0
  78. package/dist/esm/protocol/Filter.js +197 -0
  79. package/dist/esm/protocol/Filter.js.map +1 -0
  80. package/dist/esm/protocol/index.js +8 -0
  81. package/dist/esm/protocol/index.js.map +1 -0
  82. package/dist/esm/token/TokenTransferProtocol.js +154 -0
  83. package/dist/esm/token/TokenTransferProtocol.js.map +1 -0
  84. package/dist/esm/token/index.js +6 -0
  85. package/dist/esm/token/index.js.map +1 -0
  86. package/dist/types/NostrKeyManager.d.ts +150 -0
  87. package/dist/types/NostrKeyManager.d.ts.map +1 -0
  88. package/dist/types/client/NostrClient.d.ts +154 -0
  89. package/dist/types/client/NostrClient.d.ts.map +1 -0
  90. package/dist/types/client/NostrEventListener.d.ts +40 -0
  91. package/dist/types/client/NostrEventListener.d.ts.map +1 -0
  92. package/dist/types/client/WebSocketAdapter.d.ts +55 -0
  93. package/dist/types/client/WebSocketAdapter.d.ts.map +1 -0
  94. package/dist/types/client/index.d.ts +9 -0
  95. package/dist/types/client/index.d.ts.map +1 -0
  96. package/dist/types/crypto/bech32.d.ts +51 -0
  97. package/dist/types/crypto/bech32.d.ts.map +1 -0
  98. package/dist/types/crypto/index.d.ts +10 -0
  99. package/dist/types/crypto/index.d.ts.map +1 -0
  100. package/dist/types/crypto/nip04.d.ts +56 -0
  101. package/dist/types/crypto/nip04.d.ts.map +1 -0
  102. package/dist/types/crypto/schnorr.d.ts +47 -0
  103. package/dist/types/crypto/schnorr.d.ts.map +1 -0
  104. package/dist/types/index.d.ts +31 -0
  105. package/dist/types/index.d.ts.map +1 -0
  106. package/dist/types/nametag/NametagBinding.d.ts +68 -0
  107. package/dist/types/nametag/NametagBinding.d.ts.map +1 -0
  108. package/dist/types/nametag/NametagUtils.d.ts +44 -0
  109. package/dist/types/nametag/NametagUtils.d.ts.map +1 -0
  110. package/dist/types/nametag/index.d.ts +8 -0
  111. package/dist/types/nametag/index.d.ts.map +1 -0
  112. package/dist/types/protocol/Event.d.ts +112 -0
  113. package/dist/types/protocol/Event.d.ts.map +1 -0
  114. package/dist/types/protocol/EventKinds.d.ts +62 -0
  115. package/dist/types/protocol/EventKinds.d.ts.map +1 -0
  116. package/dist/types/protocol/Filter.d.ts +146 -0
  117. package/dist/types/protocol/Filter.d.ts.map +1 -0
  118. package/dist/types/protocol/index.d.ts +10 -0
  119. package/dist/types/protocol/index.d.ts.map +1 -0
  120. package/dist/types/token/TokenTransferProtocol.d.ts +67 -0
  121. package/dist/types/token/TokenTransferProtocol.d.ts.map +1 -0
  122. package/dist/types/token/index.d.ts +6 -0
  123. package/dist/types/token/index.d.ts.map +1 -0
  124. package/package.json +89 -0
@@ -0,0 +1,155 @@
1
+ /**
2
+ * NametagBinding - Create and parse nametag binding events.
3
+ * Uses kind 30078 (APP_DATA) for parameterized replaceable events.
4
+ */
5
+ import { Event } from '../protocol/Event.js';
6
+ import { Filter } from '../protocol/Filter.js';
7
+ import * as EventKinds from '../protocol/EventKinds.js';
8
+ import * as NametagUtils from './NametagUtils.js';
9
+ /** Default country code for phone number normalization */
10
+ const DEFAULT_COUNTRY = 'US';
11
+ /**
12
+ * Create a nametag binding event.
13
+ *
14
+ * Event structure:
15
+ * - Kind: 30078 (APP_DATA - parameterized replaceable)
16
+ * - Tags:
17
+ * - ["d", "<hashed_nametag>"] - Required for parameterized replaceable
18
+ * - ["nametag", "<hashed_nametag>"] - Hashed for privacy
19
+ * - ["t", "<hashed_nametag>"] - Indexed tag for relay search
20
+ * - ["address", "<unicity_addr>"] - Unicity blockchain address
21
+ * - Content: JSON with nametag_hash, address, verified timestamp
22
+ *
23
+ * @param keyManager Key manager with signing keys
24
+ * @param nametagId Nametag identifier (phone number or username)
25
+ * @param unicityAddress Unicity blockchain address
26
+ * @param defaultCountry Default country code for phone normalization
27
+ * @returns Signed event
28
+ */
29
+ export async function createBindingEvent(keyManager, nametagId, unicityAddress, defaultCountry = DEFAULT_COUNTRY) {
30
+ const hashedNametag = NametagUtils.hashNametag(nametagId, defaultCountry);
31
+ const content = {
32
+ nametag_hash: hashedNametag,
33
+ address: unicityAddress,
34
+ verified: Date.now(),
35
+ };
36
+ const event = Event.create(keyManager, {
37
+ kind: EventKinds.APP_DATA,
38
+ tags: [
39
+ ['d', hashedNametag],
40
+ ['nametag', hashedNametag],
41
+ ['t', hashedNametag],
42
+ ['address', unicityAddress],
43
+ ],
44
+ content: JSON.stringify(content),
45
+ });
46
+ return event;
47
+ }
48
+ /**
49
+ * Create a filter to query pubkey by nametag.
50
+ * Query direction: nametag → pubkey
51
+ *
52
+ * @param nametagId Nametag identifier
53
+ * @param defaultCountry Default country code for phone normalization
54
+ * @returns Filter for nametag binding events
55
+ */
56
+ export function createNametagToPubkeyFilter(nametagId, defaultCountry = DEFAULT_COUNTRY) {
57
+ const hashedNametag = NametagUtils.hashNametag(nametagId, defaultCountry);
58
+ return Filter.builder()
59
+ .kinds(EventKinds.APP_DATA)
60
+ .tTags(hashedNametag)
61
+ .build();
62
+ }
63
+ /**
64
+ * Create a filter to query nametags by pubkey.
65
+ * Query direction: pubkey → nametags
66
+ *
67
+ * @param nostrPubkey Nostr public key (hex)
68
+ * @returns Filter for nametag binding events
69
+ */
70
+ export function createPubkeyToNametagFilter(nostrPubkey) {
71
+ return Filter.builder()
72
+ .kinds(EventKinds.APP_DATA)
73
+ .authors(nostrPubkey)
74
+ .limit(10)
75
+ .build();
76
+ }
77
+ /**
78
+ * Parse the hashed nametag from a binding event.
79
+ * Tries tags first, then content JSON.
80
+ *
81
+ * @param event Binding event
82
+ * @returns Hashed nametag, or undefined if not found
83
+ */
84
+ export function parseNametagHashFromEvent(event) {
85
+ // Try "nametag" tag first
86
+ const fromTag = event.getTagValue('nametag');
87
+ if (fromTag) {
88
+ return fromTag;
89
+ }
90
+ // Try "d" tag
91
+ const fromDTag = event.getTagValue('d');
92
+ if (fromDTag) {
93
+ return fromDTag;
94
+ }
95
+ // Try content JSON
96
+ try {
97
+ const content = JSON.parse(event.content);
98
+ return content.nametag_hash;
99
+ }
100
+ catch {
101
+ return undefined;
102
+ }
103
+ }
104
+ /**
105
+ * Parse the Unicity address from a binding event.
106
+ * Tries tags first, then content JSON.
107
+ *
108
+ * @param event Binding event
109
+ * @returns Unicity address, or undefined if not found
110
+ */
111
+ export function parseAddressFromEvent(event) {
112
+ // Try "address" tag first
113
+ const fromTag = event.getTagValue('address');
114
+ if (fromTag) {
115
+ return fromTag;
116
+ }
117
+ // Try content JSON
118
+ try {
119
+ const content = JSON.parse(event.content);
120
+ return content.address;
121
+ }
122
+ catch {
123
+ return undefined;
124
+ }
125
+ }
126
+ /**
127
+ * Verify that a binding event is valid.
128
+ * Checks signature and structure.
129
+ *
130
+ * @param event Event to verify
131
+ * @returns true if the binding event is valid
132
+ */
133
+ export function isValidBindingEvent(event) {
134
+ // Check event kind
135
+ if (event.kind !== EventKinds.APP_DATA) {
136
+ return false;
137
+ }
138
+ // Check required tags
139
+ if (!event.hasTag('d')) {
140
+ return false;
141
+ }
142
+ // Check content structure
143
+ try {
144
+ const content = JSON.parse(event.content);
145
+ if (!content.nametag_hash || !content.address) {
146
+ return false;
147
+ }
148
+ }
149
+ catch {
150
+ return false;
151
+ }
152
+ // Verify signature
153
+ return event.verify();
154
+ }
155
+ //# sourceMappingURL=NametagBinding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NametagBinding.js","sourceRoot":"","sources":["../../../src/nametag/NametagBinding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * NametagUtils - Privacy-preserving nametag normalization and hashing.
3
+ * Supports phone number normalization to E.164 format.
4
+ */
5
+ import { sha256 } from '@noble/hashes/sha256';
6
+ import { bytesToHex } from '@noble/hashes/utils';
7
+ import { parsePhoneNumber, isValidPhoneNumber } from 'libphonenumber-js';
8
+ /** Salt prefix for nametag hashing */
9
+ const NAMETAG_SALT = 'unicity:nametag:';
10
+ /** Default country code for phone number normalization */
11
+ const DEFAULT_COUNTRY = 'US';
12
+ /**
13
+ * Compute SHA-256 hash of a string.
14
+ * @param input String to hash
15
+ * @returns Hex-encoded hash
16
+ */
17
+ function sha256Hex(input) {
18
+ const bytes = new TextEncoder().encode(input);
19
+ return bytesToHex(sha256(bytes));
20
+ }
21
+ /**
22
+ * Check if a string looks like a phone number.
23
+ * Heuristic: starts with + OR has >50% digits AND >= 7 digits total.
24
+ * @param str String to check
25
+ * @returns true if the string looks like a phone number
26
+ */
27
+ function isLikelyPhoneNumber(str) {
28
+ if (str.startsWith('+')) {
29
+ return true;
30
+ }
31
+ const digitsOnly = str.replace(/\D/g, '');
32
+ const digitCount = digitsOnly.length;
33
+ if (digitCount < 7) {
34
+ return false;
35
+ }
36
+ // Count non-digit characters (excluding common phone number chars)
37
+ const cleanedLength = str.replace(/[\s\-\(\)\.]/g, '').length;
38
+ const digitRatio = digitCount / cleanedLength;
39
+ return digitRatio > 0.5;
40
+ }
41
+ /**
42
+ * Normalize a phone number to E.164 format.
43
+ * @param phoneNumber Phone number string
44
+ * @param defaultCountry Default country code
45
+ * @returns E.164 formatted phone number, or null if invalid
46
+ */
47
+ function normalizePhoneNumber(phoneNumber, defaultCountry) {
48
+ try {
49
+ // Try to parse with default country
50
+ if (isValidPhoneNumber(phoneNumber, defaultCountry)) {
51
+ const parsed = parsePhoneNumber(phoneNumber, defaultCountry);
52
+ return parsed.format('E.164');
53
+ }
54
+ // Try without default country (for numbers with country code)
55
+ if (isValidPhoneNumber(phoneNumber)) {
56
+ const parsed = parsePhoneNumber(phoneNumber);
57
+ return parsed.format('E.164');
58
+ }
59
+ return null;
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ /**
66
+ * Normalize a nametag for hashing.
67
+ * - If it looks like a phone number, normalize to E.164
68
+ * - Otherwise, lowercase and remove @unicity suffix
69
+ * @param nametag Nametag to normalize
70
+ * @param defaultCountry Default country code for phone normalization
71
+ * @returns Normalized nametag
72
+ */
73
+ export function normalizeNametag(nametag, defaultCountry = DEFAULT_COUNTRY) {
74
+ const trimmed = nametag.trim();
75
+ if (isLikelyPhoneNumber(trimmed)) {
76
+ const normalized = normalizePhoneNumber(trimmed, defaultCountry);
77
+ if (normalized) {
78
+ return normalized;
79
+ }
80
+ // If phone normalization fails, fall through to standard normalization
81
+ }
82
+ // Standard normalization: lowercase, remove @unicity suffix
83
+ let normalized = trimmed.toLowerCase();
84
+ if (normalized.endsWith('@unicity')) {
85
+ normalized = normalized.slice(0, -8);
86
+ }
87
+ return normalized;
88
+ }
89
+ /**
90
+ * Hash a nametag with the standard salt.
91
+ * @param nametag Nametag to hash
92
+ * @param defaultCountry Default country code for phone normalization
93
+ * @returns Hex-encoded SHA-256 hash
94
+ */
95
+ export function hashNametag(nametag, defaultCountry = DEFAULT_COUNTRY) {
96
+ const normalized = normalizeNametag(nametag, defaultCountry);
97
+ return sha256Hex(NAMETAG_SALT + normalized);
98
+ }
99
+ /**
100
+ * Compare two nametags for equality (handling format variations).
101
+ * @param tag1 First nametag
102
+ * @param tag2 Second nametag
103
+ * @param defaultCountry Default country code for phone normalization
104
+ * @returns true if the nametags represent the same identity
105
+ */
106
+ export function areSameNametag(tag1, tag2, defaultCountry = DEFAULT_COUNTRY) {
107
+ const normalized1 = normalizeNametag(tag1, defaultCountry);
108
+ const normalized2 = normalizeNametag(tag2, defaultCountry);
109
+ return normalized1 === normalized2;
110
+ }
111
+ /**
112
+ * Format a nametag for display (privacy-preserving).
113
+ * For phone numbers, hides middle digits.
114
+ * @param nametag Nametag to format
115
+ * @param defaultCountry Default country code for phone normalization
116
+ * @returns Display-safe formatted nametag
117
+ */
118
+ export function formatForDisplay(nametag, defaultCountry = DEFAULT_COUNTRY) {
119
+ const trimmed = nametag.trim();
120
+ if (isLikelyPhoneNumber(trimmed)) {
121
+ const normalized = normalizePhoneNumber(trimmed, defaultCountry);
122
+ if (normalized) {
123
+ // Hide middle digits: +1415***2671
124
+ const digits = normalized.slice(1); // Remove +
125
+ if (digits.length > 6) {
126
+ const start = digits.slice(0, 4);
127
+ const end = digits.slice(-4);
128
+ return '+' + start + '***' + end;
129
+ }
130
+ }
131
+ }
132
+ return normalizeNametag(nametag, defaultCountry);
133
+ }
134
+ /**
135
+ * Check if a string is a valid phone number.
136
+ * @param str String to check
137
+ * @param defaultCountry Default country code
138
+ * @returns true if the string is a valid phone number
139
+ */
140
+ export function isPhoneNumber(str, defaultCountry = DEFAULT_COUNTRY) {
141
+ try {
142
+ return isValidPhoneNumber(str, defaultCountry) ||
143
+ isValidPhoneNumber(str);
144
+ }
145
+ catch {
146
+ return false;
147
+ }
148
+ }
149
+ //# sourceMappingURL=NametagUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NametagUtils.js","sourceRoot":"","sources":["../../../src/nametag/NametagUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Nametag module - Privacy-preserving identity bindings
3
+ */
4
+ export * as NametagUtils from './NametagUtils.js';
5
+ export * from './NametagUtils.js';
6
+ export * as NametagBinding from './NametagBinding.js';
7
+ export * from './NametagBinding.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/nametag/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAC;AAClD,cAAc,mBAAmB,CAAC;AAClC,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Event - Represents a Nostr event (NIP-01).
3
+ * Provides serialization, signing, and verification functionality.
4
+ */
5
+ import { sha256 } from '@noble/hashes/sha256';
6
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
7
+ import * as Schnorr from '../crypto/schnorr.js';
8
+ /**
9
+ * Event class representing a Nostr event (NIP-01).
10
+ */
11
+ export class Event {
12
+ /** Event ID - SHA-256 hash of the serialized event data (hex) */
13
+ id;
14
+ /** Creator's x-only public key (hex) */
15
+ pubkey;
16
+ /** Unix timestamp in seconds */
17
+ created_at;
18
+ /** Event kind (type) */
19
+ kind;
20
+ /** Event tags */
21
+ tags;
22
+ /** Event content */
23
+ content;
24
+ /** Schnorr signature (hex) */
25
+ sig;
26
+ /**
27
+ * Create an Event instance.
28
+ * @param data Signed event data
29
+ */
30
+ constructor(data) {
31
+ this.id = data.id;
32
+ this.pubkey = data.pubkey;
33
+ this.created_at = data.created_at;
34
+ this.kind = data.kind;
35
+ this.tags = data.tags;
36
+ this.content = data.content;
37
+ this.sig = data.sig;
38
+ }
39
+ /**
40
+ * Create and sign a new event.
41
+ * @param keyManager Key manager with signing key
42
+ * @param data Unsigned event data
43
+ * @returns Signed Event instance
44
+ */
45
+ static create(keyManager, data) {
46
+ const pubkey = keyManager.getPublicKeyHex();
47
+ const created_at = data.created_at ?? Math.floor(Date.now() / 1000);
48
+ // Calculate event ID
49
+ const id = Event.calculateId(pubkey, created_at, data.kind, data.tags, data.content);
50
+ // Sign the event ID
51
+ const idBytes = hexToBytes(id);
52
+ const sig = keyManager.signHex(idBytes);
53
+ return new Event({
54
+ id,
55
+ pubkey,
56
+ created_at,
57
+ kind: data.kind,
58
+ tags: data.tags,
59
+ content: data.content,
60
+ sig,
61
+ });
62
+ }
63
+ /**
64
+ * Calculate the event ID from event data.
65
+ * ID = SHA-256(serialized event data)
66
+ * Serialized format: [0, pubkey, created_at, kind, tags, content]
67
+ */
68
+ static calculateId(pubkey, created_at, kind, tags, content) {
69
+ const serialized = JSON.stringify([0, pubkey, created_at, kind, tags, content]);
70
+ const hash = sha256(new TextEncoder().encode(serialized));
71
+ return bytesToHex(hash);
72
+ }
73
+ /**
74
+ * Verify the event signature.
75
+ * @returns true if the signature is valid
76
+ */
77
+ verify() {
78
+ try {
79
+ // Verify the ID
80
+ const calculatedId = Event.calculateId(this.pubkey, this.created_at, this.kind, this.tags, this.content);
81
+ if (calculatedId !== this.id) {
82
+ return false;
83
+ }
84
+ // Verify the signature
85
+ const idBytes = hexToBytes(this.id);
86
+ const sigBytes = hexToBytes(this.sig);
87
+ const pubkeyBytes = hexToBytes(this.pubkey);
88
+ return Schnorr.verify(sigBytes, idBytes, pubkeyBytes);
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }
94
+ /**
95
+ * Parse an event from JSON data.
96
+ * @param json JSON object or string
97
+ * @returns Event instance
98
+ */
99
+ static fromJSON(json) {
100
+ const data = typeof json === 'string' ? JSON.parse(json) : json;
101
+ if (!Event.isValidEventData(data)) {
102
+ throw new Error('Invalid event data');
103
+ }
104
+ return new Event(data);
105
+ }
106
+ /**
107
+ * Check if data has valid event structure.
108
+ */
109
+ static isValidEventData(data) {
110
+ if (typeof data !== 'object' || data === null) {
111
+ return false;
112
+ }
113
+ const obj = data;
114
+ return (typeof obj.id === 'string' &&
115
+ typeof obj.pubkey === 'string' &&
116
+ typeof obj.created_at === 'number' &&
117
+ typeof obj.kind === 'number' &&
118
+ Array.isArray(obj.tags) &&
119
+ typeof obj.content === 'string' &&
120
+ typeof obj.sig === 'string');
121
+ }
122
+ /**
123
+ * Convert the event to a plain object.
124
+ * @returns Plain object representation
125
+ */
126
+ toJSON() {
127
+ return {
128
+ id: this.id,
129
+ pubkey: this.pubkey,
130
+ created_at: this.created_at,
131
+ kind: this.kind,
132
+ tags: this.tags,
133
+ content: this.content,
134
+ sig: this.sig,
135
+ };
136
+ }
137
+ /**
138
+ * Get the first value of a tag by name.
139
+ * @param tagName Tag name to find
140
+ * @returns First value of the tag, or undefined if not found
141
+ */
142
+ getTagValue(tagName) {
143
+ const tag = this.tags.find((t) => t[0] === tagName);
144
+ return tag?.[1];
145
+ }
146
+ /**
147
+ * Get all values of a tag by name.
148
+ * @param tagName Tag name to find
149
+ * @returns Array of tag values
150
+ */
151
+ getTagValues(tagName) {
152
+ return this.tags.filter((t) => t[0] === tagName).map((t) => t[1] ?? '');
153
+ }
154
+ /**
155
+ * Check if a tag exists.
156
+ * @param tagName Tag name to check
157
+ * @returns true if the tag exists
158
+ */
159
+ hasTag(tagName) {
160
+ return this.tags.some((t) => t[0] === tagName);
161
+ }
162
+ /**
163
+ * Get all values from a single tag entry (excluding the tag name).
164
+ * @param tagName Tag name to find
165
+ * @returns Array of values from the first matching tag, or empty array
166
+ */
167
+ getTagEntryValues(tagName) {
168
+ const tag = this.tags.find((t) => t[0] === tagName);
169
+ return tag ? tag.slice(1) : [];
170
+ }
171
+ }
172
+ //# sourceMappingURL=Event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Event.js","sourceRoot":"","sources":["../../../src/protocol/Event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * EventKinds - Standardized Nostr event kind definitions.
3
+ * Includes both standard NIP kinds and Unicity custom kinds.
4
+ */
5
+ // ============================================================================
6
+ // Standard NIP Event Kinds
7
+ // ============================================================================
8
+ /** NIP-01: User profile metadata */
9
+ export const PROFILE = 0;
10
+ /** NIP-01: Short text note */
11
+ export const TEXT_NOTE = 1;
12
+ /** NIP-01: Recommend relay to followers */
13
+ export const RECOMMEND_RELAY = 2;
14
+ /** NIP-02: Contact list (follows) */
15
+ export const CONTACTS = 3;
16
+ /** NIP-04: Encrypted direct messages */
17
+ export const ENCRYPTED_DM = 4;
18
+ /** NIP-09: Event deletion */
19
+ export const DELETION = 5;
20
+ /** NIP-25: Reactions (likes, etc.) */
21
+ export const REACTION = 7;
22
+ /** NIP-59: Gift wrap for private events */
23
+ export const GIFT_WRAP = 1059;
24
+ /** NIP-65: Relay list metadata */
25
+ export const RELAY_LIST = 10002;
26
+ /** NIP-78: Application-specific data (parameterized replaceable) */
27
+ export const APP_DATA = 30078;
28
+ // ============================================================================
29
+ // Unicity Custom Event Kinds
30
+ // ============================================================================
31
+ /** Unicity: Agent profile information */
32
+ export const AGENT_PROFILE = 31111;
33
+ /** Unicity: Agent GPS location */
34
+ export const AGENT_LOCATION = 31112;
35
+ /** Unicity: Token transfer event */
36
+ export const TOKEN_TRANSFER = 31113;
37
+ /** Unicity: File metadata */
38
+ export const FILE_METADATA = 31114;
39
+ // ============================================================================
40
+ // Event Kind Classification Functions
41
+ // ============================================================================
42
+ /**
43
+ * Check if an event kind is replaceable.
44
+ * Replaceable events (kinds 0, 3, or 10000-19999) are replaced when a new
45
+ * event with the same kind and pubkey is published.
46
+ * @param kind Event kind number
47
+ * @returns true if the event kind is replaceable
48
+ */
49
+ export function isReplaceable(kind) {
50
+ return kind === 0 || kind === 3 || (kind >= 10000 && kind < 20000);
51
+ }
52
+ /**
53
+ * Check if an event kind is ephemeral.
54
+ * Ephemeral events (kinds 20000-29999) are not stored by relays.
55
+ * @param kind Event kind number
56
+ * @returns true if the event kind is ephemeral
57
+ */
58
+ export function isEphemeral(kind) {
59
+ return kind >= 20000 && kind < 30000;
60
+ }
61
+ /**
62
+ * Check if an event kind is parameterized replaceable.
63
+ * Parameterized replaceable events (kinds 30000-39999) are replaced when a
64
+ * new event with the same kind, pubkey, and "d" tag value is published.
65
+ * @param kind Event kind number
66
+ * @returns true if the event kind is parameterized replaceable
67
+ */
68
+ export function isParameterizedReplaceable(kind) {
69
+ return kind >= 30000 && kind < 40000;
70
+ }
71
+ /**
72
+ * Get a human-readable name for an event kind.
73
+ * @param kind Event kind number
74
+ * @returns Human-readable name for the event kind
75
+ */
76
+ export function getName(kind) {
77
+ switch (kind) {
78
+ case PROFILE:
79
+ return 'Profile';
80
+ case TEXT_NOTE:
81
+ return 'Text Note';
82
+ case RECOMMEND_RELAY:
83
+ return 'Recommend Relay';
84
+ case CONTACTS:
85
+ return 'Contacts';
86
+ case ENCRYPTED_DM:
87
+ return 'Encrypted DM';
88
+ case DELETION:
89
+ return 'Deletion';
90
+ case REACTION:
91
+ return 'Reaction';
92
+ case GIFT_WRAP:
93
+ return 'Gift Wrap';
94
+ case RELAY_LIST:
95
+ return 'Relay List';
96
+ case APP_DATA:
97
+ return 'App Data';
98
+ case AGENT_PROFILE:
99
+ return 'Agent Profile';
100
+ case AGENT_LOCATION:
101
+ return 'Agent Location';
102
+ case TOKEN_TRANSFER:
103
+ return 'Token Transfer';
104
+ case FILE_METADATA:
105
+ return 'File Metadata';
106
+ default:
107
+ if (isReplaceable(kind)) {
108
+ return `Replaceable (${kind})`;
109
+ }
110
+ if (isEphemeral(kind)) {
111
+ return `Ephemeral (${kind})`;
112
+ }
113
+ if (isParameterizedReplaceable(kind)) {
114
+ return `Parameterized Replaceable (${kind})`;
115
+ }
116
+ return `Unknown (${kind})`;
117
+ }
118
+ }
119
+ //# sourceMappingURL=EventKinds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventKinds.js","sourceRoot":"","sources":["../../../src/protocol/EventKinds.ts"],"names":[],"mappings":"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"}