@qrlwallet/connect 0.1.0 → 2.0.0
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 +10 -31
- package/dist/index.d.mts +235 -113
- package/dist/index.d.ts +235 -113
- package/dist/index.js +806 -435
- package/dist/index.mjs +797 -434
- package/package.json +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,121 @@
|
|
|
1
1
|
import EventEmitter from 'eventemitter3';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Post-quantum handshake (v2).
|
|
5
|
+
*
|
|
6
|
+
* Flow:
|
|
7
|
+
* dApp relay wallet
|
|
8
|
+
* ────────────────────────────────────────────────────────────────────
|
|
9
|
+
* initiate() → (pk, sk)
|
|
10
|
+
* QR(cid, pk) rendered scan QR
|
|
11
|
+
* receiveQR(cid, pk)
|
|
12
|
+
* → SYNACK{ct, c0}
|
|
13
|
+
* ◄── SYNACK ─────── send
|
|
14
|
+
* onSynAck(cid, SYNACK)
|
|
15
|
+
* → ACK{c1}
|
|
16
|
+
* send ACK ──► ──► ack onAck(ACK)
|
|
17
|
+
*
|
|
18
|
+
* Data phase: encryptMessage / decryptMessage use direction-tagged counter
|
|
19
|
+
* nonces and AAD = H_tx || seq to bind every ciphertext to the transcript.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
interface Session {
|
|
23
|
+
cid: Uint8Array;
|
|
24
|
+
key: CryptoKey;
|
|
25
|
+
htx: Uint8Array;
|
|
26
|
+
sendDir: Uint8Array;
|
|
27
|
+
recvDir: Uint8Array;
|
|
28
|
+
sendSeq: number;
|
|
29
|
+
recvSeq: number;
|
|
30
|
+
}
|
|
31
|
+
/** Wire-safe persisted form for localStorage. */
|
|
32
|
+
interface PersistedSession {
|
|
33
|
+
cid: string;
|
|
34
|
+
kAeadRaw: string;
|
|
35
|
+
htx: string;
|
|
36
|
+
sendDir: string;
|
|
37
|
+
recvDir: string;
|
|
38
|
+
sendSeq: number;
|
|
39
|
+
recvSeq: number;
|
|
40
|
+
}
|
|
41
|
+
interface SynAckMessage {
|
|
42
|
+
type: KeyExchangeMessageType.SYNACK;
|
|
43
|
+
ct: string;
|
|
44
|
+
c0: string;
|
|
45
|
+
v: number;
|
|
46
|
+
}
|
|
47
|
+
interface AckMessage {
|
|
48
|
+
type: KeyExchangeMessageType.ACK;
|
|
49
|
+
c1: string;
|
|
50
|
+
v: number;
|
|
51
|
+
}
|
|
52
|
+
interface KeyExchangeEvents {
|
|
53
|
+
keys_exchanged: () => void;
|
|
54
|
+
step_change: (step: KeyExchangeMessageType) => void;
|
|
55
|
+
}
|
|
56
|
+
declare class KeyExchange extends EventEmitter<KeyExchangeEvents> {
|
|
57
|
+
private isOriginator;
|
|
58
|
+
private keypair;
|
|
59
|
+
private session;
|
|
60
|
+
private step;
|
|
61
|
+
private awaitingSynAck;
|
|
62
|
+
private awaitingAck;
|
|
63
|
+
private keysExchanged;
|
|
64
|
+
constructor(isOriginator: boolean, restored?: Session);
|
|
65
|
+
/**
|
|
66
|
+
* Originator (dApp) side: begin a fresh handshake by generating an
|
|
67
|
+
* ephemeral ML-KEM-768 keypair. Returns pk to embed in the QR URI.
|
|
68
|
+
*/
|
|
69
|
+
initiate(): Uint8Array;
|
|
70
|
+
/**
|
|
71
|
+
* Originator: handle a SYNACK received over the relay.
|
|
72
|
+
* Returns an ACK wire message to send, or null if the SYNACK was a
|
|
73
|
+
* duplicate (handshake already complete).
|
|
74
|
+
*/
|
|
75
|
+
onSynAck(cid: Uint8Array, msg: SynAckMessage): Promise<AckMessage | null>;
|
|
76
|
+
/**
|
|
77
|
+
* Responder (wallet) side: begin handshake from a scanned QR.
|
|
78
|
+
* Returns the SYNACK wire message to emit on the relay.
|
|
79
|
+
*/
|
|
80
|
+
receiveQR(cid: Uint8Array, pk: Uint8Array): Promise<SynAckMessage>;
|
|
81
|
+
/**
|
|
82
|
+
* Responder: verify an incoming ACK and finalize the session.
|
|
83
|
+
* Duplicates are silently ignored (handshake is idempotent).
|
|
84
|
+
*/
|
|
85
|
+
onAck(msg: AckMessage): Promise<void>;
|
|
86
|
+
/** Encrypt a string for the counterparty. Returns base64. */
|
|
87
|
+
encryptMessage(data: string): Promise<string>;
|
|
88
|
+
/** Decrypt a base64 ciphertext from the counterparty. */
|
|
89
|
+
decryptMessage(b64: string): Promise<string>;
|
|
90
|
+
/** Reset all state for a fresh handshake. Zeroes any live secret-key buffer. */
|
|
91
|
+
reset(): void;
|
|
92
|
+
private resetInternal;
|
|
93
|
+
areKeysExchanged(): boolean;
|
|
94
|
+
getSession(): Session | null;
|
|
95
|
+
getCurrentStep(): KeyExchangeMessageType;
|
|
96
|
+
/** Export the current session as a JSON-safe persisted record. */
|
|
97
|
+
exportPersisted(): Promise<PersistedSession | null>;
|
|
98
|
+
/** Rehydrate a Session from its persisted form. */
|
|
99
|
+
static sessionFromPersisted(p: PersistedSession): Promise<Session>;
|
|
100
|
+
}
|
|
101
|
+
|
|
3
102
|
/** dApp metadata shown to user in approval UI */
|
|
4
103
|
interface DAppMetadata {
|
|
5
104
|
name: string;
|
|
6
105
|
url: string;
|
|
7
106
|
icon?: string;
|
|
8
107
|
}
|
|
9
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* Stored session for reconnection.
|
|
110
|
+
*
|
|
111
|
+
* v2 persists the derived AES-256 session key (not the ML-KEM secret key) —
|
|
112
|
+
* the ML-KEM keypair is ephemeral and zeroized after the handshake.
|
|
113
|
+
* Re-pair (generate a new QR) to rotate the session key.
|
|
114
|
+
*/
|
|
10
115
|
interface DAppSession {
|
|
116
|
+
version: 2;
|
|
11
117
|
channelId: string;
|
|
12
|
-
|
|
13
|
-
otherPublicKey: string | null;
|
|
118
|
+
keyExchange: PersistedSession;
|
|
14
119
|
dappMetadata: DAppMetadata;
|
|
15
120
|
connectedAccounts: string[];
|
|
16
121
|
chainId: string;
|
|
@@ -26,7 +131,13 @@ interface PendingRequest {
|
|
|
26
131
|
reject: (error: Error) => void;
|
|
27
132
|
timestamp: number;
|
|
28
133
|
}
|
|
29
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* Key-exchange wire-message types.
|
|
136
|
+
*
|
|
137
|
+
* v2 note: only SYNACK (wallet→dApp) and ACK (dApp→wallet) are transmitted
|
|
138
|
+
* over the relay. The SYN step is carried by the QR code itself — the dApp's
|
|
139
|
+
* ML-KEM-768 encapsulation key is embedded in the URI, not sent on the wire.
|
|
140
|
+
*/
|
|
30
141
|
declare enum KeyExchangeMessageType {
|
|
31
142
|
SYN = "key_handshake_SYN",
|
|
32
143
|
SYNACK = "key_handshake_SYNACK",
|
|
@@ -164,14 +275,18 @@ declare class QRLConnectProvider extends EventEmitter<ProviderEvents> {
|
|
|
164
275
|
*/
|
|
165
276
|
newConnection(): Promise<string>;
|
|
166
277
|
/**
|
|
167
|
-
* Disconnect from wallet and clean up.
|
|
278
|
+
* Disconnect from wallet and clean up. Returns once the TERMINATE has
|
|
279
|
+
* either been flushed to the relay or the 800ms best-effort window has
|
|
280
|
+
* elapsed — the wallet gets an instant disconnect instead of landing in
|
|
281
|
+
* its stale-session grace period.
|
|
168
282
|
*/
|
|
169
|
-
disconnect(): void
|
|
283
|
+
disconnect(): Promise<void>;
|
|
170
284
|
}
|
|
171
285
|
|
|
172
286
|
/**
|
|
173
|
-
* Connection Manager
|
|
174
|
-
*
|
|
287
|
+
* Connection Manager — orchestrates socket lifecycle, the post-quantum
|
|
288
|
+
* handshake, encrypted message routing, and session persistence for the
|
|
289
|
+
* dApp side of QRL Connect v2.
|
|
175
290
|
*/
|
|
176
291
|
|
|
177
292
|
interface ConnectionManagerEvents {
|
|
@@ -188,7 +303,6 @@ interface ConnectionManagerEvents {
|
|
|
188
303
|
}
|
|
189
304
|
declare class ConnectionManager extends EventEmitter<ConnectionManagerEvents> {
|
|
190
305
|
private socketClient;
|
|
191
|
-
private ecies;
|
|
192
306
|
private keyExchange;
|
|
193
307
|
private status;
|
|
194
308
|
private channelId;
|
|
@@ -198,14 +312,11 @@ declare class ConnectionManager extends EventEmitter<ConnectionManagerEvents> {
|
|
|
198
312
|
private connectedAccounts;
|
|
199
313
|
private storageKey;
|
|
200
314
|
private unresponsiveTimer;
|
|
201
|
-
private synRetryTimer;
|
|
202
315
|
private failedReconnects;
|
|
203
|
-
private synSent;
|
|
204
|
-
private synAttempts;
|
|
205
316
|
private walletPresent;
|
|
317
|
+
private pendingRestore;
|
|
318
|
+
private messageQueue;
|
|
206
319
|
private static MAX_RECONNECT_FAILURES;
|
|
207
|
-
private static SYN_RETRY_MS;
|
|
208
|
-
private static MAX_SYN_ATTEMPTS;
|
|
209
320
|
constructor(options: {
|
|
210
321
|
dappMetadata: DAppMetadata;
|
|
211
322
|
relayUrl?: string;
|
|
@@ -215,110 +326,56 @@ declare class ConnectionManager extends EventEmitter<ConnectionManagerEvents> {
|
|
|
215
326
|
private setupSocketListeners;
|
|
216
327
|
private setupKeyExchangeListeners;
|
|
217
328
|
/**
|
|
218
|
-
* Generate
|
|
329
|
+
* Generate a new v2 connection URI. Rotates channel id and keypair.
|
|
330
|
+
* Returns a `qrlconnect://?q=…` URI safe for QR-rendering or deep-link.
|
|
219
331
|
*/
|
|
220
332
|
getConnectionURI(retryOnConflict?: boolean): Promise<string>;
|
|
221
333
|
/**
|
|
222
334
|
* Reconnect to an existing session.
|
|
335
|
+
* Returns false if there is nothing to restore.
|
|
223
336
|
*/
|
|
224
337
|
reconnect(): Promise<boolean>;
|
|
225
338
|
/**
|
|
226
|
-
* Send a JSON-RPC request to the wallet.
|
|
339
|
+
* Send a JSON-RPC request to the wallet (async, fire-and-forget).
|
|
227
340
|
*/
|
|
228
341
|
sendJsonRpc(request: JsonRpcRequest): void;
|
|
342
|
+
getStatus(): ConnectionStatus;
|
|
343
|
+
getAccounts(): string[];
|
|
344
|
+
getChainId(): string;
|
|
345
|
+
getChannelId(): string;
|
|
346
|
+
/** Check (sync) if a persisted session exists and has not expired. */
|
|
347
|
+
hasStoredSession(): boolean;
|
|
348
|
+
/**
|
|
349
|
+
* Best-effort TERMINATE delivery before we tear the socket down. Without
|
|
350
|
+
* awaiting, the socket.disconnect() below would win the race against the
|
|
351
|
+
* outbound emit, the wallet would only see `participants_changed:
|
|
352
|
+
* disconnect` and enter its stale-session grace period instead of an
|
|
353
|
+
* instant disconnect. Mirrors the wallet side's pattern.
|
|
354
|
+
*/
|
|
355
|
+
private flushTerminate;
|
|
229
356
|
/**
|
|
230
|
-
*
|
|
357
|
+
* Reset to a fresh channel + keypair. Sends TERMINATE to any live peer,
|
|
358
|
+
* drops the persisted session, and prepares a clean state for
|
|
359
|
+
* getConnectionURI() to be called again.
|
|
231
360
|
*/
|
|
361
|
+
resetForNewChannel(): Promise<void>;
|
|
362
|
+
disconnect(): Promise<void>;
|
|
363
|
+
private enqueueRelayMessage;
|
|
232
364
|
private handleRelayMessage;
|
|
233
|
-
private
|
|
365
|
+
private handleSynAck;
|
|
234
366
|
private handleDecryptedMessage;
|
|
235
|
-
/** Send a plaintext (unencrypted) message through the relay. */
|
|
236
367
|
private sendPlaintext;
|
|
237
|
-
/** Send an encrypted message through the relay. */
|
|
238
368
|
private sendEncrypted;
|
|
239
369
|
private startUnresponsiveTimer;
|
|
240
370
|
private clearUnresponsiveTimer;
|
|
241
|
-
private sendSYN;
|
|
242
|
-
private scheduleSynRetry;
|
|
243
|
-
private clearSynRetryTimer;
|
|
244
371
|
private setStatus;
|
|
245
372
|
private isDappParticipantConflictError;
|
|
246
373
|
private areArraysEqual;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
getChainId(): string;
|
|
250
|
-
getChannelId(): string;
|
|
251
|
-
/** Check if a stored session exists (without loading/restoring it). */
|
|
252
|
-
hasStoredSession(): boolean;
|
|
253
|
-
/**
|
|
254
|
-
* Reset the connection and create a new channel for a fresh pairing.
|
|
255
|
-
* Disconnects any existing session, generates a new channel ID and keys.
|
|
256
|
-
*/
|
|
257
|
-
resetForNewChannel(): void;
|
|
258
|
-
/** Disconnect and clean up. */
|
|
259
|
-
disconnect(): void;
|
|
260
|
-
private saveSession;
|
|
261
|
-
private loadSession;
|
|
374
|
+
private persistSession;
|
|
375
|
+
private readStoredSession;
|
|
262
376
|
private clearSession;
|
|
263
377
|
}
|
|
264
378
|
|
|
265
|
-
/**
|
|
266
|
-
* ECIES encryption/decryption client.
|
|
267
|
-
* Adapted from MetaMask SDK's ECIES.ts pattern.
|
|
268
|
-
*/
|
|
269
|
-
declare class ECIESClient {
|
|
270
|
-
private privateKey;
|
|
271
|
-
constructor(existingPrivateKey?: string);
|
|
272
|
-
/** Get public key as hex string */
|
|
273
|
-
getPublicKey(): string;
|
|
274
|
-
/** Get private key as hex string (for session persistence) */
|
|
275
|
-
getPrivateKeyHex(): string;
|
|
276
|
-
/** Encrypt a string message for the given public key. Returns base64. */
|
|
277
|
-
encrypt(data: string, otherPublicKey: string): string;
|
|
278
|
-
/** Decrypt a base64-encoded message using our private key. */
|
|
279
|
-
decrypt(encryptedBase64: string): string;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Key Exchange - 3-step SYN/SYNACK/ACK handshake protocol.
|
|
284
|
-
* Adapted from MetaMask SDK's KeyExchange.ts.
|
|
285
|
-
*/
|
|
286
|
-
|
|
287
|
-
interface KeyExchangeEvents {
|
|
288
|
-
keys_exchanged: () => void;
|
|
289
|
-
step_change: (step: KeyExchangeMessageType) => void;
|
|
290
|
-
}
|
|
291
|
-
declare class KeyExchange extends EventEmitter<KeyExchangeEvents> {
|
|
292
|
-
private ecies;
|
|
293
|
-
private otherPublicKey;
|
|
294
|
-
private keysExchanged;
|
|
295
|
-
private awaitingSynAck;
|
|
296
|
-
private awaitingAck;
|
|
297
|
-
private step;
|
|
298
|
-
private isOriginator;
|
|
299
|
-
constructor(ecies: ECIESClient, isOriginator: boolean, otherPublicKey?: string);
|
|
300
|
-
/** Get the SYN message to start the handshake (originator/dApp side). */
|
|
301
|
-
createSYN(): object;
|
|
302
|
-
/**
|
|
303
|
-
* Process an incoming key exchange message.
|
|
304
|
-
* Returns a response message to send back, or null if handshake is complete.
|
|
305
|
-
*/
|
|
306
|
-
onMessage(message: {
|
|
307
|
-
type: KeyExchangeMessageType;
|
|
308
|
-
pubkey?: string;
|
|
309
|
-
v?: number;
|
|
310
|
-
}): object | null;
|
|
311
|
-
/** Encrypt a message for the counterparty. */
|
|
312
|
-
encryptMessage(data: string): string;
|
|
313
|
-
/** Decrypt a message from the counterparty. */
|
|
314
|
-
decryptMessage(encryptedBase64: string): string;
|
|
315
|
-
/** Reset key exchange state for a fresh handshake (e.g. new QR code). */
|
|
316
|
-
reset(): void;
|
|
317
|
-
areKeysExchanged(): boolean;
|
|
318
|
-
getOtherPublicKey(): string | null;
|
|
319
|
-
getCurrentStep(): KeyExchangeMessageType;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
379
|
/**
|
|
323
380
|
* Socket.IO client wrapper for relay communication.
|
|
324
381
|
*/
|
|
@@ -334,24 +391,44 @@ interface SocketClientEvents {
|
|
|
334
391
|
}) => void;
|
|
335
392
|
error: (err: Error) => void;
|
|
336
393
|
}
|
|
394
|
+
interface JoinResult {
|
|
395
|
+
bufferedMessages: unknown[];
|
|
396
|
+
/**
|
|
397
|
+
* Base64-encoded KEM public key the relay has bound to this channel.
|
|
398
|
+
* Populated for wallet joins (v2 protocol). `null` if the dApp hasn't
|
|
399
|
+
* registered a PK yet — wallet callers must treat this as a retry signal.
|
|
400
|
+
*/
|
|
401
|
+
channelPublicKey: string | null;
|
|
402
|
+
}
|
|
337
403
|
declare class SocketClient extends EventEmitter<SocketClientEvents> {
|
|
338
404
|
private socket;
|
|
339
405
|
private relayUrl;
|
|
340
406
|
private channelId;
|
|
341
407
|
private clientType;
|
|
408
|
+
private publicKeyBase64;
|
|
342
409
|
private seq;
|
|
343
410
|
private pendingJoin;
|
|
344
411
|
constructor(relayUrl: string, clientType: 'dapp' | 'wallet');
|
|
412
|
+
/**
|
|
413
|
+
* dApp-only: stash the PK so it gets uploaded on every join_channel
|
|
414
|
+
* attempt (including auto-rejoins after reconnect).
|
|
415
|
+
*/
|
|
416
|
+
setPublicKey(publicKeyBase64: string): void;
|
|
345
417
|
/**
|
|
346
418
|
* Connect to the relay server.
|
|
347
419
|
*/
|
|
348
420
|
connect(): void;
|
|
349
421
|
/**
|
|
350
|
-
*
|
|
422
|
+
* Resolve or reject the currently-pending `joinChannel` promise, if it
|
|
423
|
+
* matches the given channelId. Clears the watchdog timer on settle so
|
|
424
|
+
* it doesn't fire after the fact.
|
|
351
425
|
*/
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
426
|
+
private settlePendingJoin;
|
|
427
|
+
/**
|
|
428
|
+
* Join a relay channel. Resolves with any buffered messages plus the
|
|
429
|
+
* dApp's public key bound to the channel (for wallet joins).
|
|
430
|
+
*/
|
|
431
|
+
joinChannel(channelId: string): Promise<JoinResult>;
|
|
355
432
|
private joinChannelNow;
|
|
356
433
|
/**
|
|
357
434
|
* Send a message through the relay.
|
|
@@ -372,23 +449,67 @@ declare class SocketClient extends EventEmitter<SocketClientEvents> {
|
|
|
372
449
|
getChannelId(): string | null;
|
|
373
450
|
}
|
|
374
451
|
|
|
375
|
-
interface QRConnectParams {
|
|
376
|
-
channelId: string;
|
|
377
|
-
pubKey: string;
|
|
378
|
-
name: string;
|
|
379
|
-
url: string;
|
|
380
|
-
icon?: string;
|
|
381
|
-
chainId: string;
|
|
382
|
-
relayUrl: string;
|
|
383
|
-
}
|
|
384
452
|
/**
|
|
385
|
-
*
|
|
453
|
+
* v2 QR URI codec (PQP2).
|
|
454
|
+
*
|
|
455
|
+
* Format: qrlconnect://?q=<base45(PQP2 || cid || fp)>[&r=<relayUrl>]
|
|
456
|
+
*
|
|
457
|
+
* PQP2 = "PQP2" magic (4 B)
|
|
458
|
+
* cid = 16 bytes (UUIDv4 raw) (16 B)
|
|
459
|
+
* fp = SHA-256("pq-fp/v2" || cid || pk) (full 32B) (32 B)
|
|
460
|
+
* total (52 B)
|
|
461
|
+
*
|
|
462
|
+
* 52 bytes → ~78 alphanumeric chars after base45 → URI under 150 chars →
|
|
463
|
+
* fits a version-5 QR at ECC-M. Scannable from any 2015-vintage camera.
|
|
464
|
+
*
|
|
465
|
+
* Security: the public key is NOT carried in the QR. It's uploaded by the
|
|
466
|
+
* dApp to the relay at channel creation, the relay binds it to the cid, and
|
|
467
|
+
* the wallet fetches it via the join_channel ack. The 32-byte fp acts as
|
|
468
|
+
* the out-of-band commitment: the wallet rejects the PK served by the relay
|
|
469
|
+
* unless SHA-256("pq-fp/v2" || cid || pk) matches the fp from the QR.
|
|
470
|
+
* Full-width SHA-256 (2^128 collision resistance) rules out brute-force
|
|
471
|
+
* substitution of a maliciously-crafted PK with the same fingerprint.
|
|
472
|
+
*
|
|
473
|
+
* Legacy v2.0 URIs (magic=PQP1, 1208-byte blob with embedded PK) are
|
|
474
|
+
* rejected with a clear error by parseConnectionURI — this is a hard
|
|
475
|
+
* break before 2.0.0 ships, no backcompat.
|
|
386
476
|
*/
|
|
387
|
-
declare
|
|
477
|
+
declare const CID_LEN = 16;
|
|
478
|
+
declare const FP_LEN = 32;
|
|
479
|
+
declare const BLOB_LEN: number;
|
|
388
480
|
/**
|
|
389
|
-
*
|
|
481
|
+
* Compute the full 32-byte fingerprint binding (label || cid || pk).
|
|
482
|
+
* Exported so the wallet side can re-derive and verify.
|
|
390
483
|
*/
|
|
391
|
-
declare function
|
|
484
|
+
declare function computeFingerprint(cid: Uint8Array, pk: Uint8Array): Promise<Uint8Array>;
|
|
485
|
+
/**
|
|
486
|
+
* Constant-time comparison of two byte arrays. Both must be the same length.
|
|
487
|
+
* The verifier MUST use this rather than `===` or `indexOf` so timing signals
|
|
488
|
+
* don't leak which byte of `fp` diverged first.
|
|
489
|
+
*/
|
|
490
|
+
declare function fingerprintEquals(a: Uint8Array, b: Uint8Array): boolean;
|
|
491
|
+
/**
|
|
492
|
+
* Encode (cid, pk) as a qrlconnect:// URI. Note the PK is not stored in the
|
|
493
|
+
* URI — we compute its fingerprint and embed only that. The caller must
|
|
494
|
+
* upload the PK to the relay separately before publishing this URI.
|
|
495
|
+
*
|
|
496
|
+
* The optional `relayUrl` rides as a sibling query param (not inside the
|
|
497
|
+
* fp-bound blob) so a tampered relay can cause the pairing to fail but
|
|
498
|
+
* cannot substitute the PK — the fp still pins that.
|
|
499
|
+
*/
|
|
500
|
+
declare function generateConnectionURI(cid: Uint8Array, pk: Uint8Array, relayUrl?: string): Promise<string>;
|
|
501
|
+
interface ParsedURI {
|
|
502
|
+
cid: Uint8Array;
|
|
503
|
+
fp: Uint8Array;
|
|
504
|
+
relayUrl?: string;
|
|
505
|
+
}
|
|
506
|
+
declare function parseConnectionURI(uri: string): Promise<ParsedURI>;
|
|
507
|
+
/** Convert 16 raw cid bytes to RFC 4122 UUID hex string. */
|
|
508
|
+
declare function cidToString(cid: Uint8Array): string;
|
|
509
|
+
/** Convert RFC 4122 UUID string to 16 raw cid bytes. */
|
|
510
|
+
declare function cidFromString(s: string): Uint8Array;
|
|
511
|
+
/** Generate 16 random bytes for a fresh channel ID. */
|
|
512
|
+
declare function cidRandom(): Uint8Array;
|
|
392
513
|
|
|
393
514
|
/**
|
|
394
515
|
* Detect if the current browser is on a mobile device.
|
|
@@ -401,9 +522,10 @@ declare function isMobileBrowser(): boolean;
|
|
|
401
522
|
declare function getAppStoreUrl(): string;
|
|
402
523
|
|
|
403
524
|
declare const DEFAULT_RELAY_URL = "https://qrlwallet.com";
|
|
525
|
+
declare const PROTOCOL_VERSION = 2;
|
|
404
526
|
/** RPC methods that require user approval in the wallet */
|
|
405
527
|
declare const RESTRICTED_METHODS: Set<string>;
|
|
406
528
|
/** RPC methods that can be auto-proxied without approval */
|
|
407
529
|
declare const UNRESTRICTED_METHODS: Set<string>;
|
|
408
530
|
|
|
409
|
-
export { ConnectionManager, ConnectionStatus, type DAppMetadata, type DAppSession, DEFAULT_RELAY_URL,
|
|
531
|
+
export { type AckMessage, BLOB_LEN, CID_LEN, ConnectionManager, ConnectionStatus, type DAppMetadata, type DAppSession, DEFAULT_RELAY_URL, FP_LEN, type JsonRpcRequest, type JsonRpcResponse, KeyExchange, KeyExchangeMessageType, MessageType, PROTOCOL_VERSION, type ParsedURI, type PendingRequest, type PersistedSession, type ProviderEvents, QRLConnectProvider as QRLConnect, type QRLConnectOptions, QRLConnectProvider, RESTRICTED_METHODS, type RelayMessage, type Session, SocketClient, type SynAckMessage, UNRESTRICTED_METHODS, cidFromString, cidRandom, cidToString, computeFingerprint, fingerprintEquals, generateConnectionURI, getAppStoreUrl, isMobileBrowser, parseConnectionURI };
|