@quilibrium/quorum-shared 2.1.0-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +2414 -0
- package/dist/index.d.ts +2414 -0
- package/dist/index.js +2788 -0
- package/dist/index.mjs +2678 -0
- package/package.json +49 -0
- package/src/api/client.ts +86 -0
- package/src/api/endpoints.ts +87 -0
- package/src/api/errors.ts +179 -0
- package/src/api/index.ts +35 -0
- package/src/crypto/encryption-state.ts +249 -0
- package/src/crypto/index.ts +55 -0
- package/src/crypto/types.ts +307 -0
- package/src/crypto/wasm-provider.ts +298 -0
- package/src/hooks/index.ts +31 -0
- package/src/hooks/keys.ts +62 -0
- package/src/hooks/mutations/index.ts +15 -0
- package/src/hooks/mutations/useDeleteMessage.ts +67 -0
- package/src/hooks/mutations/useEditMessage.ts +87 -0
- package/src/hooks/mutations/useReaction.ts +163 -0
- package/src/hooks/mutations/useSendMessage.ts +131 -0
- package/src/hooks/useChannels.ts +49 -0
- package/src/hooks/useMessages.ts +77 -0
- package/src/hooks/useSpaces.ts +60 -0
- package/src/index.ts +32 -0
- package/src/signing/index.ts +10 -0
- package/src/signing/types.ts +83 -0
- package/src/signing/wasm-provider.ts +75 -0
- package/src/storage/adapter.ts +118 -0
- package/src/storage/index.ts +9 -0
- package/src/sync/index.ts +83 -0
- package/src/sync/service.test.ts +822 -0
- package/src/sync/service.ts +947 -0
- package/src/sync/types.ts +267 -0
- package/src/sync/utils.ts +588 -0
- package/src/transport/browser-websocket.ts +299 -0
- package/src/transport/index.ts +34 -0
- package/src/transport/rn-websocket.ts +321 -0
- package/src/transport/types.ts +56 -0
- package/src/transport/websocket.ts +212 -0
- package/src/types/bookmark.ts +29 -0
- package/src/types/conversation.ts +25 -0
- package/src/types/index.ts +57 -0
- package/src/types/message.ts +178 -0
- package/src/types/space.ts +75 -0
- package/src/types/user.ts +72 -0
- package/src/utils/encoding.ts +106 -0
- package/src/utils/formatting.ts +139 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/logger.ts +141 -0
- package/src/utils/mentions.ts +135 -0
- package/src/utils/validation.ts +84 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket client interface
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic WebSocket connection management.
|
|
5
|
+
* Handles connection, reconnection, and message routing.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: This handles transport only. Encryption is handled separately
|
|
8
|
+
* by the CryptoProvider before/after message transmission.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// ============ Connection State ============
|
|
12
|
+
|
|
13
|
+
export type WebSocketConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting';
|
|
14
|
+
|
|
15
|
+
// ============ Message Types ============
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Encrypted message received from WebSocket
|
|
19
|
+
* The content is a SealedMessage containing the encrypted envelope.
|
|
20
|
+
* All cryptographic material (ephemeral key, identity key) comes from the envelope itself.
|
|
21
|
+
*/
|
|
22
|
+
export interface EncryptedWebSocketMessage {
|
|
23
|
+
/** The encrypted message content (JSON string of SealedMessage) */
|
|
24
|
+
encryptedContent: string;
|
|
25
|
+
/** The inbox address this message was sent to */
|
|
26
|
+
inboxAddress: string;
|
|
27
|
+
/** Server timestamp */
|
|
28
|
+
timestamp: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* SealedMessage format from the network
|
|
33
|
+
* Contains an encrypted envelope that can be unsealed with device keys.
|
|
34
|
+
* The ephemeral_public_key is used along with the inbox private key to decrypt.
|
|
35
|
+
*/
|
|
36
|
+
export interface SealedMessage {
|
|
37
|
+
/** The inbox address the message was sent to */
|
|
38
|
+
inbox_address: string;
|
|
39
|
+
/** Sender's ephemeral public key (used for decryption) */
|
|
40
|
+
ephemeral_public_key: string;
|
|
41
|
+
/** The encrypted envelope (contains identity key, message, return inbox info) */
|
|
42
|
+
envelope: string;
|
|
43
|
+
/** Optional inbox public key for verification */
|
|
44
|
+
inbox_public_key?: string;
|
|
45
|
+
/** Optional inbox signature for verification */
|
|
46
|
+
inbox_signature?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* UnsealedEnvelope - the decrypted content of a SealedMessage
|
|
51
|
+
* Contains all the data needed to establish a session and decrypt the message.
|
|
52
|
+
*/
|
|
53
|
+
export interface UnsealedEnvelope {
|
|
54
|
+
/** Sender's user address */
|
|
55
|
+
user_address: string;
|
|
56
|
+
/** Sender's display name */
|
|
57
|
+
display_name?: string;
|
|
58
|
+
/** Sender's icon URL */
|
|
59
|
+
user_icon?: string;
|
|
60
|
+
/** Inbox address for sending replies */
|
|
61
|
+
return_inbox_address: string;
|
|
62
|
+
/** Encryption key for the return inbox */
|
|
63
|
+
return_inbox_encryption_key: string;
|
|
64
|
+
/** Public key for the return inbox */
|
|
65
|
+
return_inbox_public_key: string;
|
|
66
|
+
/** Private key for the return inbox (only for sender's own use) */
|
|
67
|
+
return_inbox_private_key: string;
|
|
68
|
+
/** Sender's identity public key (for X3DH) */
|
|
69
|
+
identity_public_key: string;
|
|
70
|
+
/** Session/conversation tag */
|
|
71
|
+
tag: string;
|
|
72
|
+
/** The encrypted/signed message content */
|
|
73
|
+
message: string;
|
|
74
|
+
/** Message type */
|
|
75
|
+
type: string;
|
|
76
|
+
/** The ephemeral public key used to seal this message */
|
|
77
|
+
ephemeral_public_key: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Outbound message to send via WebSocket
|
|
82
|
+
*/
|
|
83
|
+
export interface OutboundWebSocketMessage {
|
|
84
|
+
/** Message type (e.g., 'message', 'listen', 'unlisten') */
|
|
85
|
+
type: string;
|
|
86
|
+
/** Message payload */
|
|
87
|
+
payload: unknown;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Listen/subscribe message for inbox addresses
|
|
92
|
+
*/
|
|
93
|
+
export interface ListenMessage {
|
|
94
|
+
type: 'listen';
|
|
95
|
+
inbox_addresses: string[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Unlisten/unsubscribe message
|
|
100
|
+
*/
|
|
101
|
+
export interface UnlistenMessage {
|
|
102
|
+
type: 'unlisten';
|
|
103
|
+
inbox_addresses: string[];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ============ Configuration ============
|
|
107
|
+
|
|
108
|
+
export interface WebSocketClientOptions {
|
|
109
|
+
/** WebSocket server URL */
|
|
110
|
+
url: string;
|
|
111
|
+
/** Interval between reconnection attempts (ms). Default: 1000 */
|
|
112
|
+
reconnectInterval?: number;
|
|
113
|
+
/** Maximum reconnection attempts. Default: Infinity */
|
|
114
|
+
maxReconnectAttempts?: number;
|
|
115
|
+
/** Queue processing interval (ms). Default: 1000 */
|
|
116
|
+
queueProcessInterval?: number;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ============ Event Handlers ============
|
|
120
|
+
|
|
121
|
+
export type MessageHandler = (message: EncryptedWebSocketMessage) => Promise<void>;
|
|
122
|
+
export type StateChangeHandler = (state: WebSocketConnectionState) => void;
|
|
123
|
+
export type ErrorHandler = (error: Error) => void;
|
|
124
|
+
|
|
125
|
+
// ============ WebSocket Client Interface ============
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* WebSocketClient - Platform-agnostic WebSocket interface
|
|
129
|
+
*
|
|
130
|
+
* Features:
|
|
131
|
+
* - Automatic reconnection with configurable interval
|
|
132
|
+
* - Dual queue system (inbound/outbound)
|
|
133
|
+
* - Inbox address subscription management
|
|
134
|
+
* - Message handler registration
|
|
135
|
+
*
|
|
136
|
+
* Implementations:
|
|
137
|
+
* - Browser/Electron: Uses native WebSocket API
|
|
138
|
+
* - React Native: Uses React Native WebSocket
|
|
139
|
+
*/
|
|
140
|
+
export interface WebSocketClient {
|
|
141
|
+
/**
|
|
142
|
+
* Current connection state
|
|
143
|
+
*/
|
|
144
|
+
readonly state: WebSocketConnectionState;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Whether currently connected
|
|
148
|
+
*/
|
|
149
|
+
readonly isConnected: boolean;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Connect to the WebSocket server
|
|
153
|
+
*/
|
|
154
|
+
connect(): Promise<void>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Disconnect from the WebSocket server
|
|
158
|
+
*/
|
|
159
|
+
disconnect(): void;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Send a message (must be already serialized)
|
|
163
|
+
* Messages are queued if not connected and sent when connection is established
|
|
164
|
+
*/
|
|
165
|
+
send(message: string): Promise<void>;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Enqueue an outbound message with async preparation
|
|
169
|
+
* Useful when message needs async work before sending
|
|
170
|
+
*/
|
|
171
|
+
enqueueOutbound(prepareMessage: () => Promise<string[]>): void;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Subscribe to messages for inbox addresses
|
|
175
|
+
*/
|
|
176
|
+
subscribe(inboxAddresses: string[]): Promise<void>;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Unsubscribe from inbox addresses
|
|
180
|
+
*/
|
|
181
|
+
unsubscribe(inboxAddresses: string[]): Promise<void>;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Set the message handler for incoming messages
|
|
185
|
+
* Only one handler can be set at a time
|
|
186
|
+
*/
|
|
187
|
+
setMessageHandler(handler: MessageHandler): void;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Set the resubscribe callback (called after reconnection)
|
|
191
|
+
*/
|
|
192
|
+
setResubscribeHandler(handler: () => Promise<void>): void;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Add a connection state change listener
|
|
196
|
+
* @returns Unsubscribe function
|
|
197
|
+
*/
|
|
198
|
+
onStateChange(handler: StateChangeHandler): () => void;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Add an error listener
|
|
202
|
+
* @returns Unsubscribe function
|
|
203
|
+
*/
|
|
204
|
+
onError(handler: ErrorHandler): () => void;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ============ Factory Function Type ============
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Factory function to create a WebSocket client
|
|
211
|
+
*/
|
|
212
|
+
export type CreateWebSocketClient = (options: WebSocketClientOptions) => WebSocketClient;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bookmark types for Quorum
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type Bookmark = {
|
|
6
|
+
bookmarkId: string;
|
|
7
|
+
messageId: string;
|
|
8
|
+
spaceId?: string;
|
|
9
|
+
channelId?: string;
|
|
10
|
+
conversationId?: string;
|
|
11
|
+
sourceType: 'channel' | 'dm';
|
|
12
|
+
createdAt: number;
|
|
13
|
+
cachedPreview: {
|
|
14
|
+
senderAddress: string;
|
|
15
|
+
senderName: string;
|
|
16
|
+
textSnippet: string;
|
|
17
|
+
messageDate: number;
|
|
18
|
+
sourceName: string;
|
|
19
|
+
contentType: 'text' | 'image' | 'sticker';
|
|
20
|
+
imageUrl?: string;
|
|
21
|
+
thumbnailUrl?: string;
|
|
22
|
+
stickerId?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const BOOKMARKS_CONFIG = {
|
|
27
|
+
MAX_BOOKMARKS: 200,
|
|
28
|
+
PREVIEW_SNIPPET_LENGTH: 150,
|
|
29
|
+
} as const;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation (DM) types for Quorum
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type ConversationSource = 'quorum' | 'farcaster';
|
|
6
|
+
|
|
7
|
+
export type Conversation = {
|
|
8
|
+
conversationId: string;
|
|
9
|
+
type: 'direct' | 'group';
|
|
10
|
+
timestamp: number;
|
|
11
|
+
address: string;
|
|
12
|
+
icon: string;
|
|
13
|
+
displayName: string;
|
|
14
|
+
lastReadTimestamp?: number;
|
|
15
|
+
isRepudiable?: boolean;
|
|
16
|
+
saveEditHistory?: boolean;
|
|
17
|
+
lastMessageId?: string;
|
|
18
|
+
// Farcaster-specific fields
|
|
19
|
+
source?: ConversationSource; // 'quorum' (E2EE) or 'farcaster' (direct cast)
|
|
20
|
+
farcasterConversationId?: string; // Farcaster conversation ID (e.g., "123-456")
|
|
21
|
+
farcasterFid?: number; // Counterparty's Farcaster FID (for 1:1 DMs)
|
|
22
|
+
farcasterUsername?: string; // Counterparty's Farcaster username
|
|
23
|
+
farcasterParticipantFids?: number[]; // All participant FIDs except current user (for group chats)
|
|
24
|
+
unreadCount?: number; // Farcaster unread count
|
|
25
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @quorum/shared types
|
|
3
|
+
*
|
|
4
|
+
* All type definitions shared between mobile and desktop apps
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Space types
|
|
8
|
+
export type {
|
|
9
|
+
Permission,
|
|
10
|
+
Role,
|
|
11
|
+
Emoji,
|
|
12
|
+
Sticker,
|
|
13
|
+
Group,
|
|
14
|
+
Channel,
|
|
15
|
+
Space,
|
|
16
|
+
} from './space';
|
|
17
|
+
|
|
18
|
+
// Message types
|
|
19
|
+
export type {
|
|
20
|
+
MessageSendStatus,
|
|
21
|
+
PostMessage,
|
|
22
|
+
UpdateProfileMessage,
|
|
23
|
+
RemoveMessage,
|
|
24
|
+
EventMessage,
|
|
25
|
+
EmbedMessage,
|
|
26
|
+
ReactionMessage,
|
|
27
|
+
RemoveReactionMessage,
|
|
28
|
+
JoinMessage,
|
|
29
|
+
LeaveMessage,
|
|
30
|
+
KickMessage,
|
|
31
|
+
MuteMessage,
|
|
32
|
+
StickerMessage,
|
|
33
|
+
PinMessage,
|
|
34
|
+
DeleteConversationMessage,
|
|
35
|
+
EditMessage,
|
|
36
|
+
MessageContent,
|
|
37
|
+
Reaction,
|
|
38
|
+
Mentions,
|
|
39
|
+
Message,
|
|
40
|
+
} from './message';
|
|
41
|
+
|
|
42
|
+
// Conversation types
|
|
43
|
+
export type { Conversation, ConversationSource } from './conversation';
|
|
44
|
+
|
|
45
|
+
// User types
|
|
46
|
+
export type {
|
|
47
|
+
FolderColor,
|
|
48
|
+
NavItem,
|
|
49
|
+
NotificationSettings,
|
|
50
|
+
UserConfig,
|
|
51
|
+
UserProfile,
|
|
52
|
+
SpaceMember,
|
|
53
|
+
} from './user';
|
|
54
|
+
|
|
55
|
+
// Bookmark types
|
|
56
|
+
export type { Bookmark } from './bookmark';
|
|
57
|
+
export { BOOKMARKS_CONFIG } from './bookmark';
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message-related types for Quorum
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Client-side ephemeral status - NEVER persist to storage or include in network payload */
|
|
6
|
+
export type MessageSendStatus = 'sending' | 'sent' | 'failed';
|
|
7
|
+
|
|
8
|
+
export type PostMessage = {
|
|
9
|
+
senderId: string;
|
|
10
|
+
type: 'post';
|
|
11
|
+
text: string | string[];
|
|
12
|
+
repliesToMessageId?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type UpdateProfileMessage = {
|
|
16
|
+
senderId: string;
|
|
17
|
+
type: 'update-profile';
|
|
18
|
+
displayName: string;
|
|
19
|
+
userIcon: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type RemoveMessage = {
|
|
23
|
+
senderId: string;
|
|
24
|
+
type: 'remove-message';
|
|
25
|
+
removeMessageId: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type EventMessage = {
|
|
29
|
+
senderId: string;
|
|
30
|
+
type: 'event';
|
|
31
|
+
text: string;
|
|
32
|
+
repliesToMessageId?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type EmbedMessage = {
|
|
36
|
+
senderId: string;
|
|
37
|
+
type: 'embed';
|
|
38
|
+
imageUrl?: string;
|
|
39
|
+
thumbnailUrl?: string;
|
|
40
|
+
videoUrl?: string;
|
|
41
|
+
width?: string;
|
|
42
|
+
height?: string;
|
|
43
|
+
isLargeGif?: boolean;
|
|
44
|
+
repliesToMessageId?: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type ReactionMessage = {
|
|
48
|
+
senderId: string;
|
|
49
|
+
type: 'reaction';
|
|
50
|
+
reaction: string;
|
|
51
|
+
messageId: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type RemoveReactionMessage = {
|
|
55
|
+
senderId: string;
|
|
56
|
+
type: 'remove-reaction';
|
|
57
|
+
reaction: string;
|
|
58
|
+
messageId: string;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type JoinMessage = {
|
|
62
|
+
senderId: string;
|
|
63
|
+
type: 'join';
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type LeaveMessage = {
|
|
67
|
+
senderId: string;
|
|
68
|
+
type: 'leave';
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export type KickMessage = {
|
|
72
|
+
senderId: string;
|
|
73
|
+
type: 'kick';
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export type MuteMessage = {
|
|
77
|
+
senderId: string;
|
|
78
|
+
type: 'mute';
|
|
79
|
+
targetUserId: string;
|
|
80
|
+
muteId: string;
|
|
81
|
+
timestamp: number;
|
|
82
|
+
action: 'mute' | 'unmute';
|
|
83
|
+
duration?: number;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export type StickerMessage = {
|
|
87
|
+
senderId: string;
|
|
88
|
+
type: 'sticker';
|
|
89
|
+
stickerId: string;
|
|
90
|
+
repliesToMessageId?: string;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export type PinMessage = {
|
|
94
|
+
senderId: string;
|
|
95
|
+
type: 'pin';
|
|
96
|
+
targetMessageId: string;
|
|
97
|
+
action: 'pin' | 'unpin';
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export type DeleteConversationMessage = {
|
|
101
|
+
senderId: string;
|
|
102
|
+
type: 'delete-conversation';
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type EditMessage = {
|
|
106
|
+
senderId: string;
|
|
107
|
+
type: 'edit-message';
|
|
108
|
+
originalMessageId: string;
|
|
109
|
+
editedText: string | string[];
|
|
110
|
+
editedAt: number;
|
|
111
|
+
editNonce: string;
|
|
112
|
+
editSignature?: string;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export type MessageContent =
|
|
116
|
+
| PostMessage
|
|
117
|
+
| EventMessage
|
|
118
|
+
| EmbedMessage
|
|
119
|
+
| ReactionMessage
|
|
120
|
+
| RemoveReactionMessage
|
|
121
|
+
| RemoveMessage
|
|
122
|
+
| JoinMessage
|
|
123
|
+
| LeaveMessage
|
|
124
|
+
| KickMessage
|
|
125
|
+
| MuteMessage
|
|
126
|
+
| UpdateProfileMessage
|
|
127
|
+
| StickerMessage
|
|
128
|
+
| PinMessage
|
|
129
|
+
| DeleteConversationMessage
|
|
130
|
+
| EditMessage;
|
|
131
|
+
|
|
132
|
+
export type Reaction = {
|
|
133
|
+
emojiId: string;
|
|
134
|
+
spaceId: string;
|
|
135
|
+
emojiName: string;
|
|
136
|
+
count: number;
|
|
137
|
+
memberIds: string[];
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export type Mentions = {
|
|
141
|
+
memberIds: string[];
|
|
142
|
+
roleIds: string[];
|
|
143
|
+
channelIds: string[];
|
|
144
|
+
everyone?: boolean;
|
|
145
|
+
totalMentionCount?: number;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export type Message = {
|
|
149
|
+
channelId: string;
|
|
150
|
+
spaceId: string;
|
|
151
|
+
messageId: string;
|
|
152
|
+
digestAlgorithm: string;
|
|
153
|
+
nonce: string;
|
|
154
|
+
createdDate: number;
|
|
155
|
+
modifiedDate: number;
|
|
156
|
+
lastModifiedHash: string;
|
|
157
|
+
content: MessageContent;
|
|
158
|
+
reactions: Reaction[];
|
|
159
|
+
mentions: Mentions;
|
|
160
|
+
replyMetadata?: {
|
|
161
|
+
parentAuthor: string;
|
|
162
|
+
parentChannelId: string;
|
|
163
|
+
};
|
|
164
|
+
publicKey?: string;
|
|
165
|
+
signature?: string;
|
|
166
|
+
isPinned?: boolean;
|
|
167
|
+
pinnedAt?: number;
|
|
168
|
+
pinnedBy?: string;
|
|
169
|
+
edits?: Array<{
|
|
170
|
+
text: string | string[];
|
|
171
|
+
modifiedDate: number;
|
|
172
|
+
lastModifiedHash: string;
|
|
173
|
+
}>;
|
|
174
|
+
/** Client-side ephemeral - NEVER persist or transmit */
|
|
175
|
+
sendStatus?: MessageSendStatus;
|
|
176
|
+
/** Client-side ephemeral - sanitized error message for display */
|
|
177
|
+
sendError?: string;
|
|
178
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Space-related types for Quorum
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type Permission = 'message:delete' | 'message:pin' | 'mention:everyone' | 'user:mute';
|
|
6
|
+
|
|
7
|
+
export type Role = {
|
|
8
|
+
roleId: string;
|
|
9
|
+
displayName: string;
|
|
10
|
+
roleTag: string;
|
|
11
|
+
color: string;
|
|
12
|
+
members: string[];
|
|
13
|
+
permissions: Permission[];
|
|
14
|
+
isPublic?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type Emoji = {
|
|
18
|
+
name: string;
|
|
19
|
+
id: string;
|
|
20
|
+
imgUrl: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type Sticker = {
|
|
24
|
+
name: string;
|
|
25
|
+
id: string;
|
|
26
|
+
imgUrl: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type Group = {
|
|
30
|
+
groupName: string;
|
|
31
|
+
channels: Channel[];
|
|
32
|
+
icon?: string;
|
|
33
|
+
iconColor?: string;
|
|
34
|
+
iconVariant?: 'outline' | 'filled';
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type Channel = {
|
|
38
|
+
channelId: string;
|
|
39
|
+
spaceId: string;
|
|
40
|
+
channelName: string;
|
|
41
|
+
channelTopic: string;
|
|
42
|
+
channelKey?: string;
|
|
43
|
+
createdDate: number;
|
|
44
|
+
modifiedDate: number;
|
|
45
|
+
mentionCount?: number;
|
|
46
|
+
mentions?: string;
|
|
47
|
+
isReadOnly?: boolean;
|
|
48
|
+
managerRoleIds?: string[];
|
|
49
|
+
isPinned?: boolean;
|
|
50
|
+
pinnedAt?: number;
|
|
51
|
+
icon?: string;
|
|
52
|
+
iconColor?: string;
|
|
53
|
+
iconVariant?: 'outline' | 'filled';
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type Space = {
|
|
57
|
+
spaceId: string;
|
|
58
|
+
spaceName: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
vanityUrl: string;
|
|
61
|
+
inviteUrl: string;
|
|
62
|
+
iconUrl: string;
|
|
63
|
+
bannerUrl: string;
|
|
64
|
+
defaultChannelId: string;
|
|
65
|
+
hubAddress: string;
|
|
66
|
+
createdDate: number;
|
|
67
|
+
modifiedDate: number;
|
|
68
|
+
isRepudiable: boolean;
|
|
69
|
+
isPublic: boolean;
|
|
70
|
+
saveEditHistory?: boolean;
|
|
71
|
+
groups: Group[];
|
|
72
|
+
roles: Role[];
|
|
73
|
+
emojis: Emoji[];
|
|
74
|
+
stickers: Sticker[];
|
|
75
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-related types for Quorum
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Bookmark } from './bookmark';
|
|
6
|
+
|
|
7
|
+
export type FolderColor = string;
|
|
8
|
+
|
|
9
|
+
export type NavItem =
|
|
10
|
+
| { type: 'space'; id: string }
|
|
11
|
+
| {
|
|
12
|
+
type: 'folder';
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
spaceIds: string[];
|
|
16
|
+
icon?: string;
|
|
17
|
+
color?: FolderColor;
|
|
18
|
+
createdDate: number;
|
|
19
|
+
modifiedDate: number;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type NotificationSettings = {
|
|
23
|
+
enabled?: boolean;
|
|
24
|
+
mentions?: boolean;
|
|
25
|
+
replies?: boolean;
|
|
26
|
+
all?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type UserConfig = {
|
|
30
|
+
address: string;
|
|
31
|
+
spaceIds: string[];
|
|
32
|
+
items?: NavItem[];
|
|
33
|
+
timestamp?: number;
|
|
34
|
+
nonRepudiable?: boolean;
|
|
35
|
+
allowSync?: boolean;
|
|
36
|
+
name?: string;
|
|
37
|
+
profile_image?: string;
|
|
38
|
+
spaceKeys?: {
|
|
39
|
+
spaceId: string;
|
|
40
|
+
encryptionState: {
|
|
41
|
+
conversationId: string;
|
|
42
|
+
inboxId: string;
|
|
43
|
+
state: string;
|
|
44
|
+
timestamp: number;
|
|
45
|
+
};
|
|
46
|
+
keys: {
|
|
47
|
+
keyId: string;
|
|
48
|
+
address?: string;
|
|
49
|
+
publicKey: string;
|
|
50
|
+
privateKey: string;
|
|
51
|
+
spaceId: string;
|
|
52
|
+
}[];
|
|
53
|
+
}[];
|
|
54
|
+
notificationSettings?: {
|
|
55
|
+
[spaceId: string]: NotificationSettings;
|
|
56
|
+
};
|
|
57
|
+
bookmarks?: Bookmark[];
|
|
58
|
+
deletedBookmarkIds?: string[];
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type UserProfile = {
|
|
62
|
+
address: string;
|
|
63
|
+
name?: string;
|
|
64
|
+
display_name?: string;
|
|
65
|
+
profile_image?: string;
|
|
66
|
+
bio?: string;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type SpaceMember = UserProfile & {
|
|
70
|
+
inbox_address: string;
|
|
71
|
+
isKicked?: boolean;
|
|
72
|
+
};
|