@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,59 @@
1
+ /**
2
+ * SDK Event Emitter
3
+ *
4
+ * Type-safe event emitter for SDK events.
5
+ */
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Event Emitter Class
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+ export class SdkEventEmitter {
10
+ constructor() {
11
+ Object.defineProperty(this, "handlers", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: {
16
+ message: new Set(),
17
+ messageSent: new Set(),
18
+ messageFailed: new Set(),
19
+ discussionRequest: new Set(),
20
+ discussionStatusChanged: new Set(),
21
+ sessionBroken: new Set(),
22
+ sessionRenewed: new Set(),
23
+ error: new Set(),
24
+ }
25
+ });
26
+ }
27
+ /**
28
+ * Register an event handler
29
+ */
30
+ on(event, handler) {
31
+ this.handlers[event].add(handler);
32
+ }
33
+ /**
34
+ * Remove an event handler
35
+ */
36
+ off(event, handler) {
37
+ this.handlers[event].delete(handler);
38
+ }
39
+ /**
40
+ * Emit an event to all registered handlers
41
+ */
42
+ emit(event, ...args) {
43
+ const handlers = this.handlers[event];
44
+ handlers.forEach(handler => {
45
+ try {
46
+ handler(...args);
47
+ }
48
+ catch (error) {
49
+ console.error(`[SdkEventEmitter] Error in ${event} handler:`, error);
50
+ }
51
+ });
52
+ }
53
+ /**
54
+ * Remove all handlers for all events
55
+ */
56
+ clear() {
57
+ Object.values(this.handlers).forEach(set => set.clear());
58
+ }
59
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * SDK Polling Manager
3
+ *
4
+ * Manages polling timers for messages, announcements, and session refresh.
5
+ */
6
+ import type { SdkConfig } from '../config/sdk';
7
+ import type { Discussion } from '../db';
8
+ export interface PollingCallbacks {
9
+ /** Fetch messages from protocol */
10
+ fetchMessages: () => Promise<void>;
11
+ /** Fetch and process announcements */
12
+ fetchAnnouncements: () => Promise<void>;
13
+ /** Handle session refresh for active discussions */
14
+ handleSessionRefresh: (discussions: Discussion[]) => Promise<void>;
15
+ /** Get active discussions for session refresh */
16
+ getActiveDiscussions: () => Promise<Discussion[]>;
17
+ /** Called when a polling error occurs */
18
+ onError: (error: Error, context: string) => void;
19
+ }
20
+ export declare class SdkPolling {
21
+ private timers;
22
+ private callbacks;
23
+ /**
24
+ * Start polling with the given configuration and callbacks.
25
+ */
26
+ start(config: SdkConfig, callbacks: PollingCallbacks): void;
27
+ /**
28
+ * Stop all polling timers.
29
+ */
30
+ stop(): void;
31
+ /**
32
+ * Check if polling is currently running.
33
+ */
34
+ isRunning(): boolean;
35
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * SDK Polling Manager
3
+ *
4
+ * Manages polling timers for messages, announcements, and session refresh.
5
+ */
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Polling Manager Class
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+ export class SdkPolling {
10
+ constructor() {
11
+ Object.defineProperty(this, "timers", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: {
16
+ messages: null,
17
+ announcements: null,
18
+ sessionRefresh: null,
19
+ }
20
+ });
21
+ Object.defineProperty(this, "callbacks", {
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true,
25
+ value: null
26
+ });
27
+ }
28
+ /**
29
+ * Start polling with the given configuration and callbacks.
30
+ */
31
+ start(config, callbacks) {
32
+ // Stop any existing timers first
33
+ this.stop();
34
+ this.callbacks = callbacks;
35
+ console.log('[SdkPolling] Starting polling', {
36
+ messagesIntervalMs: config.polling.messagesIntervalMs,
37
+ announcementsIntervalMs: config.polling.announcementsIntervalMs,
38
+ sessionRefreshIntervalMs: config.polling.sessionRefreshIntervalMs,
39
+ });
40
+ // Start message polling
41
+ this.timers.messages = setInterval(async () => {
42
+ try {
43
+ await this.callbacks?.fetchMessages();
44
+ }
45
+ catch (error) {
46
+ console.error('[SdkPolling] Message polling error:', error);
47
+ this.callbacks?.onError(error instanceof Error ? error : new Error(String(error)), 'message_polling');
48
+ }
49
+ }, config.polling.messagesIntervalMs);
50
+ // Start announcement polling
51
+ this.timers.announcements = setInterval(async () => {
52
+ try {
53
+ await this.callbacks?.fetchAnnouncements();
54
+ }
55
+ catch (error) {
56
+ console.error('[SdkPolling] Announcement polling error:', error);
57
+ this.callbacks?.onError(error instanceof Error ? error : new Error(String(error)), 'announcement_polling');
58
+ }
59
+ }, config.polling.announcementsIntervalMs);
60
+ // Start session refresh polling
61
+ this.timers.sessionRefresh = setInterval(async () => {
62
+ try {
63
+ const discussions = await this.callbacks?.getActiveDiscussions();
64
+ if (discussions && discussions.length > 0) {
65
+ await this.callbacks?.handleSessionRefresh(discussions);
66
+ }
67
+ }
68
+ catch (error) {
69
+ console.error('[SdkPolling] Session refresh polling error:', error);
70
+ this.callbacks?.onError(error instanceof Error ? error : new Error(String(error)), 'session_refresh_polling');
71
+ }
72
+ }, config.polling.sessionRefreshIntervalMs);
73
+ }
74
+ /**
75
+ * Stop all polling timers.
76
+ */
77
+ stop() {
78
+ if (this.timers.messages) {
79
+ clearInterval(this.timers.messages);
80
+ this.timers.messages = null;
81
+ }
82
+ if (this.timers.announcements) {
83
+ clearInterval(this.timers.announcements);
84
+ this.timers.announcements = null;
85
+ }
86
+ if (this.timers.sessionRefresh) {
87
+ clearInterval(this.timers.sessionRefresh);
88
+ this.timers.sessionRefresh = null;
89
+ }
90
+ this.callbacks = null;
91
+ }
92
+ /**
93
+ * Check if polling is currently running.
94
+ */
95
+ isRunning() {
96
+ return (this.timers.messages !== null ||
97
+ this.timers.announcements !== null ||
98
+ this.timers.sessionRefresh !== null);
99
+ }
100
+ }
@@ -1,9 +1,7 @@
1
1
  /**
2
2
  * Core SDK components
3
3
  */
4
-
5
4
  export { SdkEventEmitter } from './SdkEventEmitter';
6
5
  export type { SdkEventType, SdkEventHandlers } from './SdkEventEmitter';
7
-
8
6
  export { SdkPolling } from './SdkPolling';
9
7
  export type { PollingCallbacks } from './SdkPolling';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core SDK components
3
+ */
4
+ export { SdkEventEmitter } from './SdkEventEmitter';
5
+ export { SdkPolling } from './SdkPolling';
@@ -0,0 +1,34 @@
1
+ /**
2
+ * BIP39 utilities for mnemonic generation, validation, and seed derivation
3
+ * Using @scure/bip39 for browser compatibility
4
+ */
5
+ import { Account } from '@massalabs/massa-web3';
6
+ export declare const PRIVATE_KEY_VERSION = 0;
7
+ /**
8
+ * Generate a new BIP39 mnemonic phrase
9
+ * @param strength - Entropy strength in bits (128, 160, 192, 224, 256)
10
+ * @returns Generated mnemonic phrase
11
+ */
12
+ export declare function generateMnemonic(strength?: number): string;
13
+ /**
14
+ * Validate a BIP39 mnemonic phrase
15
+ * @param mnemonic - The mnemonic phrase to validate
16
+ * @returns True if valid, false otherwise
17
+ */
18
+ export declare function validateMnemonic(mnemonic: string): boolean;
19
+ /**
20
+ * Generate a seed from mnemonic and optional passphrase
21
+ * @param mnemonic - The BIP39 mnemonic phrase
22
+ * @param passphrase - Optional passphrase (empty string if not provided)
23
+ * @returns Uint8Array seed
24
+ */
25
+ export declare function mnemonicToSeed(mnemonic: string, passphrase?: string): Uint8Array;
26
+ /**
27
+ * Create a Massa blockchain account from a mnemonic phrase
28
+ *
29
+ * @param mnemonic - The BIP39 mnemonic phrase
30
+ * @param passphrase - Optional passphrase for additional security
31
+ * @returns Massa Account object
32
+ * @throws Error if mnemonic is invalid
33
+ */
34
+ export declare function accountFromMnemonic(mnemonic: string, passphrase?: string): Promise<Account>;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * BIP39 utilities for mnemonic generation, validation, and seed derivation
3
+ * Using @scure/bip39 for browser compatibility
4
+ */
5
+ import { generateMnemonic as generateMnemonicScure, mnemonicToSeedSync, validateMnemonic as validateMnemonicScure, } from '@scure/bip39';
6
+ import { wordlist } from '@scure/bip39/wordlists/english.js';
7
+ import { Account, PrivateKey } from '@massalabs/massa-web3';
8
+ import varint from 'varint';
9
+ export const PRIVATE_KEY_VERSION = 0;
10
+ /**
11
+ * Generate a new BIP39 mnemonic phrase
12
+ * @param strength - Entropy strength in bits (128, 160, 192, 224, 256)
13
+ * @returns Generated mnemonic phrase
14
+ */
15
+ export function generateMnemonic(strength = 256) {
16
+ // @scure/bip39 generateMnemonic expects strength in bits (128, 160, 192, 224, 256)
17
+ return generateMnemonicScure(wordlist, strength);
18
+ }
19
+ /**
20
+ * Validate a BIP39 mnemonic phrase
21
+ * @param mnemonic - The mnemonic phrase to validate
22
+ * @returns True if valid, false otherwise
23
+ */
24
+ export function validateMnemonic(mnemonic) {
25
+ return validateMnemonicScure(mnemonic, wordlist);
26
+ }
27
+ /**
28
+ * Generate a seed from mnemonic and optional passphrase
29
+ * @param mnemonic - The BIP39 mnemonic phrase
30
+ * @param passphrase - Optional passphrase (empty string if not provided)
31
+ * @returns Uint8Array seed
32
+ */
33
+ export function mnemonicToSeed(mnemonic, passphrase = '') {
34
+ return mnemonicToSeedSync(mnemonic, passphrase);
35
+ }
36
+ /**
37
+ * Create a Massa blockchain account from a mnemonic phrase
38
+ *
39
+ * @param mnemonic - The BIP39 mnemonic phrase
40
+ * @param passphrase - Optional passphrase for additional security
41
+ * @returns Massa Account object
42
+ * @throws Error if mnemonic is invalid
43
+ */
44
+ export async function accountFromMnemonic(mnemonic, passphrase) {
45
+ try {
46
+ if (!validateMnemonic(mnemonic)) {
47
+ throw new Error('Invalid mnemonic phrase');
48
+ }
49
+ const seed = mnemonicToSeed(mnemonic, passphrase);
50
+ const versionArray = varint.encode(PRIVATE_KEY_VERSION);
51
+ const privateKeyBytes = seed.slice(0, 32);
52
+ const privateKey = new Uint8Array([...versionArray, ...privateKeyBytes]);
53
+ const pkey = PrivateKey.fromBytes(privateKey);
54
+ const account = await Account.fromPrivateKey(pkey);
55
+ return account;
56
+ }
57
+ catch (error) {
58
+ console.error('Error in accountFromMnemonic:', error);
59
+ console.error('Error stack:', error instanceof Error ? error.stack : 'No stack');
60
+ throw error;
61
+ }
62
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * High-level encryption utilities
3
+ *
4
+ * Provides convenient wrappers for encrypting and decrypting strings
5
+ * using the WASM encryption primitives.
6
+ */
7
+ import { EncryptionKey } from '../wasm/encryption';
8
+ /**
9
+ * Encrypt a plaintext string using AES-256-SIV
10
+ *
11
+ * @param plaintext - The string to encrypt
12
+ * @param key - The encryption key (64 bytes)
13
+ * @param salt - Optional salt/nonce bytes (will generate random if not provided)
14
+ * @returns Object containing encrypted data and nonce bytes
15
+ */
16
+ export declare function encrypt(plaintext: string, key: EncryptionKey, salt?: Uint8Array): Promise<{
17
+ encryptedData: Uint8Array;
18
+ nonce: Uint8Array;
19
+ }>;
20
+ /**
21
+ * Decrypt encrypted data back to a string
22
+ *
23
+ * @param encryptedData - The encrypted data bytes
24
+ * @param salt - The nonce/salt used during encryption
25
+ * @param key - The encryption key (must match encryption key)
26
+ * @returns The decrypted plaintext string
27
+ * @throws Error if decryption fails (wrong key, corrupted data, etc.)
28
+ */
29
+ export declare function decrypt(encryptedData: Uint8Array, salt: Uint8Array, key: EncryptionKey): Promise<string>;
30
+ /**
31
+ * Derive an encryption key from a seed string and nonce
32
+ *
33
+ * @param seedString - The seed string (e.g., password)
34
+ * @param nonce - The nonce/salt for key derivation
35
+ * @returns The derived encryption key
36
+ */
37
+ export declare function deriveKey(seedString: string, nonce: Uint8Array): Promise<EncryptionKey>;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * High-level encryption utilities
3
+ *
4
+ * Provides convenient wrappers for encrypting and decrypting strings
5
+ * using the WASM encryption primitives.
6
+ */
7
+ import { decryptAead, encryptAead, EncryptionKey, generateNonce, Nonce, } from '../wasm/encryption';
8
+ /**
9
+ * Encrypt a plaintext string using AES-256-SIV
10
+ *
11
+ * @param plaintext - The string to encrypt
12
+ * @param key - The encryption key (64 bytes)
13
+ * @param salt - Optional salt/nonce bytes (will generate random if not provided)
14
+ * @returns Object containing encrypted data and nonce bytes
15
+ */
16
+ export async function encrypt(plaintext, key, salt) {
17
+ const nonce = salt ? Nonce.from_bytes(salt) : await generateNonce();
18
+ const encryptedData = await encryptAead(key, nonce, new TextEncoder().encode(plaintext), new Uint8Array());
19
+ return { encryptedData, nonce: nonce.to_bytes() };
20
+ }
21
+ /**
22
+ * Decrypt encrypted data back to a string
23
+ *
24
+ * @param encryptedData - The encrypted data bytes
25
+ * @param salt - The nonce/salt used during encryption
26
+ * @param key - The encryption key (must match encryption key)
27
+ * @returns The decrypted plaintext string
28
+ * @throws Error if decryption fails (wrong key, corrupted data, etc.)
29
+ */
30
+ export async function decrypt(encryptedData, salt, key) {
31
+ const plain = await decryptAead(key, Nonce.from_bytes(salt), encryptedData, new Uint8Array());
32
+ if (!plain) {
33
+ throw new Error('Failed to decrypt data');
34
+ }
35
+ return new TextDecoder().decode(plain);
36
+ }
37
+ /**
38
+ * Derive an encryption key from a seed string and nonce
39
+ *
40
+ * @param seedString - The seed string (e.g., password)
41
+ * @param nonce - The nonce/salt for key derivation
42
+ * @returns The derived encryption key
43
+ */
44
+ export async function deriveKey(seedString, nonce) {
45
+ return await EncryptionKey.from_seed(seedString, nonce);
46
+ }
package/dist/db.d.ts ADDED
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Gossip Database
3
+ *
4
+ * IndexedDB database implementation using Dexie for the Gossip messenger.
5
+ * Provides tables for contacts, messages, discussions, user profiles, and more.
6
+ */
7
+ import Dexie, { Table } from 'dexie';
8
+ export type AuthMethod = 'capacitor' | 'webauthn' | 'password';
9
+ export interface Contact {
10
+ id?: number;
11
+ ownerUserId: string;
12
+ userId: string;
13
+ name: string;
14
+ avatar?: string;
15
+ publicKeys: Uint8Array;
16
+ isOnline: boolean;
17
+ lastSeen: Date;
18
+ createdAt: Date;
19
+ }
20
+ export interface Message {
21
+ id?: number;
22
+ ownerUserId: string;
23
+ contactUserId: string;
24
+ content: string;
25
+ serializedContent?: Uint8Array;
26
+ type: MessageType;
27
+ direction: MessageDirection;
28
+ status: MessageStatus;
29
+ timestamp: Date;
30
+ metadata?: Record<string, unknown>;
31
+ seeker?: Uint8Array;
32
+ replyTo?: {
33
+ originalContent?: string;
34
+ originalSeeker: Uint8Array;
35
+ };
36
+ forwardOf?: {
37
+ originalContent?: string;
38
+ originalSeeker: Uint8Array;
39
+ };
40
+ encryptedMessage?: Uint8Array;
41
+ }
42
+ export interface UserProfile {
43
+ userId: string;
44
+ username: string;
45
+ avatar?: string;
46
+ security: {
47
+ encKeySalt: Uint8Array;
48
+ authMethod: AuthMethod;
49
+ webauthn?: {
50
+ credentialId?: string;
51
+ };
52
+ iCloudSync?: boolean;
53
+ mnemonicBackup: {
54
+ encryptedMnemonic: Uint8Array;
55
+ createdAt: Date;
56
+ backedUp: boolean;
57
+ };
58
+ };
59
+ session: Uint8Array;
60
+ bio?: string;
61
+ status: 'online' | 'away' | 'busy' | 'offline';
62
+ lastSeen: Date;
63
+ createdAt: Date;
64
+ updatedAt: Date;
65
+ lastPublicKeyPush?: Date;
66
+ lastBulletinCounter?: string;
67
+ }
68
+ export declare enum DiscussionStatus {
69
+ PENDING = "pending",
70
+ ACTIVE = "active",
71
+ CLOSED = "closed",// closed by the user
72
+ BROKEN = "broken",// The session is killed. Need to be reinitiated
73
+ SEND_FAILED = "sendFailed",// The discussion was initiated by the session manager but could not be broadcasted on network
74
+ RECONNECTING = "reconnecting"
75
+ }
76
+ export declare enum MessageDirection {
77
+ INCOMING = "incoming",
78
+ OUTGOING = "outgoing"
79
+ }
80
+ export declare enum MessageStatus {
81
+ WAITING_SESSION = "waiting_session",// Waiting for active session with peer
82
+ SENDING = "sending",
83
+ SENT = "sent",
84
+ DELIVERED = "delivered",
85
+ READ = "read",
86
+ FAILED = "failed"
87
+ }
88
+ export declare enum DiscussionDirection {
89
+ INITIATED = "initiated",
90
+ RECEIVED = "received"
91
+ }
92
+ export declare enum MessageType {
93
+ TEXT = "text",
94
+ KEEP_ALIVE = "keep_alive",
95
+ IMAGE = "image",
96
+ FILE = "file",
97
+ AUDIO = "audio",
98
+ VIDEO = "video"
99
+ }
100
+ export interface Discussion {
101
+ id?: number;
102
+ ownerUserId: string;
103
+ contactUserId: string;
104
+ direction: DiscussionDirection;
105
+ status: DiscussionStatus;
106
+ nextSeeker?: Uint8Array;
107
+ initiationAnnouncement?: Uint8Array;
108
+ announcementMessage?: string;
109
+ lastSyncTimestamp?: Date;
110
+ customName?: string;
111
+ lastMessageId?: number;
112
+ lastMessageContent?: string;
113
+ lastMessageTimestamp?: Date;
114
+ unreadCount: number;
115
+ createdAt: Date;
116
+ updatedAt: Date;
117
+ }
118
+ export interface PendingEncryptedMessage {
119
+ id?: number;
120
+ seeker: Uint8Array;
121
+ ciphertext: Uint8Array;
122
+ fetchedAt: Date;
123
+ }
124
+ export interface PendingAnnouncement {
125
+ id?: number;
126
+ announcement: Uint8Array;
127
+ fetchedAt: Date;
128
+ counter?: string;
129
+ }
130
+ export interface ActiveSeeker {
131
+ id?: number;
132
+ seeker: Uint8Array;
133
+ }
134
+ export declare class GossipDatabase extends Dexie {
135
+ contacts: Table<Contact>;
136
+ messages: Table<Message>;
137
+ userProfile: Table<UserProfile>;
138
+ discussions: Table<Discussion>;
139
+ pendingEncryptedMessages: Table<PendingEncryptedMessage>;
140
+ pendingAnnouncements: Table<PendingAnnouncement>;
141
+ activeSeekers: Table<ActiveSeeker>;
142
+ constructor();
143
+ /** CONTACTS */
144
+ getContactsByOwner(ownerUserId: string): Promise<Contact[]>;
145
+ getContactByOwnerAndUserId(ownerUserId: string, userId: string): Promise<Contact | undefined>;
146
+ /** DISCUSSIONS */
147
+ getDiscussionsByOwner(ownerUserId: string): Promise<Discussion[]>;
148
+ getUnreadCountByOwner(ownerUserId: string): Promise<number>;
149
+ getDiscussionByOwnerAndContact(ownerUserId: string, contactUserId: string): Promise<Discussion | undefined>;
150
+ /**
151
+ * Get all active discussions with their sync status
152
+ * @returns Array of active discussions
153
+ */
154
+ getActiveDiscussionsByOwner(ownerUserId: string): Promise<Discussion[]>;
155
+ markMessagesAsRead(ownerUserId: string, contactUserId: string): Promise<void>;
156
+ getMessagesForContactByOwner(ownerUserId: string, contactUserId: string, limit?: number): Promise<Message[]>;
157
+ addMessage(message: Omit<Message, 'id'>): Promise<number>;
158
+ /**
159
+ * Update the last sync timestamp for a discussion
160
+ * @param discussionId - The discussion ID
161
+ * @param timestamp - The sync timestamp
162
+ */
163
+ updateLastSyncTimestamp(discussionId: number, timestamp: Date): Promise<void>;
164
+ deleteDb(): Promise<void>;
165
+ /**
166
+ * Set all active seekers, replacing any existing ones
167
+ * @param seekers - Array of seeker Uint8Arrays to store
168
+ */
169
+ setActiveSeekers(seekers: Uint8Array[]): Promise<void>;
170
+ /**
171
+ * Get all active seekers from the database
172
+ * @returns Array of seeker Uint8Arrays
173
+ */
174
+ getActiveSeekers(): Promise<Uint8Array[]>;
175
+ }
176
+ /**
177
+ * Get the database instance.
178
+ * Creates a default instance if none was set via setDb().
179
+ */
180
+ export declare function getDb(): GossipDatabase;
181
+ /**
182
+ * Set the database instance.
183
+ * Call this before using any SDK functions if you need a custom db instance.
184
+ */
185
+ export declare function setDb(database: GossipDatabase): void;
186
+ /**
187
+ * Get the database instance.
188
+ * Creates a default instance if none was set via setDb().
189
+ */
190
+ export declare const db: GossipDatabase;