@massalabs/gossip-sdk 0.0.2-dev.20260128094509 → 0.0.2-dev.20260128160824
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/dist/api/messageProtocol/index.d.ts +19 -0
- package/dist/api/messageProtocol/index.js +26 -0
- package/dist/api/messageProtocol/mock.d.ts +12 -0
- package/{src/api/messageProtocol/mock.ts → dist/api/messageProtocol/mock.js} +2 -3
- package/dist/api/messageProtocol/rest.d.ts +22 -0
- package/dist/api/messageProtocol/rest.js +161 -0
- package/dist/api/messageProtocol/types.d.ts +61 -0
- package/dist/api/messageProtocol/types.js +6 -0
- package/dist/assets/generated/wasm/README.md +281 -0
- package/dist/assets/generated/wasm/gossip_wasm.d.ts +638 -0
- package/dist/assets/generated/wasm/gossip_wasm.js +1557 -0
- package/dist/assets/generated/wasm/gossip_wasm_bg.wasm +0 -0
- package/dist/assets/generated/wasm/gossip_wasm_bg.wasm.d.ts +164 -0
- package/dist/assets/generated/wasm/package.json +15 -0
- package/dist/assets/generated/wasm-node/README.md +281 -0
- package/dist/assets/generated/wasm-node/gossip_wasm.d.ts +443 -0
- package/dist/assets/generated/wasm-node/gossip_wasm.js +1488 -0
- package/dist/assets/generated/wasm-node/gossip_wasm_bg.wasm +0 -0
- package/dist/assets/generated/wasm-node/gossip_wasm_bg.wasm.d.ts +164 -0
- package/dist/assets/generated/wasm-node/package.json +11 -0
- package/dist/config/protocol.d.ts +36 -0
- package/dist/config/protocol.js +77 -0
- package/dist/config/sdk.d.ts +82 -0
- package/dist/config/sdk.js +55 -0
- package/{src/contacts.ts → dist/contacts.d.ts} +11 -95
- package/dist/contacts.js +166 -0
- package/dist/core/SdkEventEmitter.d.ts +36 -0
- package/dist/core/SdkEventEmitter.js +59 -0
- package/dist/core/SdkPolling.d.ts +35 -0
- package/dist/core/SdkPolling.js +100 -0
- package/{src/core/index.ts → dist/core/index.d.ts} +0 -2
- package/dist/core/index.js +5 -0
- package/dist/crypto/bip39.d.ts +34 -0
- package/dist/crypto/bip39.js +62 -0
- package/dist/crypto/encryption.d.ts +37 -0
- package/dist/crypto/encryption.js +46 -0
- package/dist/db.d.ts +190 -0
- package/dist/db.js +311 -0
- package/dist/gossipSdk.d.ts +274 -0
- package/dist/gossipSdk.js +690 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +61 -0
- package/dist/services/announcement.d.ts +43 -0
- package/dist/services/announcement.js +491 -0
- package/dist/services/auth.d.ts +37 -0
- package/dist/services/auth.js +76 -0
- package/dist/services/discussion.d.ts +63 -0
- package/dist/services/discussion.js +297 -0
- package/dist/services/message.d.ts +74 -0
- package/dist/services/message.js +826 -0
- package/dist/services/refresh.d.ts +41 -0
- package/dist/services/refresh.js +205 -0
- package/{src/sw.ts → dist/sw.d.ts} +1 -8
- package/dist/sw.js +10 -0
- package/dist/types/events.d.ts +80 -0
- package/dist/types/events.js +7 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.js +7 -0
- package/dist/utils/base64.d.ts +10 -0
- package/dist/utils/base64.js +30 -0
- package/dist/utils/contacts.d.ts +42 -0
- package/dist/utils/contacts.js +113 -0
- package/dist/utils/discussions.d.ts +24 -0
- package/dist/utils/discussions.js +38 -0
- package/dist/utils/logs.d.ts +19 -0
- package/dist/utils/logs.js +89 -0
- package/dist/utils/messageSerialization.d.ts +64 -0
- package/dist/utils/messageSerialization.js +184 -0
- package/dist/utils/queue.d.ts +50 -0
- package/dist/utils/queue.js +110 -0
- package/dist/utils/type.d.ts +10 -0
- package/dist/utils/type.js +4 -0
- package/dist/utils/userId.d.ts +40 -0
- package/dist/utils/userId.js +90 -0
- package/dist/utils/validation.d.ts +50 -0
- package/dist/utils/validation.js +112 -0
- package/dist/utils.d.ts +30 -0
- package/{src/utils.ts → dist/utils.js} +9 -19
- package/dist/wasm/encryption.d.ts +56 -0
- package/{src/wasm/encryption.ts → dist/wasm/encryption.js} +22 -51
- package/dist/wasm/index.d.ts +10 -0
- package/{src/wasm/index.ts → dist/wasm/index.js} +1 -8
- package/dist/wasm/loader.d.ts +22 -0
- package/dist/wasm/loader.js +78 -0
- package/dist/wasm/session.d.ts +85 -0
- package/dist/wasm/session.js +226 -0
- package/dist/wasm/userKeys.d.ts +17 -0
- package/{src/wasm/userKeys.ts → dist/wasm/userKeys.js} +6 -13
- package/package.json +15 -2
- package/src/api/messageProtocol/index.ts +0 -53
- package/src/api/messageProtocol/rest.ts +0 -209
- package/src/api/messageProtocol/types.ts +0 -70
- package/src/config/protocol.ts +0 -97
- package/src/config/sdk.ts +0 -131
- package/src/core/SdkEventEmitter.ts +0 -91
- package/src/core/SdkPolling.ts +0 -134
- package/src/crypto/bip39.ts +0 -84
- package/src/crypto/encryption.ts +0 -77
- package/src/db.ts +0 -465
- package/src/gossipSdk.ts +0 -994
- package/src/index.ts +0 -211
- package/src/services/announcement.ts +0 -653
- package/src/services/auth.ts +0 -95
- package/src/services/discussion.ts +0 -380
- package/src/services/message.ts +0 -1055
- package/src/services/refresh.ts +0 -234
- package/src/types/events.ts +0 -108
- package/src/types.ts +0 -70
- package/src/utils/base64.ts +0 -39
- package/src/utils/contacts.ts +0 -161
- package/src/utils/discussions.ts +0 -55
- package/src/utils/logs.ts +0 -86
- package/src/utils/messageSerialization.ts +0 -257
- package/src/utils/queue.ts +0 -106
- package/src/utils/type.ts +0 -7
- package/src/utils/userId.ts +0 -114
- package/src/utils/validation.ts +0 -144
- package/src/wasm/loader.ts +0 -123
- package/src/wasm/session.ts +0 -276
- package/test/config/protocol.spec.ts +0 -31
- package/test/config/sdk.spec.ts +0 -163
- package/test/db/helpers.spec.ts +0 -142
- package/test/db/operations.spec.ts +0 -128
- package/test/db/states.spec.ts +0 -535
- package/test/integration/discussion-flow.spec.ts +0 -422
- package/test/integration/messaging-flow.spec.ts +0 -708
- package/test/integration/sdk-lifecycle.spec.ts +0 -325
- package/test/mocks/index.ts +0 -9
- package/test/mocks/mockMessageProtocol.ts +0 -100
- package/test/services/auth.spec.ts +0 -311
- package/test/services/discussion.spec.ts +0 -279
- package/test/services/message-deduplication.spec.ts +0 -299
- package/test/services/message-startup.spec.ts +0 -331
- package/test/services/message.spec.ts +0 -817
- package/test/services/refresh.spec.ts +0 -199
- package/test/services/session-status.spec.ts +0 -349
- package/test/session/wasm.spec.ts +0 -227
- package/test/setup.ts +0 -52
- package/test/utils/contacts.spec.ts +0 -156
- package/test/utils/discussions.spec.ts +0 -66
- package/test/utils/queue.spec.ts +0 -52
- package/test/utils/serialization.spec.ts +0 -120
- package/test/utils/userId.spec.ts +0 -120
- package/test/utils/validation.spec.ts +0 -223
- package/test/utils.ts +0 -212
- package/tsconfig.json +0 -26
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -28
package/dist/contacts.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contact Management SDK
|
|
3
|
+
*
|
|
4
|
+
* Functions for managing contacts including CRUD operations.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { getContacts, addContact, deleteContact } from 'gossip-sdk';
|
|
9
|
+
*
|
|
10
|
+
* // Get all contacts
|
|
11
|
+
* const contacts = await getContacts(userId);
|
|
12
|
+
*
|
|
13
|
+
* // Add a new contact
|
|
14
|
+
* const result = await addContact(userId, contactUserId, 'Alice', publicKeys);
|
|
15
|
+
*
|
|
16
|
+
* // Delete a contact
|
|
17
|
+
* await deleteContact(userId, contactUserId);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import { updateContactName as updateContactNameUtil, deleteContact as deleteContactUtil, } from './utils/contacts';
|
|
21
|
+
/**
|
|
22
|
+
* Get all contacts for an owner.
|
|
23
|
+
*
|
|
24
|
+
* @param ownerUserId - The user ID of the contact owner
|
|
25
|
+
* @param db - Database instance
|
|
26
|
+
* @returns Array of contacts
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const contacts = await getContacts(myUserId, db);
|
|
31
|
+
* contacts.forEach(c => console.log(c.name, c.userId));
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export async function getContacts(ownerUserId, db) {
|
|
35
|
+
try {
|
|
36
|
+
return await db.getContactsByOwner(ownerUserId);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Error getting contacts:', error);
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get a specific contact by owner and contact user IDs.
|
|
45
|
+
*
|
|
46
|
+
* @param ownerUserId - The user ID of the contact owner
|
|
47
|
+
* @param contactUserId - The user ID of the contact
|
|
48
|
+
* @param db - Database instance
|
|
49
|
+
* @returns Contact or null if not found
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const contact = await getContact(myUserId, theirUserId, db);
|
|
54
|
+
* if (contact) {
|
|
55
|
+
* console.log('Found contact:', contact.name);
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export async function getContact(ownerUserId, contactUserId, db) {
|
|
60
|
+
try {
|
|
61
|
+
const contact = await db.getContactByOwnerAndUserId(ownerUserId, contactUserId);
|
|
62
|
+
return contact ?? null;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error('Error getting contact:', error);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Add a new contact.
|
|
71
|
+
*
|
|
72
|
+
* @param ownerUserId - The user ID of the contact owner
|
|
73
|
+
* @param userId - The user ID of the contact (Bech32-encoded)
|
|
74
|
+
* @param name - Display name for the contact
|
|
75
|
+
* @param publicKeys - The contact's public keys
|
|
76
|
+
* @param db - Database instance
|
|
77
|
+
* @returns Result with success status and optional contact
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const result = await addContact(
|
|
82
|
+
* myUserId,
|
|
83
|
+
* 'gossip1abc...',
|
|
84
|
+
* 'Alice',
|
|
85
|
+
* alicePublicKeys,
|
|
86
|
+
* db
|
|
87
|
+
* );
|
|
88
|
+
* if (result.success) {
|
|
89
|
+
* console.log('Contact added:', result.contact?.name);
|
|
90
|
+
* } else if (result.error === 'Contact already exists') {
|
|
91
|
+
* console.log('Contact already exists');
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export async function addContact(ownerUserId, userId, name, publicKeys, db) {
|
|
96
|
+
try {
|
|
97
|
+
// Check if contact already exists
|
|
98
|
+
const existing = await db.getContactByOwnerAndUserId(ownerUserId, userId);
|
|
99
|
+
if (existing) {
|
|
100
|
+
return { success: false, error: 'Contact already exists' };
|
|
101
|
+
}
|
|
102
|
+
const contact = {
|
|
103
|
+
ownerUserId,
|
|
104
|
+
userId,
|
|
105
|
+
name,
|
|
106
|
+
publicKeys: publicKeys.to_bytes(),
|
|
107
|
+
isOnline: false,
|
|
108
|
+
lastSeen: new Date(),
|
|
109
|
+
createdAt: new Date(),
|
|
110
|
+
};
|
|
111
|
+
const id = await db.contacts.add(contact);
|
|
112
|
+
const newContact = await db.contacts.get(id);
|
|
113
|
+
return { success: true, contact: newContact };
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error('Error adding contact:', error);
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Update contact name.
|
|
125
|
+
*
|
|
126
|
+
* @param ownerUserId - The user ID of the contact owner
|
|
127
|
+
* @param contactUserId - The user ID of the contact
|
|
128
|
+
* @param newName - New name for the contact
|
|
129
|
+
* @param db - Database instance
|
|
130
|
+
* @returns Result with success status and trimmed name
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const result = await updateContactName(myUserId, theirUserId, 'Alice Smith', db);
|
|
135
|
+
* if (result.ok) {
|
|
136
|
+
* console.log('Updated to:', result.trimmedName);
|
|
137
|
+
* } else {
|
|
138
|
+
* console.error('Failed:', result.message);
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export async function updateContactName(ownerUserId, contactUserId, newName, db) {
|
|
143
|
+
return await updateContactNameUtil(ownerUserId, contactUserId, newName, db);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Delete a contact and all associated discussions and messages.
|
|
147
|
+
*
|
|
148
|
+
* @param ownerUserId - The user ID of the contact owner
|
|
149
|
+
* @param contactUserId - The user ID of the contact to delete
|
|
150
|
+
* @param db - Database instance
|
|
151
|
+
* @param session - Session module for peer management
|
|
152
|
+
* @returns Result with success status
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* const result = await deleteContact(myUserId, theirUserId, db, session);
|
|
157
|
+
* if (result.ok) {
|
|
158
|
+
* console.log('Contact deleted');
|
|
159
|
+
* } else {
|
|
160
|
+
* console.error('Failed:', result.message);
|
|
161
|
+
* }
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export async function deleteContact(ownerUserId, contactUserId, db, session) {
|
|
165
|
+
return await deleteContactUtil(ownerUserId, contactUserId, db, session);
|
|
166
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Event Emitter
|
|
3
|
+
*
|
|
4
|
+
* Type-safe event emitter for SDK events.
|
|
5
|
+
*/
|
|
6
|
+
import type { Message, Discussion, Contact } from '../db';
|
|
7
|
+
export type SdkEventType = 'message' | 'messageSent' | 'messageFailed' | 'discussionRequest' | 'discussionStatusChanged' | 'sessionBroken' | 'sessionRenewed' | 'error';
|
|
8
|
+
export interface SdkEventHandlers {
|
|
9
|
+
message: (message: Message) => void;
|
|
10
|
+
messageSent: (message: Message) => void;
|
|
11
|
+
messageFailed: (message: Message, error: Error) => void;
|
|
12
|
+
discussionRequest: (discussion: Discussion, contact: Contact) => void;
|
|
13
|
+
discussionStatusChanged: (discussion: Discussion) => void;
|
|
14
|
+
sessionBroken: (discussion: Discussion) => void;
|
|
15
|
+
sessionRenewed: (discussion: Discussion) => void;
|
|
16
|
+
error: (error: Error, context: string) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare class SdkEventEmitter {
|
|
19
|
+
private handlers;
|
|
20
|
+
/**
|
|
21
|
+
* Register an event handler
|
|
22
|
+
*/
|
|
23
|
+
on<K extends SdkEventType>(event: K, handler: SdkEventHandlers[K]): void;
|
|
24
|
+
/**
|
|
25
|
+
* Remove an event handler
|
|
26
|
+
*/
|
|
27
|
+
off<K extends SdkEventType>(event: K, handler: SdkEventHandlers[K]): void;
|
|
28
|
+
/**
|
|
29
|
+
* Emit an event to all registered handlers
|
|
30
|
+
*/
|
|
31
|
+
emit<K extends SdkEventType>(event: K, ...args: Parameters<SdkEventHandlers[K]>): void;
|
|
32
|
+
/**
|
|
33
|
+
* Remove all handlers for all events
|
|
34
|
+
*/
|
|
35
|
+
clear(): void;
|
|
36
|
+
}
|
|
@@ -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,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
|
+
}
|