nostr-double-ratchet 0.0.38 → 0.0.48

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/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export * from "./Session"
2
2
  export * from "./Invite"
3
- export * from "./InviteList"
3
+ export * from "./AppKeys"
4
4
  export * from "./inviteUtils"
5
5
  export * from "./types"
6
6
  export * from "./utils"
7
7
  export * from "./SessionManager"
8
- export * from "./DeviceManager"
9
- export * from "./StorageAdapter"
8
+ export * from "./AppKeysManager"
9
+ export * from "./StorageAdapter"
@@ -49,7 +49,7 @@ export function generateDeviceId(): string {
49
49
  export interface EncryptInviteResponseParams {
50
50
  /** The invitee's session public key */
51
51
  inviteeSessionPublicKey: string
52
- /** The invitee's identity public key */
52
+ /** The invitee's identity public key (also serves as device ID) */
53
53
  inviteePublicKey: string
54
54
  /** The invitee's identity private key (optional if encrypt function provided) */
55
55
  inviteePrivateKey?: Uint8Array
@@ -59,8 +59,8 @@ export interface EncryptInviteResponseParams {
59
59
  inviterEphemeralPublicKey: string
60
60
  /** The shared secret for the invite */
61
61
  sharedSecret: string
62
- /** Optional device ID for the invitee's device */
63
- deviceId?: string
62
+ /** The invitee's owner/Nostr identity public key (optional for single-device users) */
63
+ ownerPublicKey?: string
64
64
  /** Optional custom encrypt function */
65
65
  encrypt?: EncryptFunction
66
66
  }
@@ -104,7 +104,7 @@ export async function encryptInviteResponse(params: EncryptInviteResponseParams)
104
104
  inviterPublicKey,
105
105
  inviterEphemeralPublicKey,
106
106
  sharedSecret,
107
- deviceId,
107
+ ownerPublicKey,
108
108
  encrypt,
109
109
  } = params
110
110
 
@@ -119,9 +119,10 @@ export async function encryptInviteResponse(params: EncryptInviteResponseParams)
119
119
  })
120
120
 
121
121
  // Create the payload
122
+ // Note: deviceId is no longer needed - inviteePublicKey (identity) serves as device ID
122
123
  const payload = JSON.stringify({
123
124
  sessionKey: inviteeSessionPublicKey,
124
- deviceId: deviceId,
125
+ ...(ownerPublicKey && { ownerPublicKey }),
125
126
  })
126
127
 
127
128
  // Encrypt with DH key (invitee -> inviter)
@@ -172,12 +173,12 @@ export interface DecryptInviteResponseParams {
172
173
  }
173
174
 
174
175
  export interface DecryptedInviteResponse {
175
- /** The invitee's identity public key */
176
+ /** The invitee's identity public key (also serves as device ID) */
176
177
  inviteeIdentity: string
177
178
  /** The invitee's session public key */
178
179
  inviteeSessionPublicKey: string
179
- /** Optional device ID for the invitee's device */
180
- deviceId?: string
180
+ /** The invitee's owner/Nostr identity public key (optional for backward compat) */
181
+ ownerPublicKey?: string
181
182
  }
182
183
 
183
184
  /**
@@ -219,12 +220,12 @@ export async function decryptInviteResponse(params: DecryptInviteResponseParams)
219
220
  const decryptedPayload = await decryptFn(dhEncrypted, inviteeIdentity)
220
221
 
221
222
  let inviteeSessionPublicKey: string
222
- let deviceId: string | undefined
223
+ let ownerPublicKey: string | undefined
223
224
 
224
225
  try {
225
226
  const parsed = JSON.parse(decryptedPayload)
226
227
  inviteeSessionPublicKey = parsed.sessionKey
227
- deviceId = parsed.deviceId
228
+ ownerPublicKey = parsed.ownerPublicKey
228
229
  } catch {
229
230
  // Backward compatibility: plain session key
230
231
  inviteeSessionPublicKey = decryptedPayload
@@ -233,7 +234,7 @@ export async function decryptInviteResponse(params: DecryptInviteResponseParams)
233
234
  return {
234
235
  inviteeIdentity,
235
236
  inviteeSessionPublicKey,
236
- deviceId,
237
+ ownerPublicKey,
237
238
  }
238
239
  }
239
240
 
package/src/types.ts CHANGED
@@ -98,14 +98,10 @@ export const INVITE_EVENT_KIND = 30078;
98
98
 
99
99
  export const INVITE_RESPONSE_KIND = 1059;
100
100
 
101
- /**
102
- * Invite list event kind (replaceable - one per user)
103
- */
104
- export const INVITE_LIST_EVENT_KIND = 10078;
101
+ export const APP_KEYS_EVENT_KIND = 30078;
105
102
 
106
103
  export const CHAT_MESSAGE_KIND = 14;
107
104
 
108
- export const MAX_SKIP = 100;
109
105
 
110
106
  export type NostrEvent = {
111
107
  id: string;
@@ -116,3 +112,30 @@ export type NostrEvent = {
116
112
  content: string;
117
113
  sig: string;
118
114
  }
115
+
116
+ /**
117
+ * Payload for reaction messages sent through NDR.
118
+ * Reactions are regular messages with a JSON payload indicating they're a reaction.
119
+ */
120
+ export interface ReactionPayload {
121
+ type: 'reaction';
122
+ /** ID of the message being reacted to */
123
+ messageId: string;
124
+ /** Emoji or reaction content */
125
+ emoji: string;
126
+ }
127
+
128
+ /**
129
+ * Kind constant for reaction inner events
130
+ */
131
+ export const REACTION_KIND = 7;
132
+
133
+ /**
134
+ * Kind constant for read/delivery receipt inner events
135
+ */
136
+ export const RECEIPT_KIND = 15;
137
+
138
+ /**
139
+ * Kind constant for typing indicator inner events
140
+ */
141
+ export const TYPING_KIND = 25;
package/src/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { hexToBytes, bytesToHex } from "@noble/hashes/utils";
2
- import { Rumor, SessionState } from "./types";
2
+ import { Rumor, SessionState, ReactionPayload } from "./types";
3
3
  import { Session } from "./Session.ts";
4
4
  import { extract as hkdf_extract, expand as hkdf_expand } from '@noble/hashes/hkdf';
5
5
  import { sha256 } from '@noble/hashes/sha256';
@@ -188,10 +188,6 @@ export function kdf(input1: Uint8Array, input2: Uint8Array = new Uint8Array(32),
188
188
  return outputs;
189
189
  }
190
190
 
191
- export function skippedMessageIndexKey(_nostrSender: string, _number: number): string {
192
- return `${_nostrSender}:${_number}`;
193
- }
194
-
195
191
  export function getMillisecondTimestamp(event: Rumor) {
196
192
  const msTag = event.tags?.find((tag: string[]) => tag[0] === "ms");
197
193
  if (msTag) {
@@ -199,3 +195,44 @@ export function getMillisecondTimestamp(event: Rumor) {
199
195
  }
200
196
  return event.created_at * 1000;
201
197
  }
198
+
199
+ /**
200
+ * Check if a message content is a reaction payload.
201
+ * @param content The message content to check
202
+ * @returns The parsed ReactionPayload if valid, null otherwise
203
+ */
204
+ export function parseReaction(content: string): ReactionPayload | null {
205
+ try {
206
+ const parsed = JSON.parse(content);
207
+ if (parsed.type === 'reaction' && typeof parsed.messageId === 'string' && typeof parsed.emoji === 'string') {
208
+ return parsed as ReactionPayload;
209
+ }
210
+ } catch {
211
+ // Not JSON or invalid structure
212
+ }
213
+ return null;
214
+ }
215
+
216
+ /**
217
+ * Check if a message content is a reaction.
218
+ * @param content The message content to check
219
+ * @returns true if the content is a reaction payload
220
+ */
221
+ export function isReaction(content: string): boolean {
222
+ return parseReaction(content) !== null;
223
+ }
224
+
225
+ /**
226
+ * Create a reaction payload JSON string.
227
+ * @param messageId The ID of the message being reacted to
228
+ * @param emoji The emoji or reaction content
229
+ * @returns JSON string of the reaction payload
230
+ */
231
+ export function createReactionPayload(messageId: string, emoji: string): string {
232
+ const payload: ReactionPayload = {
233
+ type: 'reaction',
234
+ messageId,
235
+ emoji
236
+ };
237
+ return JSON.stringify(payload);
238
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Martti Malmi
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,127 +0,0 @@
1
- import { InviteList, DeviceEntry } from "./InviteList";
2
- import { DevicePayload } from "./inviteUtils";
3
- import { NostrSubscribe, NostrPublish, IdentityKey } from "./types";
4
- import { StorageAdapter } from "./StorageAdapter";
5
- import { SessionManager } from "./SessionManager";
6
- export interface OwnerDeviceOptions {
7
- ownerPublicKey: string;
8
- identityKey: IdentityKey;
9
- deviceId: string;
10
- deviceLabel: string;
11
- nostrSubscribe: NostrSubscribe;
12
- nostrPublish: NostrPublish;
13
- storage?: StorageAdapter;
14
- }
15
- export interface DelegateDeviceOptions {
16
- deviceId: string;
17
- deviceLabel: string;
18
- nostrSubscribe: NostrSubscribe;
19
- nostrPublish: NostrPublish;
20
- storage?: StorageAdapter;
21
- }
22
- export interface RestoreDelegateOptions {
23
- deviceId: string;
24
- devicePublicKey: string;
25
- devicePrivateKey: Uint8Array;
26
- ephemeralPublicKey: string;
27
- ephemeralPrivateKey: Uint8Array;
28
- sharedSecret: string;
29
- nostrSubscribe: NostrSubscribe;
30
- nostrPublish: NostrPublish;
31
- storage?: StorageAdapter;
32
- }
33
- export interface CreateDelegateResult {
34
- manager: DelegateDeviceManager;
35
- payload: DevicePayload;
36
- }
37
- export interface IDeviceManager {
38
- init(): Promise<void>;
39
- getDeviceId(): string;
40
- getIdentityPublicKey(): string;
41
- getIdentityKey(): IdentityKey;
42
- getEphemeralKeypair(): {
43
- publicKey: string;
44
- privateKey: Uint8Array;
45
- } | null;
46
- getSharedSecret(): string | null;
47
- getOwnerPublicKey(): string | null;
48
- close(): void;
49
- createSessionManager(sessionStorage?: StorageAdapter): SessionManager;
50
- }
51
- /** Owner's main device. Has identity key and can manage InviteList. */
52
- export declare class OwnerDeviceManager implements IDeviceManager {
53
- private readonly deviceId;
54
- private readonly deviceLabel;
55
- private readonly nostrSubscribe;
56
- private readonly nostrPublish;
57
- private readonly storage;
58
- private readonly ownerPublicKey;
59
- private readonly identityKey;
60
- private inviteList;
61
- private initialized;
62
- private subscriptions;
63
- private readonly storageVersion;
64
- private get versionPrefix();
65
- constructor(options: OwnerDeviceOptions);
66
- init(): Promise<void>;
67
- getDeviceId(): string;
68
- getIdentityPublicKey(): string;
69
- getIdentityKey(): IdentityKey;
70
- getEphemeralKeypair(): {
71
- publicKey: string;
72
- privateKey: Uint8Array;
73
- } | null;
74
- getSharedSecret(): string | null;
75
- getOwnerPublicKey(): string;
76
- getInviteList(): InviteList | null;
77
- getOwnDevices(): DeviceEntry[];
78
- addDevice(payload: DevicePayload): Promise<void>;
79
- revokeDevice(deviceId: string): Promise<void>;
80
- updateDeviceLabel(deviceId: string, label: string): Promise<void>;
81
- close(): void;
82
- createSessionManager(sessionStorage?: StorageAdapter): SessionManager;
83
- private inviteListKey;
84
- private loadInviteList;
85
- private saveInviteList;
86
- private fetchInviteList;
87
- private mergeInviteLists;
88
- private modifyInviteList;
89
- private subscribeToOwnInviteList;
90
- }
91
- /** Delegate device. Has own identity key, waits for activation, checks revocation. */
92
- export declare class DelegateDeviceManager implements IDeviceManager {
93
- private readonly deviceId;
94
- private readonly nostrSubscribe;
95
- private readonly nostrPublish;
96
- private readonly storage;
97
- private readonly devicePublicKey;
98
- private readonly devicePrivateKey;
99
- private readonly ephemeralPublicKey;
100
- private readonly ephemeralPrivateKey;
101
- private readonly sharedSecret;
102
- private ownerPubkeyFromActivation?;
103
- private initialized;
104
- private subscriptions;
105
- private readonly storageVersion;
106
- private get versionPrefix();
107
- private constructor();
108
- static create(options: DelegateDeviceOptions): CreateDelegateResult;
109
- static restore(options: RestoreDelegateOptions): DelegateDeviceManager;
110
- init(): Promise<void>;
111
- getDeviceId(): string;
112
- getIdentityPublicKey(): string;
113
- getIdentityKey(): Uint8Array;
114
- getEphemeralKeypair(): {
115
- publicKey: string;
116
- privateKey: Uint8Array;
117
- };
118
- getSharedSecret(): string;
119
- getOwnerPublicKey(): string | null;
120
- waitForActivation(timeoutMs?: number): Promise<string>;
121
- isRevoked(): Promise<boolean>;
122
- close(): void;
123
- createSessionManager(sessionStorage?: StorageAdapter): SessionManager;
124
- private ownerPubkeyKey;
125
- private fetchInviteList;
126
- }
127
- //# sourceMappingURL=DeviceManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DeviceManager.d.ts","sourceRoot":"","sources":["../src/DeviceManager.ts"],"names":[],"mappings":"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"}
@@ -1,43 +0,0 @@
1
- import { VerifiedEvent, UnsignedEvent } from "nostr-tools";
2
- import { NostrSubscribe, Unsubscribe, EncryptFunction, DecryptFunction } from "./types";
3
- import { Session } from "./Session";
4
- export interface DeviceEntry {
5
- ephemeralPublicKey: string;
6
- /** Only stored locally, not published */
7
- ephemeralPrivateKey?: Uint8Array;
8
- sharedSecret: string;
9
- deviceId: string;
10
- deviceLabel: string;
11
- createdAt: number;
12
- /** Owner's pubkey for owner devices, delegate's own pubkey for delegate devices */
13
- identityPubkey: string;
14
- }
15
- /**
16
- * Manages a consolidated list of device invites (kind 10078).
17
- * Single atomic event containing all device invites for a user.
18
- * Uses union merge strategy for conflict resolution.
19
- */
20
- export declare class InviteList {
21
- readonly ownerPublicKey: string;
22
- private devices;
23
- private removedDeviceIds;
24
- constructor(ownerPublicKey: string, devices?: DeviceEntry[], removedDeviceIds?: string[]);
25
- createDevice(label: string, deviceId?: string): DeviceEntry;
26
- addDevice(device: DeviceEntry): void;
27
- removeDevice(deviceId: string): void;
28
- getDevice(deviceId: string): DeviceEntry | undefined;
29
- getAllDevices(): DeviceEntry[];
30
- getRemovedDeviceIds(): string[];
31
- updateDeviceLabel(deviceId: string, newLabel: string): void;
32
- getEvent(): UnsignedEvent;
33
- static fromEvent(event: VerifiedEvent): InviteList;
34
- serialize(): string;
35
- static deserialize(json: string): InviteList;
36
- merge(other: InviteList): InviteList;
37
- accept(deviceId: string, nostrSubscribe: NostrSubscribe, inviteePublicKey: string, encryptor: Uint8Array | EncryptFunction, inviteeDeviceId?: string): Promise<{
38
- session: Session;
39
- event: VerifiedEvent;
40
- }>;
41
- listen(decryptor: Uint8Array | DecryptFunction, nostrSubscribe: NostrSubscribe, onSession: (session: Session, identity: string, deviceId?: string, ourDeviceId?: string) => void): Unsubscribe;
42
- }
43
- //# sourceMappingURL=InviteList.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"InviteList.d.ts","sourceRoot":"","sources":["../src/InviteList.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAE,aAAa,EAAe,MAAM,aAAa,CAAA;AACtF,OAAO,EACL,cAAc,EACd,WAAW,EACX,eAAe,EACf,eAAe,EAGhB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAiCnC,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,yCAAyC;IACzC,mBAAmB,CAAC,EAAE,UAAU,CAAA;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,mFAAmF;IACnF,cAAc,EAAE,MAAM,CAAA;CACvB;AAMD;;;;GAIG;AACH,qBAAa,UAAU;aAKH,cAAc,EAAE,MAAM;IAJxC,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,gBAAgB,CAAyB;gBAG/B,cAAc,EAAE,MAAM,EACtC,OAAO,GAAE,WAAW,EAAO,EAC3B,gBAAgB,GAAE,MAAM,EAAO;IAQjC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW;IAa3D,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IASpC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIpD,aAAa,IAAI,WAAW,EAAE;IAI9B,mBAAmB,IAAI,MAAM,EAAE;IAI/B,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAO3D,QAAQ,IAAI,aAAa;IA6BzB,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU;IA0BlD,SAAS,IAAI,MAAM;IAenB,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAY5C,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU;IA0B9B,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAE,UAAU,GAAG,eAAe,EACvC,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,aAAa,CAAA;KAAE,CAAC;IAoCtD,MAAM,CACJ,SAAS,EAAE,UAAU,GAAG,eAAe,EACvC,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,CACT,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,KACjB,IAAI,GACR,WAAW;CAiDf"}
@@ -1,117 +0,0 @@
1
- import { Session } from './Session';
2
- import { NostrSubscribe } from './types';
3
- interface DeviceRecord {
4
- deviceId: string;
5
- publicKey: string;
6
- activeSession?: Session;
7
- inactiveSessions: Session[];
8
- isStale: boolean;
9
- staleTimestamp?: number;
10
- lastActivity?: number;
11
- }
12
- /**
13
- * Manages sessions for a single user across multiple devices
14
- * Structure: UserRecord → DeviceRecord → Sessions
15
- */
16
- export declare class UserRecord {
17
- readonly userId: string;
18
- private readonly nostrSubscribe;
19
- private deviceRecords;
20
- private isStale;
21
- private staleTimestamp?;
22
- constructor(userId: string, nostrSubscribe: NostrSubscribe);
23
- /**
24
- * Creates or updates a device record for this user
25
- */
26
- upsertDevice(deviceId: string, publicKey: string): DeviceRecord;
27
- /**
28
- * Gets a device record by deviceId
29
- */
30
- getDevice(deviceId: string): DeviceRecord | undefined;
31
- /**
32
- * Gets all device records for this user
33
- */
34
- getAllDevices(): DeviceRecord[];
35
- /**
36
- * Gets all active (non-stale) device records
37
- */
38
- getActiveDevices(): DeviceRecord[];
39
- /**
40
- * Removes a device record and closes all its sessions
41
- */
42
- removeDevice(deviceId: string): boolean;
43
- /**
44
- * Adds or updates a session for a specific device
45
- */
46
- upsertSession(deviceId: string, session: Session, publicKey?: string): void;
47
- /**
48
- * Gets the active session for a specific device
49
- */
50
- getActiveSession(deviceId: string): Session | undefined;
51
- /**
52
- * Gets all sessions (active + inactive) for a specific device
53
- */
54
- getDeviceSessions(deviceId: string): Session[];
55
- /**
56
- * Gets all active sessions across all devices for this user
57
- */
58
- getActiveSessions(): Session[];
59
- /**
60
- * Gets all sessions (active + inactive) across all devices
61
- */
62
- getAllSessions(): Session[];
63
- /**
64
- * Gets sessions that are ready to send messages
65
- */
66
- getSendableSessions(): Session[];
67
- /**
68
- * Marks a specific device as stale
69
- */
70
- markDeviceStale(deviceId: string): void;
71
- /**
72
- * Marks the entire user record as stale
73
- */
74
- markUserStale(): void;
75
- /**
76
- * Removes stale devices and sessions older than maxLatency
77
- */
78
- pruneStaleRecords(maxLatency: number): void;
79
- /**
80
- * Gets the most recently active device
81
- */
82
- getMostActiveDevice(): DeviceRecord | undefined;
83
- /**
84
- * Gets the preferred session (from most active device)
85
- */
86
- getPreferredSession(): Session | undefined;
87
- /**
88
- * Checks if this user has any active sessions
89
- */
90
- hasActiveSessions(): boolean;
91
- /**
92
- * Gets total count of devices
93
- */
94
- getDeviceCount(): number;
95
- /**
96
- * Gets total count of active sessions
97
- */
98
- getActiveSessionCount(): number;
99
- /**
100
- * Cleanup when destroying the user record
101
- */
102
- close(): void;
103
- /**
104
- * @deprecated Use upsertDevice instead
105
- */
106
- conditionalUpdate(deviceId: string, publicKey: string): void;
107
- /**
108
- * @deprecated Use upsertSession instead
109
- */
110
- insertSession(deviceId: string, session: Session): void;
111
- /**
112
- * Creates a new session for a device
113
- */
114
- createSession(deviceId: string, sharedSecret: Uint8Array, ourCurrentPrivateKey: Uint8Array, isInitiator: boolean, name?: string): Session;
115
- }
116
- export {};
117
- //# sourceMappingURL=UserRecord.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"UserRecord.d.ts","sourceRoot":"","sources":["../src/UserRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,UAAU;aAMH,MAAM,EAAE,MAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc;IANjC,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,cAAc,CAAC,CAAS;gBAGd,MAAM,EAAE,MAAM,EACb,cAAc,EAAE,cAAc;IAQjD;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY;IAyBtE;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI5D;;OAEG;IACI,aAAa,IAAI,YAAY,EAAE;IAItC;;OAEG;IACI,gBAAgB,IAAI,YAAY,EAAE;IAKzC;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAe9C;;OAEG;IACI,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAclF;;OAEG;IACI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAK9D;;OAEG;IACI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE;IAYrD;;OAEG;IACI,iBAAiB,IAAI,OAAO,EAAE;IAsBrC;;OAEG;IACI,cAAc,IAAI,OAAO,EAAE;IAalC;;OAEG;IACI,mBAAmB,IAAI,OAAO,EAAE;IAUvC;;OAEG;IACI,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ9C;;OAEG;IACI,aAAa,IAAI,IAAI;IAK5B;;OAEG;IACI,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAsBlD;;OAEG;IACI,mBAAmB,IAAI,YAAY,GAAG,SAAS;IAWtD;;OAEG;IACI,mBAAmB,IAAI,OAAO,GAAG,SAAS;IAKjD;;OAEG;IACI,iBAAiB,IAAI,OAAO;IAInC;;OAEG;IACI,cAAc,IAAI,MAAM;IAI/B;;OAEG;IACI,qBAAqB,IAAI,MAAM;IAItC;;OAEG;IACI,KAAK,IAAI,IAAI;IAYpB;;OAEG;IACI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAInE;;OAEG;IACI,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAI9D;;OAEG;IACI,aAAa,CAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,UAAU,EACxB,oBAAoB,EAAE,UAAU,EAChC,WAAW,EAAE,OAAO,EACpB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO;CAkBX"}