@massalabs/gossip-sdk 0.0.2-dev.20260128094509 → 0.0.2-dev.20260128111120

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 (142) hide show
  1. package/dist/api/messageProtocol/index.d.ts +19 -0
  2. package/dist/api/messageProtocol/index.js +26 -0
  3. package/dist/api/messageProtocol/mock.d.ts +12 -0
  4. package/{src/api/messageProtocol/mock.ts → dist/api/messageProtocol/mock.js} +2 -3
  5. package/dist/api/messageProtocol/rest.d.ts +22 -0
  6. package/dist/api/messageProtocol/rest.js +161 -0
  7. package/dist/api/messageProtocol/types.d.ts +61 -0
  8. package/dist/api/messageProtocol/types.js +6 -0
  9. package/dist/assets/generated/wasm/README.md +281 -0
  10. package/dist/assets/generated/wasm/gossip_wasm.d.ts +498 -0
  11. package/dist/assets/generated/wasm/gossip_wasm.js +1399 -0
  12. package/dist/assets/generated/wasm/gossip_wasm_bg.wasm +0 -0
  13. package/dist/assets/generated/wasm/gossip_wasm_bg.wasm.d.ts +68 -0
  14. package/dist/assets/generated/wasm/package.json +15 -0
  15. package/dist/config/protocol.d.ts +36 -0
  16. package/dist/config/protocol.js +77 -0
  17. package/dist/config/sdk.d.ts +82 -0
  18. package/dist/config/sdk.js +55 -0
  19. package/{src/contacts.ts → dist/contacts.d.ts} +10 -94
  20. package/dist/contacts.js +166 -0
  21. package/dist/core/SdkEventEmitter.d.ts +36 -0
  22. package/dist/core/SdkEventEmitter.js +59 -0
  23. package/dist/core/SdkPolling.d.ts +35 -0
  24. package/dist/core/SdkPolling.js +100 -0
  25. package/{src/core/index.ts → dist/core/index.d.ts} +0 -2
  26. package/dist/core/index.js +5 -0
  27. package/dist/crypto/bip39.d.ts +34 -0
  28. package/dist/crypto/bip39.js +62 -0
  29. package/dist/crypto/encryption.d.ts +37 -0
  30. package/dist/crypto/encryption.js +46 -0
  31. package/dist/db.d.ts +190 -0
  32. package/dist/db.js +311 -0
  33. package/dist/gossipSdk.d.ts +274 -0
  34. package/dist/gossipSdk.js +690 -0
  35. package/dist/index.d.ts +73 -0
  36. package/dist/index.js +77 -0
  37. package/dist/services/announcement.d.ts +43 -0
  38. package/dist/services/announcement.js +491 -0
  39. package/dist/services/auth.d.ts +37 -0
  40. package/dist/services/auth.js +76 -0
  41. package/dist/services/discussion.d.ts +63 -0
  42. package/dist/services/discussion.js +297 -0
  43. package/dist/services/message.d.ts +74 -0
  44. package/dist/services/message.js +826 -0
  45. package/dist/services/refresh.d.ts +41 -0
  46. package/dist/services/refresh.js +205 -0
  47. package/{src/sw.ts → dist/sw.d.ts} +1 -8
  48. package/dist/sw.js +10 -0
  49. package/dist/types/events.d.ts +80 -0
  50. package/dist/types/events.js +7 -0
  51. package/dist/types.d.ts +32 -0
  52. package/dist/types.js +7 -0
  53. package/dist/utils/base64.d.ts +10 -0
  54. package/dist/utils/base64.js +30 -0
  55. package/dist/utils/contacts.d.ts +42 -0
  56. package/dist/utils/contacts.js +113 -0
  57. package/dist/utils/discussions.d.ts +24 -0
  58. package/dist/utils/discussions.js +38 -0
  59. package/dist/utils/logs.d.ts +19 -0
  60. package/dist/utils/logs.js +89 -0
  61. package/dist/utils/messageSerialization.d.ts +64 -0
  62. package/dist/utils/messageSerialization.js +184 -0
  63. package/dist/utils/queue.d.ts +50 -0
  64. package/dist/utils/queue.js +110 -0
  65. package/dist/utils/type.d.ts +10 -0
  66. package/dist/utils/type.js +4 -0
  67. package/dist/utils/userId.d.ts +40 -0
  68. package/dist/utils/userId.js +90 -0
  69. package/dist/utils/validation.d.ts +50 -0
  70. package/dist/utils/validation.js +112 -0
  71. package/dist/utils.d.ts +30 -0
  72. package/{src/utils.ts → dist/utils.js} +9 -19
  73. package/dist/wasm/encryption.d.ts +56 -0
  74. package/{src/wasm/encryption.ts → dist/wasm/encryption.js} +22 -51
  75. package/dist/wasm/index.d.ts +10 -0
  76. package/{src/wasm/index.ts → dist/wasm/index.js} +1 -8
  77. package/dist/wasm/loader.d.ts +21 -0
  78. package/dist/wasm/loader.js +103 -0
  79. package/dist/wasm/session.d.ts +85 -0
  80. package/dist/wasm/session.js +226 -0
  81. package/dist/wasm/userKeys.d.ts +17 -0
  82. package/{src/wasm/userKeys.ts → dist/wasm/userKeys.js} +6 -13
  83. package/package.json +5 -1
  84. package/src/api/messageProtocol/index.ts +0 -53
  85. package/src/api/messageProtocol/rest.ts +0 -209
  86. package/src/api/messageProtocol/types.ts +0 -70
  87. package/src/config/protocol.ts +0 -97
  88. package/src/config/sdk.ts +0 -131
  89. package/src/core/SdkEventEmitter.ts +0 -91
  90. package/src/core/SdkPolling.ts +0 -134
  91. package/src/crypto/bip39.ts +0 -84
  92. package/src/crypto/encryption.ts +0 -77
  93. package/src/db.ts +0 -465
  94. package/src/gossipSdk.ts +0 -994
  95. package/src/index.ts +0 -211
  96. package/src/services/announcement.ts +0 -653
  97. package/src/services/auth.ts +0 -95
  98. package/src/services/discussion.ts +0 -380
  99. package/src/services/message.ts +0 -1055
  100. package/src/services/refresh.ts +0 -234
  101. package/src/types/events.ts +0 -108
  102. package/src/types.ts +0 -70
  103. package/src/utils/base64.ts +0 -39
  104. package/src/utils/contacts.ts +0 -161
  105. package/src/utils/discussions.ts +0 -55
  106. package/src/utils/logs.ts +0 -86
  107. package/src/utils/messageSerialization.ts +0 -257
  108. package/src/utils/queue.ts +0 -106
  109. package/src/utils/type.ts +0 -7
  110. package/src/utils/userId.ts +0 -114
  111. package/src/utils/validation.ts +0 -144
  112. package/src/wasm/loader.ts +0 -123
  113. package/src/wasm/session.ts +0 -276
  114. package/test/config/protocol.spec.ts +0 -31
  115. package/test/config/sdk.spec.ts +0 -163
  116. package/test/db/helpers.spec.ts +0 -142
  117. package/test/db/operations.spec.ts +0 -128
  118. package/test/db/states.spec.ts +0 -535
  119. package/test/integration/discussion-flow.spec.ts +0 -422
  120. package/test/integration/messaging-flow.spec.ts +0 -708
  121. package/test/integration/sdk-lifecycle.spec.ts +0 -325
  122. package/test/mocks/index.ts +0 -9
  123. package/test/mocks/mockMessageProtocol.ts +0 -100
  124. package/test/services/auth.spec.ts +0 -311
  125. package/test/services/discussion.spec.ts +0 -279
  126. package/test/services/message-deduplication.spec.ts +0 -299
  127. package/test/services/message-startup.spec.ts +0 -331
  128. package/test/services/message.spec.ts +0 -817
  129. package/test/services/refresh.spec.ts +0 -199
  130. package/test/services/session-status.spec.ts +0 -349
  131. package/test/session/wasm.spec.ts +0 -227
  132. package/test/setup.ts +0 -52
  133. package/test/utils/contacts.spec.ts +0 -156
  134. package/test/utils/discussions.spec.ts +0 -66
  135. package/test/utils/queue.spec.ts +0 -52
  136. package/test/utils/serialization.spec.ts +0 -120
  137. package/test/utils/userId.spec.ts +0 -120
  138. package/test/utils/validation.spec.ts +0 -223
  139. package/test/utils.ts +0 -212
  140. package/tsconfig.json +0 -26
  141. package/tsconfig.tsbuildinfo +0 -1
  142. package/vitest.config.ts +0 -28
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Logger utility for SDK
3
+ *
4
+ * Provides structured console logging with module and context support.
5
+ * All output goes to the terminal via console methods.
6
+ */
7
+ export declare class Logger {
8
+ private module;
9
+ private context;
10
+ constructor(module: string, context?: string);
11
+ private getSource;
12
+ private formatMainMessage;
13
+ info(message: string, extra?: unknown): void;
14
+ error(messageOrError: string | Error | unknown, extra?: unknown): void;
15
+ debug(message: string, extra?: unknown): void;
16
+ warn(message: string, extra?: unknown): void;
17
+ withContext(newContext: string): Logger;
18
+ forMethod(methodName: string): Logger;
19
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Logger utility for SDK
3
+ *
4
+ * Provides structured console logging with module and context support.
5
+ * All output goes to the terminal via console methods.
6
+ */
7
+ export class Logger {
8
+ constructor(module, context = '') {
9
+ Object.defineProperty(this, "module", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: void 0
14
+ });
15
+ Object.defineProperty(this, "context", {
16
+ enumerable: true,
17
+ configurable: true,
18
+ writable: true,
19
+ value: void 0
20
+ });
21
+ this.module = module;
22
+ this.context = context;
23
+ }
24
+ getSource() {
25
+ return this.context ? `${this.module}:${this.context}` : this.module;
26
+ }
27
+ formatMainMessage(message) {
28
+ const source = this.getSource();
29
+ return `[${source}] ${message}`;
30
+ }
31
+ info(message, extra) {
32
+ const main = this.formatMainMessage(message);
33
+ if (extra !== undefined) {
34
+ console.log(main, extra);
35
+ }
36
+ else {
37
+ console.log(main);
38
+ }
39
+ }
40
+ error(messageOrError, extra) {
41
+ const source = this.getSource();
42
+ if (messageOrError instanceof Error) {
43
+ const main = `[${source}] ${messageOrError.message}`;
44
+ console.error(main, messageOrError, extra);
45
+ }
46
+ else {
47
+ const message = typeof messageOrError === 'string'
48
+ ? messageOrError
49
+ : messageOrError instanceof Error
50
+ ? messageOrError.message
51
+ : JSON.stringify(messageOrError);
52
+ const main = `[${source}] ${message}`;
53
+ if (extra !== undefined) {
54
+ console.error(main, extra);
55
+ }
56
+ else {
57
+ console.error(main);
58
+ }
59
+ }
60
+ }
61
+ debug(message, extra) {
62
+ const main = this.formatMainMessage(message);
63
+ if (extra !== undefined) {
64
+ console.debug(main, extra);
65
+ }
66
+ else {
67
+ console.debug(main);
68
+ }
69
+ }
70
+ warn(message, extra) {
71
+ const main = this.formatMainMessage(message);
72
+ if (extra !== undefined) {
73
+ console.warn(main, extra);
74
+ }
75
+ else {
76
+ console.warn(main);
77
+ }
78
+ }
79
+ // Chainable context builder
80
+ withContext(newContext) {
81
+ const fullContext = this.context
82
+ ? `${this.context}:${newContext}`
83
+ : newContext;
84
+ return new Logger(this.module, fullContext);
85
+ }
86
+ forMethod(methodName) {
87
+ return this.withContext(methodName);
88
+ }
89
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Message Serialization Utilities
3
+ *
4
+ * Functions for serializing and deserializing messages for the protocol.
5
+ * Supports regular text messages, replies, forwards, and keep-alive messages.
6
+ */
7
+ import { MessageType } from '../db';
8
+ export declare const MESSAGE_TYPE_KEEP_ALIVE = 3;
9
+ export interface DeserializedMessage {
10
+ content: string;
11
+ replyTo?: {
12
+ originalContent: string;
13
+ originalSeeker: Uint8Array;
14
+ };
15
+ forwardOf?: {
16
+ originalContent: string;
17
+ originalSeeker: Uint8Array;
18
+ };
19
+ type: MessageType;
20
+ }
21
+ /**
22
+ * Serialize a keep-alive message
23
+ * Keep-alive messages are used to maintain session activity
24
+ */
25
+ export declare function serializeKeepAliveMessage(): Uint8Array;
26
+ /**
27
+ * Serialize a regular text message
28
+ *
29
+ * Format: [type: 1 byte][content: variable]
30
+ *
31
+ * @param content - The message content string
32
+ * @returns Serialized message bytes
33
+ */
34
+ export declare function serializeRegularMessage(content: string): Uint8Array;
35
+ /**
36
+ * Serialize a reply message
37
+ *
38
+ * Format: [type: 1 byte][originalContentLen: 4 bytes][originalContent][seeker: 34 bytes][newContent]
39
+ *
40
+ * @param newContent - The reply content
41
+ * @param originalContent - The content being replied to
42
+ * @param originalSeeker - The seeker of the original message
43
+ * @returns Serialized reply message bytes
44
+ */
45
+ export declare function serializeReplyMessage(newContent: string, originalContent: string, originalSeeker: Uint8Array): Uint8Array;
46
+ /**
47
+ * Serialize a forward message
48
+ *
49
+ * Format: [type: 1 byte][forwardContentLen: 4 bytes][forwardContent][seeker: 34 bytes][newContent]
50
+ *
51
+ * @param forwardContent - The content being forwarded
52
+ * @param newContent - Optional new content to add (empty string if none)
53
+ * @param originalSeeker - The seeker of the original message
54
+ * @returns Serialized forward message bytes
55
+ */
56
+ export declare function serializeForwardMessage(forwardContent: string, newContent: string, originalSeeker: Uint8Array): Uint8Array;
57
+ /**
58
+ * Deserialize a message from bytes
59
+ *
60
+ * @param buffer - The serialized message bytes
61
+ * @returns Deserialized message object
62
+ * @throws Error if message format is invalid
63
+ */
64
+ export declare function deserializeMessage(buffer: Uint8Array): DeserializedMessage;
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Message Serialization Utilities
3
+ *
4
+ * Functions for serializing and deserializing messages for the protocol.
5
+ * Supports regular text messages, replies, forwards, and keep-alive messages.
6
+ */
7
+ import { strToBytes, bytesToStr, U32 } from '@massalabs/massa-web3';
8
+ import { MessageType } from '../db';
9
+ // Message type constants (protocol-level)
10
+ const MESSAGE_TYPE_REGULAR = 0x00;
11
+ const MESSAGE_TYPE_REPLY = 0x01;
12
+ const MESSAGE_TYPE_FORWARD = 0x02;
13
+ export const MESSAGE_TYPE_KEEP_ALIVE = 0x03;
14
+ // Seeker size: 1 byte length prefix + 32 bytes hash + 1 byte key index
15
+ const SEEKER_SIZE = 34;
16
+ /**
17
+ * Serialize a keep-alive message
18
+ * Keep-alive messages are used to maintain session activity
19
+ */
20
+ export function serializeKeepAliveMessage() {
21
+ return new Uint8Array([MESSAGE_TYPE_KEEP_ALIVE]);
22
+ }
23
+ /**
24
+ * Serialize a regular text message
25
+ *
26
+ * Format: [type: 1 byte][content: variable]
27
+ *
28
+ * @param content - The message content string
29
+ * @returns Serialized message bytes
30
+ */
31
+ export function serializeRegularMessage(content) {
32
+ const contentBytes = strToBytes(content);
33
+ const result = new Uint8Array(1 + contentBytes.length);
34
+ result[0] = MESSAGE_TYPE_REGULAR;
35
+ result.set(contentBytes, 1);
36
+ return result;
37
+ }
38
+ /**
39
+ * Serialize a reply message
40
+ *
41
+ * Format: [type: 1 byte][originalContentLen: 4 bytes][originalContent][seeker: 34 bytes][newContent]
42
+ *
43
+ * @param newContent - The reply content
44
+ * @param originalContent - The content being replied to
45
+ * @param originalSeeker - The seeker of the original message
46
+ * @returns Serialized reply message bytes
47
+ */
48
+ export function serializeReplyMessage(newContent, originalContent, originalSeeker) {
49
+ const newContentBytes = strToBytes(newContent);
50
+ const originalContentBytes = strToBytes(originalContent);
51
+ const originalContentLenBytes = U32.toBytes(BigInt(originalContentBytes.length));
52
+ // Calculate total size
53
+ const totalSize = 1 + // type
54
+ originalContentLenBytes.length + // length prefix (4 bytes)
55
+ originalContentBytes.length + // original content
56
+ SEEKER_SIZE + // seeker
57
+ newContentBytes.length; // new content
58
+ const result = new Uint8Array(totalSize);
59
+ let offset = 0;
60
+ // Type byte
61
+ result[offset++] = MESSAGE_TYPE_REPLY;
62
+ // Original content length (4 bytes)
63
+ result.set(originalContentLenBytes, offset);
64
+ offset += originalContentLenBytes.length;
65
+ // Original content
66
+ result.set(originalContentBytes, offset);
67
+ offset += originalContentBytes.length;
68
+ // Seeker (34 bytes)
69
+ result.set(originalSeeker, offset);
70
+ offset += SEEKER_SIZE;
71
+ // New content
72
+ result.set(newContentBytes, offset);
73
+ return result;
74
+ }
75
+ /**
76
+ * Serialize a forward message
77
+ *
78
+ * Format: [type: 1 byte][forwardContentLen: 4 bytes][forwardContent][seeker: 34 bytes][newContent]
79
+ *
80
+ * @param forwardContent - The content being forwarded
81
+ * @param newContent - Optional new content to add (empty string if none)
82
+ * @param originalSeeker - The seeker of the original message
83
+ * @returns Serialized forward message bytes
84
+ */
85
+ export function serializeForwardMessage(forwardContent, newContent, originalSeeker) {
86
+ const newContentBytes = strToBytes(newContent);
87
+ const forwardContentBytes = strToBytes(forwardContent);
88
+ const forwardContentLenBytes = U32.toBytes(BigInt(forwardContentBytes.length));
89
+ // Calculate total size
90
+ const totalSize = 1 + // type
91
+ forwardContentLenBytes.length + // length prefix (4 bytes)
92
+ forwardContentBytes.length + // forward content
93
+ SEEKER_SIZE + // seeker
94
+ newContentBytes.length; // new content
95
+ const result = new Uint8Array(totalSize);
96
+ let offset = 0;
97
+ // Type byte
98
+ result[offset++] = MESSAGE_TYPE_FORWARD;
99
+ // Forward content length (4 bytes)
100
+ result.set(forwardContentLenBytes, offset);
101
+ offset += forwardContentLenBytes.length;
102
+ // Forward content
103
+ result.set(forwardContentBytes, offset);
104
+ offset += forwardContentBytes.length;
105
+ // Seeker (34 bytes)
106
+ result.set(originalSeeker, offset);
107
+ offset += SEEKER_SIZE;
108
+ // New content
109
+ result.set(newContentBytes, offset);
110
+ return result;
111
+ }
112
+ /**
113
+ * Deserialize a message from bytes
114
+ *
115
+ * @param buffer - The serialized message bytes
116
+ * @returns Deserialized message object
117
+ * @throws Error if message format is invalid
118
+ */
119
+ export function deserializeMessage(buffer) {
120
+ if (buffer.length < 1) {
121
+ throw new Error('Empty message buffer');
122
+ }
123
+ const messageType = buffer[0];
124
+ switch (messageType) {
125
+ case MESSAGE_TYPE_KEEP_ALIVE:
126
+ return {
127
+ content: '',
128
+ type: MessageType.KEEP_ALIVE,
129
+ };
130
+ case MESSAGE_TYPE_REGULAR:
131
+ return {
132
+ content: bytesToStr(buffer.slice(1)),
133
+ type: MessageType.TEXT,
134
+ };
135
+ case MESSAGE_TYPE_REPLY: {
136
+ // Format: [type: 1][originalContentLen: 4][originalContent][seeker: 34][newContent]
137
+ let offset = 1;
138
+ // Read original content length (4 bytes)
139
+ const originalContentLen = Number(U32.fromBytes(buffer.slice(offset, offset + 4)));
140
+ offset += 4;
141
+ // Read original content
142
+ const originalContent = bytesToStr(buffer.slice(offset, offset + originalContentLen));
143
+ offset += originalContentLen;
144
+ // Read seeker (34 bytes)
145
+ const originalSeeker = buffer.slice(offset, offset + SEEKER_SIZE);
146
+ offset += SEEKER_SIZE;
147
+ // Read new content (rest of buffer)
148
+ const content = bytesToStr(buffer.slice(offset));
149
+ return {
150
+ content,
151
+ replyTo: {
152
+ originalContent,
153
+ originalSeeker,
154
+ },
155
+ type: MessageType.TEXT,
156
+ };
157
+ }
158
+ case MESSAGE_TYPE_FORWARD: {
159
+ // Format: [type: 1][forwardContentLen: 4][forwardContent][seeker: 34][newContent]
160
+ let offset = 1;
161
+ // Read forward content length (4 bytes)
162
+ const forwardContentLen = Number(U32.fromBytes(buffer.slice(offset, offset + 4)));
163
+ offset += 4;
164
+ // Read forward content
165
+ const originalContent = bytesToStr(buffer.slice(offset, offset + forwardContentLen));
166
+ offset += forwardContentLen;
167
+ // Read seeker (34 bytes)
168
+ const originalSeeker = buffer.slice(offset, offset + SEEKER_SIZE);
169
+ offset += SEEKER_SIZE;
170
+ // Read new content (rest of buffer)
171
+ const content = bytesToStr(buffer.slice(offset));
172
+ return {
173
+ content,
174
+ forwardOf: {
175
+ originalContent,
176
+ originalSeeker,
177
+ },
178
+ type: MessageType.TEXT,
179
+ };
180
+ }
181
+ default:
182
+ throw new Error(`Unknown message type: ${messageType}`);
183
+ }
184
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Promise Queue
3
+ *
4
+ * Ensures async operations are executed sequentially.
5
+ * Used to serialize session manager operations per contact.
6
+ */
7
+ /**
8
+ * A simple promise queue that executes tasks sequentially.
9
+ * Tasks are processed in FIFO order.
10
+ */
11
+ export declare class PromiseQueue {
12
+ private queue;
13
+ private processing;
14
+ /**
15
+ * Add a task to the queue. Returns a promise that resolves
16
+ * when the task completes.
17
+ */
18
+ enqueue<T>(fn: () => Promise<T>): Promise<T>;
19
+ /**
20
+ * Process the next task in the queue.
21
+ */
22
+ private processNext;
23
+ /**
24
+ * Check if the queue is currently processing.
25
+ */
26
+ get isProcessing(): boolean;
27
+ /**
28
+ * Get the number of pending tasks.
29
+ */
30
+ get pendingCount(): number;
31
+ }
32
+ /**
33
+ * Manages multiple queues keyed by string (e.g., contact ID).
34
+ * Creates queues lazily on first use.
35
+ */
36
+ export declare class QueueManager {
37
+ private queues;
38
+ /**
39
+ * Get or create a queue for the given key.
40
+ */
41
+ getQueue(key: string): PromiseQueue;
42
+ /**
43
+ * Enqueue a task for a specific key.
44
+ */
45
+ enqueue<T>(key: string, fn: () => Promise<T>): Promise<T>;
46
+ /**
47
+ * Clear all queues.
48
+ */
49
+ clear(): void;
50
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Promise Queue
3
+ *
4
+ * Ensures async operations are executed sequentially.
5
+ * Used to serialize session manager operations per contact.
6
+ */
7
+ /**
8
+ * A simple promise queue that executes tasks sequentially.
9
+ * Tasks are processed in FIFO order.
10
+ */
11
+ export class PromiseQueue {
12
+ constructor() {
13
+ Object.defineProperty(this, "queue", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: []
18
+ });
19
+ Object.defineProperty(this, "processing", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: false
24
+ });
25
+ }
26
+ /**
27
+ * Add a task to the queue. Returns a promise that resolves
28
+ * when the task completes.
29
+ */
30
+ enqueue(fn) {
31
+ return new Promise((resolve, reject) => {
32
+ this.queue.push({
33
+ fn: fn,
34
+ resolve: resolve,
35
+ reject,
36
+ });
37
+ this.processNext();
38
+ });
39
+ }
40
+ /**
41
+ * Process the next task in the queue.
42
+ */
43
+ async processNext() {
44
+ if (this.processing || this.queue.length === 0) {
45
+ return;
46
+ }
47
+ this.processing = true;
48
+ const task = this.queue.shift();
49
+ try {
50
+ const result = await task.fn();
51
+ task.resolve(result);
52
+ }
53
+ catch (error) {
54
+ task.reject(error);
55
+ }
56
+ finally {
57
+ this.processing = false;
58
+ this.processNext();
59
+ }
60
+ }
61
+ /**
62
+ * Check if the queue is currently processing.
63
+ */
64
+ get isProcessing() {
65
+ return this.processing;
66
+ }
67
+ /**
68
+ * Get the number of pending tasks.
69
+ */
70
+ get pendingCount() {
71
+ return this.queue.length;
72
+ }
73
+ }
74
+ /**
75
+ * Manages multiple queues keyed by string (e.g., contact ID).
76
+ * Creates queues lazily on first use.
77
+ */
78
+ export class QueueManager {
79
+ constructor() {
80
+ Object.defineProperty(this, "queues", {
81
+ enumerable: true,
82
+ configurable: true,
83
+ writable: true,
84
+ value: new Map()
85
+ });
86
+ }
87
+ /**
88
+ * Get or create a queue for the given key.
89
+ */
90
+ getQueue(key) {
91
+ let queue = this.queues.get(key);
92
+ if (!queue) {
93
+ queue = new PromiseQueue();
94
+ this.queues.set(key, queue);
95
+ }
96
+ return queue;
97
+ }
98
+ /**
99
+ * Enqueue a task for a specific key.
100
+ */
101
+ enqueue(key, fn) {
102
+ return this.getQueue(key).enqueue(fn);
103
+ }
104
+ /**
105
+ * Clear all queues.
106
+ */
107
+ clear() {
108
+ this.queues.clear();
109
+ }
110
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Common type utilities for the SDK
3
+ */
4
+ export type Result<T, E = Error> = {
5
+ success: true;
6
+ data: T;
7
+ } | {
8
+ success: false;
9
+ error: E;
10
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Common type utilities for the SDK
3
+ */
4
+ export {};
@@ -0,0 +1,40 @@
1
+ /**
2
+ * User ID encoding/decoding utilities using Bech32 format
3
+ * Format: gossip1<encoded-32-bytes>
4
+ *
5
+ * Uses @scure/base for reliable, battle-tested Bech32 encoding
6
+ */
7
+ /**
8
+ * Encode a 32-byte user ID to Bech32 format with "gossip" prefix
9
+ * @param userId - 32-byte user ID as Uint8Array
10
+ * @returns Bech32-encoded string (e.g., "gossip1qpzry9x8gf2tvdw0s3jn54khce6mua7l...")
11
+ * @throws Error if userId is not exactly 32 bytes
12
+ */
13
+ export declare function encodeUserId(userId: Uint8Array): string;
14
+ /**
15
+ * Decode a Bech32-encoded user ID back to 32 bytes
16
+ * @param encoded - Bech32-encoded string (e.g., "gossip1qpzry9x8gf2tvdw0s3jn54khce6mua7l...")
17
+ * @returns 32-byte user ID as Uint8Array
18
+ * @throws Error if the format is invalid, checksum fails, or decoded length is not 32 bytes
19
+ */
20
+ export declare function decodeUserId(encoded: string): Uint8Array;
21
+ /**
22
+ * Validate a Bech32-encoded user ID string
23
+ * @param encoded - Bech32-encoded string to validate
24
+ * @returns true if valid, false otherwise
25
+ */
26
+ export declare function isValidUserId(encoded: string): boolean;
27
+ /**
28
+ * Format a user ID for display (shortened version)
29
+ * @param userId - Bech32-encoded user ID string
30
+ * @param prefixChars - Number of characters to show after prefix (default: 8)
31
+ * @param suffixChars - Number of characters to show at end (default: 6)
32
+ * @returns Formatted string (e.g., "gossip1qpzry9x8...mua7l")
33
+ */
34
+ export declare function formatUserId(userId: string, prefixChars?: number, suffixChars?: number): string;
35
+ /**
36
+ * Generates a random 32-byte user ID
37
+ * @param password - Optional password
38
+ * @returns gossip Bech32 string representing a 32-byte user ID
39
+ */
40
+ export declare function generate(password?: string): Promise<string>;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * User ID encoding/decoding utilities using Bech32 format
3
+ * Format: gossip1<encoded-32-bytes>
4
+ *
5
+ * Uses @scure/base for reliable, battle-tested Bech32 encoding
6
+ */
7
+ import { bech32 } from '@scure/base';
8
+ import { generateUserKeys } from '../wasm';
9
+ const GOSSIP_PREFIX = 'gossip';
10
+ const USER_ID_BYTE_LENGTH = 32;
11
+ /**
12
+ * Encode a 32-byte user ID to Bech32 format with "gossip" prefix
13
+ * @param userId - 32-byte user ID as Uint8Array
14
+ * @returns Bech32-encoded string (e.g., "gossip1qpzry9x8gf2tvdw0s3jn54khce6mua7l...")
15
+ * @throws Error if userId is not exactly 32 bytes
16
+ */
17
+ export function encodeUserId(userId) {
18
+ if (userId.length !== USER_ID_BYTE_LENGTH) {
19
+ throw new Error(`User ID must be exactly ${USER_ID_BYTE_LENGTH} bytes, got ${userId.length}`);
20
+ }
21
+ return bech32.encode(GOSSIP_PREFIX, bech32.toWords(userId));
22
+ }
23
+ /**
24
+ * Decode a Bech32-encoded user ID back to 32 bytes
25
+ * @param encoded - Bech32-encoded string (e.g., "gossip1qpzry9x8gf2tvdw0s3jn54khce6mua7l...")
26
+ * @returns 32-byte user ID as Uint8Array
27
+ * @throws Error if the format is invalid, checksum fails, or decoded length is not 32 bytes
28
+ */
29
+ export function decodeUserId(encoded) {
30
+ // Type assertion needed as bech32.decode expects a template literal type
31
+ const { prefix, words } = bech32.decode(encoded, 90);
32
+ // Verify prefix
33
+ if (prefix !== GOSSIP_PREFIX) {
34
+ throw new Error(`Invalid prefix: expected "${GOSSIP_PREFIX}", got "${prefix}"`);
35
+ }
36
+ // Convert from 5-bit words back to bytes
37
+ const decoded = bech32.fromWords(words);
38
+ // Verify length
39
+ if (decoded.length !== USER_ID_BYTE_LENGTH) {
40
+ throw new Error(`Decoded user ID must be ${USER_ID_BYTE_LENGTH} bytes, got ${decoded.length}`);
41
+ }
42
+ return new Uint8Array(decoded);
43
+ }
44
+ /**
45
+ * Validate a Bech32-encoded user ID string
46
+ * @param encoded - Bech32-encoded string to validate
47
+ * @returns true if valid, false otherwise
48
+ */
49
+ export function isValidUserId(encoded) {
50
+ try {
51
+ decodeUserId(encoded);
52
+ return true;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ /**
59
+ * Format a user ID for display (shortened version)
60
+ * @param userId - Bech32-encoded user ID string
61
+ * @param prefixChars - Number of characters to show after prefix (default: 8)
62
+ * @param suffixChars - Number of characters to show at end (default: 6)
63
+ * @returns Formatted string (e.g., "gossip1qpzry9x8...mua7l")
64
+ */
65
+ export function formatUserId(userId, prefixChars = 8, suffixChars = 6) {
66
+ if (!userId)
67
+ return '';
68
+ // Find separator position
69
+ const sepPos = userId.indexOf('1');
70
+ if (sepPos === -1)
71
+ return userId;
72
+ const prefix = userId.substring(0, sepPos + 1); // "gossip1"
73
+ const data = userId.substring(sepPos + 1); // rest of the string
74
+ if (data.length <= prefixChars + suffixChars) {
75
+ return userId; // Too short to format
76
+ }
77
+ const start = data.slice(0, prefixChars);
78
+ const end = data.slice(-suffixChars);
79
+ return `${prefix}${start}...${end}`;
80
+ }
81
+ /**
82
+ * Generates a random 32-byte user ID
83
+ * @param password - Optional password
84
+ * @returns gossip Bech32 string representing a 32-byte user ID
85
+ */
86
+ export async function generate(password) {
87
+ const identity = await generateUserKeys(password || '');
88
+ const userId = identity.public_keys().derive_id();
89
+ return encodeUserId(userId);
90
+ }