@massalabs/gossip-sdk 0.0.2-dev.20260223065033 → 0.0.2-dev.20260223101931

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,6 +33,11 @@ await sdk.init();
33
33
  // 2. Open session (login)
34
34
  await sdk.openSession({
35
35
  mnemonic: 'word1 word2 word3 ... word12',
36
+ // Optional: for existing session
37
+ // encryptedSession: savedBlob,
38
+ // encryptionKey, // optional - derived from mnemonic if not provided
39
+ // Optional: for persistence
40
+ // onPersist: async (blob, key) => { await saveToStorage(blob, key); },
36
41
  });
37
42
 
38
43
  // 3. Use the SDK
@@ -308,12 +313,12 @@ await sdk.init({
308
313
 
309
314
  ## Session Persistence
310
315
 
311
- For restoring sessions across app restarts:
316
+ For restoring sessions across app restarts, pass `encryptionKey` (optional — derived from mnemonic if omitted) and `onPersist` when opening the session:
312
317
 
313
318
  ```typescript
314
319
  await sdk.openSession({
315
320
  mnemonic,
316
- encryptionKey,
321
+ encryptionKey, // optional
317
322
  onPersist: async (blob, key) => {
318
323
  await storage.save({ session: blob });
319
324
  },
package/dist/gossip.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { type SdkConfig, type DeepPartial } from './config/sdk';
2
- import { SessionStatus, SessionConfig } from './assets/generated/wasm/gossip_wasm';
3
2
  import { EncryptionKey } from './wasm/encryption';
4
3
  import { type AnnouncementReceptionResult } from './services/announcement';
5
4
  import { DiscussionInitializationResult } from './services/discussion';
@@ -8,7 +7,7 @@ import { AuthService } from './services/auth';
8
7
  import type { DeleteContactResult, UpdateContactNameResult } from './utils/contacts';
9
8
  import { type ValidationResult } from './utils/validation';
10
9
  import { type Contact, type Discussion, type Message } from './db';
11
- import type { UserPublicKeys } from './wasm/bindings';
10
+ import { type UserPublicKeys, type SessionConfig, SessionStatus } from './wasm/bindings';
12
11
  import { SdkEventType, type SdkEventHandlers } from './core/SdkEventEmitter';
13
12
  import { AnnouncementPayload } from './utils/announcementPayload';
14
13
  import { Result } from './utils/type';
@@ -38,12 +37,10 @@ export interface OpenSessionOptions {
38
37
  mnemonic: string;
39
38
  /** Existing encrypted session blob (for restoring session) */
40
39
  encryptedSession?: Uint8Array;
41
- /** Encryption key for decrypting session */
40
+ /** Encryption key for decrypting session and storage. Will be created if not provided. */
42
41
  encryptionKey?: EncryptionKey;
43
42
  /** Callback when session state changes (for persistence) */
44
43
  onPersist?: (encryptedBlob: Uint8Array, encryptionKey: EncryptionKey) => Promise<void>;
45
- /** Encryption key for persisting session (required if onPersist is provided) */
46
- persistEncryptionKey?: EncryptionKey;
47
44
  /** Custom session configuration (optional, uses defaults if not provided) */
48
45
  sessionConfig?: SessionConfig;
49
46
  }
@@ -93,15 +90,7 @@ declare class GossipSdk {
93
90
  * Get encrypted session blob for persistence.
94
91
  * Throws if no session is open.
95
92
  */
96
- getEncryptedSession(encryptionKey: EncryptionKey): Uint8Array;
97
- /**
98
- * Configure session persistence after session is opened.
99
- * Use this when you need to set up persistence after account creation.
100
- *
101
- * @param encryptionKey - Key to encrypt session blob
102
- * @param onPersist - Callback to save encrypted session blob
103
- */
104
- configurePersistence(encryptionKey: EncryptionKey, onPersist: (encryptedBlob: Uint8Array, encryptionKey: EncryptionKey) => Promise<void>): void;
93
+ getEncryptedSession(): Uint8Array;
105
94
  /** Auth service (available after init, before session) */
106
95
  get auth(): AuthService;
107
96
  /** Message service */
package/dist/gossip.js CHANGED
@@ -46,6 +46,7 @@ import { defaultSdkConfig, mergeConfig, } from './config/sdk';
46
46
  import { startWasmInitialization, ensureWasmInitialized } from './wasm/loader';
47
47
  import { generateUserKeys } from './wasm/userKeys';
48
48
  import { SessionModule } from './wasm/session';
49
+ import { generateEncryptionKeyFromSeed, } from './wasm/encryption';
49
50
  import { AnnouncementService, } from './services/announcement';
50
51
  import { DiscussionService, } from './services/discussion';
51
52
  import { MessageService, rowToMessage, } from './services/message';
@@ -56,6 +57,7 @@ import { QueueManager } from './utils/queue';
56
57
  import { encodeUserId, decodeUserId } from './utils/userId';
57
58
  import { initDb, getMessageById, getMessagesByOwnerAndContact, getMessagesByStatus, updateMessageById, getDiscussionByOwnerAndContact, getDiscussionsByOwner, getContactsByOwner, getContactByOwnerAndUser, MessageStatus, } from './db';
58
59
  import { addContact, updateContactName, deleteContact } from './utils/contacts';
60
+ import { SessionManagerWrapper, } from './wasm/bindings';
59
61
  import { SdkEventEmitter, SdkEventType, } from './core/SdkEventEmitter';
60
62
  import { SdkPolling } from './core/SdkPolling';
61
63
  export { SdkEventType };
@@ -198,23 +200,23 @@ class GossipSdk {
198
200
  if (this.state.status === SdkStatus.SESSION_OPEN) {
199
201
  throw new Error('Session already open. Call closeSession() first.');
200
202
  }
201
- // Validate session restore options - must have both or neither
202
- if (options.encryptedSession && !options.encryptionKey) {
203
- throw new Error('encryptionKey is required when encryptedSession is provided.');
204
- }
205
- if (options.encryptionKey && !options.encryptedSession) {
206
- console.warn('[GossipSdk] encryptionKey provided without encryptedSession - key will be ignored');
207
- }
208
- // Validate persistence options
209
- if (options.onPersist && !options.persistEncryptionKey) {
210
- throw new Error('persistEncryptionKey is required when onPersist is provided.');
211
- }
212
- if (options.persistEncryptionKey && !options.onPersist) {
213
- console.warn('[GossipSdk] persistEncryptionKey provided without onPersist callback - key will be unused');
214
- }
203
+ // Derive encryption key from mnemonic when not provided
204
+ const encryptionKey = options.encryptionKey ??
205
+ (await generateEncryptionKeyFromSeed(options.mnemonic, new Uint8Array(32).fill(0)));
215
206
  const { messageProtocol } = this.state;
216
207
  // Ensure WASM is ready
217
208
  await ensureWasmInitialized();
209
+ // Validate that encryptedSession can be decrypted with the provided key
210
+ if (options.encryptedSession) {
211
+ try {
212
+ const sessionManager = SessionManagerWrapper.from_encrypted_blob(options.encryptedSession, encryptionKey);
213
+ // We only create this wrapper for validation, free it immediately
214
+ sessionManager.free();
215
+ }
216
+ catch {
217
+ throw new Error('[GossipSdk] Failed to load encrypted session. Please provide a valid encryptedSession and encryptionKey.');
218
+ }
219
+ }
218
220
  // Generate keys from mnemonic
219
221
  const userKeys = await generateUserKeys(options.mnemonic);
220
222
  // Create session with persistence callback
@@ -223,8 +225,8 @@ class GossipSdk {
223
225
  await this.handleSessionPersist();
224
226
  }, options.sessionConfig);
225
227
  // Restore existing session state if provided
226
- if (options.encryptedSession && options.encryptionKey) {
227
- session.load(options.encryptedSession, options.encryptionKey);
228
+ if (options.encryptedSession) {
229
+ session.load(options.encryptedSession, encryptionKey);
228
230
  }
229
231
  // Get config from initialized state
230
232
  const { config } = this.state;
@@ -249,7 +251,7 @@ class GossipSdk {
249
251
  config,
250
252
  session,
251
253
  userKeys,
252
- persistEncryptionKey: options.persistEncryptionKey,
254
+ encryptionKey,
253
255
  onPersist: options.onPersist,
254
256
  };
255
257
  // Create cached service API wrappers
@@ -369,28 +371,12 @@ class GossipSdk {
369
371
  * Get encrypted session blob for persistence.
370
372
  * Throws if no session is open.
371
373
  */
372
- getEncryptedSession(encryptionKey) {
374
+ getEncryptedSession() {
373
375
  const state = this.requireSession();
374
- return state.session.toEncryptedBlob(encryptionKey);
375
- }
376
- /**
377
- * Configure session persistence after session is opened.
378
- * Use this when you need to set up persistence after account creation.
379
- *
380
- * @param encryptionKey - Key to encrypt session blob
381
- * @param onPersist - Callback to save encrypted session blob
382
- */
383
- configurePersistence(encryptionKey, onPersist) {
384
- if (this.state.status !== SdkStatus.SESSION_OPEN) {
385
- throw new Error('No session open. Call openSession() first.');
376
+ if (!state.encryptionKey) {
377
+ throw new Error('No encryption key found. Call openSession() first.');
386
378
  }
387
- // Update state with persistence config
388
- this.state = {
389
- ...this.state,
390
- persistEncryptionKey: encryptionKey,
391
- onPersist,
392
- };
393
- console.log('[GossipSdk] Session persistence configured');
379
+ return state.session.toEncryptedBlob(state.encryptionKey);
394
380
  }
395
381
  // ─────────────────────────────────────────────────────────────────
396
382
  // Services (accessible only when session is open)
@@ -524,13 +510,13 @@ class GossipSdk {
524
510
  async handleSessionPersist() {
525
511
  if (this.state.status !== SdkStatus.SESSION_OPEN)
526
512
  return;
527
- const { onPersist, persistEncryptionKey, session } = this.state;
528
- if (!onPersist || !persistEncryptionKey)
513
+ const { onPersist, encryptionKey, session } = this.state;
514
+ if (!onPersist || !encryptionKey)
529
515
  return;
530
516
  try {
531
- const blob = session.toEncryptedBlob(persistEncryptionKey);
517
+ const blob = session.toEncryptedBlob(encryptionKey);
532
518
  console.log(`[SessionPersist] Saving session blob (${blob.length} bytes)`);
533
- await onPersist(blob, persistEncryptionKey);
519
+ await onPersist(blob, encryptionKey);
534
520
  }
535
521
  catch (error) {
536
522
  this.eventEmitter.emit(SdkEventType.ERROR, error instanceof Error ? error : new Error(String(error)), 'session_persist');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massalabs/gossip-sdk",
3
- "version": "0.0.2-dev.20260223065033",
3
+ "version": "0.0.2-dev.20260223101931",
4
4
  "description": "Gossip SDK for automation, chatbot, and integration use cases",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",