@le-space/p2pass 0.1.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/LICENSE +21 -0
- package/README.md +258 -0
- package/dist/backup/registry-backup.d.ts +26 -0
- package/dist/backup/registry-backup.js +51 -0
- package/dist/identity/identity-service.d.ts +116 -0
- package/dist/identity/identity-service.js +524 -0
- package/dist/identity/mode-detector.d.ts +29 -0
- package/dist/identity/mode-detector.js +124 -0
- package/dist/identity/signing-preference.d.ts +30 -0
- package/dist/identity/signing-preference.js +55 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +91 -0
- package/dist/p2p/setup.d.ts +48 -0
- package/dist/p2p/setup.js +283 -0
- package/dist/recovery/ipns-key.d.ts +41 -0
- package/dist/recovery/ipns-key.js +127 -0
- package/dist/recovery/manifest.d.ts +106 -0
- package/dist/recovery/manifest.js +243 -0
- package/dist/registry/device-registry.d.ts +122 -0
- package/dist/registry/device-registry.js +275 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.js +46 -0
- package/dist/registry/manager.d.ts +76 -0
- package/dist/registry/manager.js +376 -0
- package/dist/registry/pairing-protocol.d.ts +61 -0
- package/dist/registry/pairing-protocol.js +653 -0
- package/dist/ucan/storacha-auth.d.ts +45 -0
- package/dist/ucan/storacha-auth.js +164 -0
- package/dist/ui/StorachaFab.svelte +134 -0
- package/dist/ui/StorachaFab.svelte.d.ts +23 -0
- package/dist/ui/StorachaIntegration.svelte +2467 -0
- package/dist/ui/StorachaIntegration.svelte.d.ts +23 -0
- package/dist/ui/fonts/dm-mono-400.ttf +0 -0
- package/dist/ui/fonts/dm-mono-500.ttf +0 -0
- package/dist/ui/fonts/dm-sans-400.ttf +0 -0
- package/dist/ui/fonts/dm-sans-500.ttf +0 -0
- package/dist/ui/fonts/dm-sans-600.ttf +0 -0
- package/dist/ui/fonts/dm-sans-700.ttf +0 -0
- package/dist/ui/fonts/epilogue-400.ttf +0 -0
- package/dist/ui/fonts/epilogue-500.ttf +0 -0
- package/dist/ui/fonts/epilogue-600.ttf +0 -0
- package/dist/ui/fonts/epilogue-700.ttf +0 -0
- package/dist/ui/fonts/storacha-fonts.css +152 -0
- package/dist/ui/storacha-backup.d.ts +44 -0
- package/dist/ui/storacha-backup.js +218 -0
- package/package.json +112 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MultiDeviceManager - Unified class for multi-device OrbitDB with WebAuthn
|
|
3
|
+
*
|
|
4
|
+
* Copied from orbitdb-identity-provider-webauthn-did/src/multi-device/manager.js
|
|
5
|
+
* with imports adapted for the @le-space/p2pass package.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
openDeviceRegistry,
|
|
10
|
+
registerDevice,
|
|
11
|
+
listDevices,
|
|
12
|
+
getDeviceByCredentialId,
|
|
13
|
+
getDeviceByDID,
|
|
14
|
+
grantDeviceWriteAccess,
|
|
15
|
+
revokeDeviceAccess,
|
|
16
|
+
coseToJwk,
|
|
17
|
+
} from './device-registry.js';
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
detectDeviceLabel,
|
|
21
|
+
sendPairingRequest,
|
|
22
|
+
registerLinkDeviceHandler,
|
|
23
|
+
LINK_DEVICE_PROTOCOL,
|
|
24
|
+
sortPairingMultiaddrs,
|
|
25
|
+
pairingFlow,
|
|
26
|
+
PAIRING_HINT_ADDR_CAP,
|
|
27
|
+
} from './pairing-protocol.js';
|
|
28
|
+
|
|
29
|
+
export class MultiDeviceManager {
|
|
30
|
+
/**
|
|
31
|
+
* @param {string|{ peerId: string, multiaddrs?: string[] }} payload
|
|
32
|
+
* @returns {{ peerId: string, multiaddrs: string[] }}
|
|
33
|
+
*/
|
|
34
|
+
static _normalizeLinkPayload(payload) {
|
|
35
|
+
if (typeof payload === 'string') {
|
|
36
|
+
const peerId = payload.trim();
|
|
37
|
+
if (!peerId) throw new Error('peerId is empty');
|
|
38
|
+
return { peerId, multiaddrs: [] };
|
|
39
|
+
}
|
|
40
|
+
if (payload && typeof payload === 'object' && typeof payload.peerId === 'string') {
|
|
41
|
+
return {
|
|
42
|
+
peerId: payload.peerId.trim(),
|
|
43
|
+
multiaddrs: Array.isArray(payload.multiaddrs) ? payload.multiaddrs : [],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
throw new Error('linkToDevice: expected a peer id string or { peerId, multiaddrs? }');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
constructor() {
|
|
50
|
+
this._credential = null;
|
|
51
|
+
this._orbitdb = null;
|
|
52
|
+
this._ipfs = null;
|
|
53
|
+
this._libp2p = null;
|
|
54
|
+
this._identity = null;
|
|
55
|
+
this._devicesDb = null;
|
|
56
|
+
this._dbAddress = null;
|
|
57
|
+
this._onPairingRequest = null;
|
|
58
|
+
this._onDeviceLinked = null;
|
|
59
|
+
this._onDeviceJoined = null;
|
|
60
|
+
this._listenersSetup = false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static async create(config) {
|
|
64
|
+
const manager = new MultiDeviceManager();
|
|
65
|
+
await manager._init(config);
|
|
66
|
+
return manager;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static async createFromExisting(config) {
|
|
70
|
+
const manager = new MultiDeviceManager();
|
|
71
|
+
manager._credential = config.credential;
|
|
72
|
+
manager._orbitdb = config.orbitdb;
|
|
73
|
+
manager._ipfs = config.ipfs;
|
|
74
|
+
manager._libp2p = config.libp2p;
|
|
75
|
+
manager._identity = config.identity;
|
|
76
|
+
manager._onPairingRequest = config.onPairingRequest || null;
|
|
77
|
+
manager._onDeviceLinked = config.onDeviceLinked || null;
|
|
78
|
+
manager._onDeviceJoined = config.onDeviceJoined || null;
|
|
79
|
+
return manager;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async _init(config) {
|
|
83
|
+
if (!config.credential) throw new Error('credential is required');
|
|
84
|
+
this._credential = config.credential;
|
|
85
|
+
this._onPairingRequest = config.onPairingRequest || null;
|
|
86
|
+
this._onDeviceLinked = config.onDeviceLinked || null;
|
|
87
|
+
this._onDeviceJoined = config.onDeviceJoined || null;
|
|
88
|
+
if (config.orbitdb) this._orbitdb = config.orbitdb;
|
|
89
|
+
if (config.ipfs) this._ipfs = config.ipfs;
|
|
90
|
+
if (config.libp2p) this._libp2p = config.libp2p;
|
|
91
|
+
if (config.identity) this._identity = config.identity;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
_getPublicKey() {
|
|
95
|
+
const { x, y } = this._credential.publicKey || {};
|
|
96
|
+
return x && y ? coseToJwk(x, y) : null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async _finalizeDb() {
|
|
100
|
+
await this._setupSyncListeners();
|
|
101
|
+
if (this._onPairingRequest) {
|
|
102
|
+
// Unregister existing handler before re-registering (e.g. after DB reopen)
|
|
103
|
+
try {
|
|
104
|
+
await this._libp2p.unhandle(LINK_DEVICE_PROTOCOL);
|
|
105
|
+
} catch {
|
|
106
|
+
/* not registered */
|
|
107
|
+
}
|
|
108
|
+
console.log(
|
|
109
|
+
'[manager] Registering link device handler for peer:',
|
|
110
|
+
this._libp2p?.peerId?.toString()
|
|
111
|
+
);
|
|
112
|
+
await registerLinkDeviceHandler(
|
|
113
|
+
this._libp2p,
|
|
114
|
+
this._devicesDb,
|
|
115
|
+
this._onPairingRequest,
|
|
116
|
+
this._onDeviceLinked
|
|
117
|
+
);
|
|
118
|
+
console.log('[manager] Link device handler registered');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async createNew() {
|
|
123
|
+
if (!this._orbitdb) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
'orbitdb not provided. Pass orbitdb, ipfs, libp2p, identity in config, or use createFromExisting().'
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this._devicesDb = await openDeviceRegistry(this._orbitdb, this._identity.id);
|
|
130
|
+
this._dbAddress = this._devicesDb.address;
|
|
131
|
+
|
|
132
|
+
await registerDevice(this._devicesDb, {
|
|
133
|
+
credential_id:
|
|
134
|
+
this._credential?.credentialId ||
|
|
135
|
+
this._credential?.id ||
|
|
136
|
+
this._libp2p?.peerId?.toString() ||
|
|
137
|
+
'unknown',
|
|
138
|
+
public_key: this._getPublicKey(),
|
|
139
|
+
device_label: detectDeviceLabel(),
|
|
140
|
+
created_at: Date.now(),
|
|
141
|
+
status: 'active',
|
|
142
|
+
ed25519_did: this._identity.id,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await this.syncDevices();
|
|
146
|
+
await this._finalizeDb();
|
|
147
|
+
|
|
148
|
+
return { dbAddress: this._dbAddress, identity: this._identity };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async _setupSyncListeners() {
|
|
152
|
+
if (this._listenersSetup || !this._devicesDb) {
|
|
153
|
+
console.log('[manager] _setupSyncListeners: skipping (already set up or no db)');
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this._listenersSetup = true;
|
|
157
|
+
|
|
158
|
+
console.log('[manager] Setting up sync listeners for DB:', this._devicesDb.address?.toString());
|
|
159
|
+
|
|
160
|
+
if (this._onDeviceJoined) {
|
|
161
|
+
console.log('[manager] Subscribing to join events');
|
|
162
|
+
this._devicesDb.events.on('join', async (peerId, details) => {
|
|
163
|
+
console.log('[manager] JOIN event fired:', peerId.toString(), details);
|
|
164
|
+
if (this._onDeviceJoined) {
|
|
165
|
+
this._onDeviceJoined(peerId.toString(), details);
|
|
166
|
+
}
|
|
167
|
+
if (this._onDeviceLinked) {
|
|
168
|
+
const devices = await listDevices(this._devicesDb);
|
|
169
|
+
console.log('[manager] JOIN: Refreshing device list, found:', devices.length);
|
|
170
|
+
for (const device of devices) {
|
|
171
|
+
this._onDeviceLinked(device);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this._devicesDb.events.on('update', async (_entry) => {
|
|
178
|
+
console.log('[manager] UPDATE event fired, _onDeviceLinked:', !!this._onDeviceLinked);
|
|
179
|
+
if (this._onDeviceLinked) {
|
|
180
|
+
const devices = await listDevices(this._devicesDb);
|
|
181
|
+
console.log('[manager] UPDATE: Devices found:', devices.length);
|
|
182
|
+
for (const device of devices) {
|
|
183
|
+
console.log(
|
|
184
|
+
'[manager] UPDATE: Triggering callback for device:',
|
|
185
|
+
device.device_label,
|
|
186
|
+
device.ed25519_did,
|
|
187
|
+
'status:',
|
|
188
|
+
device.status
|
|
189
|
+
);
|
|
190
|
+
this._onDeviceLinked(device);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
console.log('[manager] Sync listeners setup complete');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async _waitForEntries(timeoutMs = 15000) {
|
|
198
|
+
const start = Date.now();
|
|
199
|
+
while (Date.now() - start < timeoutMs) {
|
|
200
|
+
const entries = await listDevices(this._devicesDb);
|
|
201
|
+
if (entries.length > 0) {
|
|
202
|
+
console.log(
|
|
203
|
+
'[manager] _waitForEntries: found',
|
|
204
|
+
entries.length,
|
|
205
|
+
'entries after',
|
|
206
|
+
Date.now() - start,
|
|
207
|
+
'ms'
|
|
208
|
+
);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
212
|
+
}
|
|
213
|
+
console.warn('[manager] _waitForEntries: timed out after', timeoutMs, 'ms with 0 entries');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async openExistingDb(dbAddress) {
|
|
217
|
+
if (!this._orbitdb) {
|
|
218
|
+
throw new Error('orbitdb not provided. Pass orbitdb, ipfs, libp2p, identity in config.');
|
|
219
|
+
}
|
|
220
|
+
this._devicesDb = await openDeviceRegistry(this._orbitdb, this._identity.id, dbAddress);
|
|
221
|
+
this._dbAddress = this._devicesDb.address;
|
|
222
|
+
await this._finalizeDb();
|
|
223
|
+
return { dbAddress: this._dbAddress, identity: this._identity };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Link to Device A by peer id. Uses addresses already in libp2p’s peer store (e.g. from pubsub
|
|
228
|
+
* discovery + autodial). Optional legacy shape: `{ peerId, multiaddrs }` for explicit dials.
|
|
229
|
+
* @param {string|{ peerId: string, multiaddrs?: string[] }} qrPayload
|
|
230
|
+
*/
|
|
231
|
+
async linkToDevice(qrPayload) {
|
|
232
|
+
if (!this._orbitdb) {
|
|
233
|
+
throw new Error('orbitdb not provided. Pass orbitdb, ipfs, libp2p, identity in config.');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const { peerId, multiaddrs } = MultiDeviceManager._normalizeLinkPayload(qrPayload);
|
|
237
|
+
console.log('[linkToDevice] Target peerId:', peerId, 'hint addrs:', multiaddrs.length);
|
|
238
|
+
console.log('[linkToDevice] My peerId:', this._libp2p?.peerId?.toString());
|
|
239
|
+
|
|
240
|
+
const result = await sendPairingRequest(
|
|
241
|
+
this._libp2p,
|
|
242
|
+
peerId,
|
|
243
|
+
{
|
|
244
|
+
id: this._identity.id,
|
|
245
|
+
orbitdbIdentityId: this._orbitdb?.identity?.id || null,
|
|
246
|
+
credentialId:
|
|
247
|
+
this._credential?.credentialId || this._credential?.id || this._libp2p.peerId.toString(),
|
|
248
|
+
publicKey: null,
|
|
249
|
+
deviceLabel: detectDeviceLabel(),
|
|
250
|
+
},
|
|
251
|
+
multiaddrs
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
pairingFlow('BOB', 'linkToDevice: sendPairingRequest finished', {
|
|
255
|
+
type: result?.type,
|
|
256
|
+
hasOrbitdbAddress: result?.type === 'granted' && !!result.orbitdbAddress,
|
|
257
|
+
reason: result?.reason,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
if (result.type === 'rejected') return result;
|
|
261
|
+
|
|
262
|
+
console.log('[linkToDevice] Got granted, opening database...');
|
|
263
|
+
pairingFlow('BOB', 'opening shared OrbitDB registry at address from Alice…');
|
|
264
|
+
this._devicesDb = await openDeviceRegistry(
|
|
265
|
+
this._orbitdb,
|
|
266
|
+
this._identity.id,
|
|
267
|
+
result.orbitdbAddress
|
|
268
|
+
);
|
|
269
|
+
this._dbAddress = this._devicesDb.address;
|
|
270
|
+
console.log('[linkToDevice] Database opened, waiting for Device A entries to sync...');
|
|
271
|
+
|
|
272
|
+
this._listenersSetup = false;
|
|
273
|
+
await this._setupSyncListeners();
|
|
274
|
+
await this._waitForEntries(15000);
|
|
275
|
+
await this._finalizeDb();
|
|
276
|
+
|
|
277
|
+
pairingFlow(
|
|
278
|
+
'BOB',
|
|
279
|
+
'linkToDevice complete: registry open + sync listeners + handler re-registered',
|
|
280
|
+
{
|
|
281
|
+
dbAddress: String(this._dbAddress || '').slice(0, 56) + '…',
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
return { type: 'granted', dbAddress: this._dbAddress };
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
getDevicesDb() {
|
|
288
|
+
return this._devicesDb;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
getPeerInfo() {
|
|
292
|
+
if (!this._libp2p) throw new Error('Libp2p not initialized');
|
|
293
|
+
const peerId = this._libp2p.peerId.toString();
|
|
294
|
+
const filtered = this._libp2p.getMultiaddrs().filter((ma) => {
|
|
295
|
+
const lower = ma.toString().toLowerCase();
|
|
296
|
+
return (
|
|
297
|
+
(lower.includes('/ws/') ||
|
|
298
|
+
lower.includes('/wss/') ||
|
|
299
|
+
lower.includes('/webtransport') ||
|
|
300
|
+
lower.includes('/p2p-circuit')) &&
|
|
301
|
+
!lower.includes('/webrtc') &&
|
|
302
|
+
!lower.includes('/ip4/127.') &&
|
|
303
|
+
!lower.includes('/ip4/localhost') &&
|
|
304
|
+
!lower.includes('/ip6/::1')
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
const sorted = sortPairingMultiaddrs(filtered);
|
|
308
|
+
const capped = sorted.slice(0, PAIRING_HINT_ADDR_CAP);
|
|
309
|
+
const multiaddrs = capped.map((ma) => ma.toString());
|
|
310
|
+
return { peerId, multiaddrs };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async listDevices() {
|
|
314
|
+
if (!this._devicesDb) return [];
|
|
315
|
+
await this.syncDevices();
|
|
316
|
+
return listDevices(this._devicesDb);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async syncDevices() {
|
|
320
|
+
// OrbitDB syncs automatically with connected peers (sync: true in openDeviceRegistry).
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async revokeDevice(did) {
|
|
324
|
+
if (!this._devicesDb) throw new Error('Device registry not initialized');
|
|
325
|
+
await revokeDeviceAccess(this._devicesDb, did);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async processIncomingPairingRequest(requestMsg) {
|
|
329
|
+
if (!this._devicesDb) throw new Error('Device registry not initialized');
|
|
330
|
+
const { identity } = requestMsg;
|
|
331
|
+
|
|
332
|
+
const isKnown =
|
|
333
|
+
(await getDeviceByCredentialId(this._devicesDb, identity.credentialId)) ||
|
|
334
|
+
(await getDeviceByDID(this._devicesDb, identity.id));
|
|
335
|
+
|
|
336
|
+
if (isKnown) {
|
|
337
|
+
return { type: 'granted', orbitdbAddress: this._dbAddress };
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const decision = this._onPairingRequest ? await this._onPairingRequest(requestMsg) : 'granted';
|
|
341
|
+
|
|
342
|
+
if (decision === 'granted') {
|
|
343
|
+
await grantDeviceWriteAccess(this._devicesDb, identity.id);
|
|
344
|
+
await registerDevice(this._devicesDb, {
|
|
345
|
+
credential_id: identity.credentialId,
|
|
346
|
+
public_key: identity.publicKey || null,
|
|
347
|
+
device_label: identity.deviceLabel || 'Unknown Device',
|
|
348
|
+
created_at: Date.now(),
|
|
349
|
+
status: 'active',
|
|
350
|
+
ed25519_did: identity.id,
|
|
351
|
+
});
|
|
352
|
+
return { type: 'granted', orbitdbAddress: this._dbAddress };
|
|
353
|
+
}
|
|
354
|
+
return { type: 'rejected', reason: 'User cancelled' };
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** Get the underlying registry DB (for extended operations like delegation storage). */
|
|
358
|
+
getRegistryDb() {
|
|
359
|
+
return this._devicesDb;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/** Get the registry DB address. */
|
|
363
|
+
getDbAddress() {
|
|
364
|
+
return this._dbAddress;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
async close() {
|
|
368
|
+
try {
|
|
369
|
+
if (this._devicesDb) await this._devicesDb.close();
|
|
370
|
+
if (this._orbitdb) await this._orbitdb.stop();
|
|
371
|
+
if (this._ipfs) await this._ipfs.stop();
|
|
372
|
+
} catch (error) {
|
|
373
|
+
console.warn('Error during cleanup:', error);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured pairing debug — filter the browser console by `[pairing-flow]`.
|
|
3
|
+
* @param {'ALICE'|'BOB'} role
|
|
4
|
+
* @param {string} phase
|
|
5
|
+
* @param {Record<string, unknown>|string} [detail]
|
|
6
|
+
*/
|
|
7
|
+
export function pairingFlow(role: "ALICE" | "BOB", phase: string, detail?: Record<string, unknown> | string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Order dial candidates so cross-browser linking usually tries stable paths first:
|
|
10
|
+
* public DNS + WSS, then WS/TCP via relay; webrtc-direct and LAN-only last.
|
|
11
|
+
* @param {import('@multiformats/multiaddr').Multiaddr[]} parsed
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Strip WebRTC-based multiaddrs from pairing. Browser WebRTC-direct dials often hit
|
|
15
|
+
* "signal timed out" across NATs; relay + WSS/WS is reliable for link-device.
|
|
16
|
+
* @param {import('@multiformats/multiaddr').Multiaddr[]} parsed
|
|
17
|
+
*/
|
|
18
|
+
export function filterPairingDialMultiaddrs(parsed: import("@multiformats/multiaddr").Multiaddr[]): import("@multiformats/multiaddr").Multiaddr[];
|
|
19
|
+
export function sortPairingMultiaddrs(parsed: any): any[];
|
|
20
|
+
/**
|
|
21
|
+
* Register the link-device handler on Device A (the established device).
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} libp2p - libp2p instance
|
|
24
|
+
* @param {Object} db - The device registry KV database
|
|
25
|
+
* @param {Function} onRequest - async (requestMsg) => 'granted' | 'rejected'
|
|
26
|
+
* @param {Function} [onDeviceLinked] - (deviceEntry) => void
|
|
27
|
+
*/
|
|
28
|
+
export function registerLinkDeviceHandler(libp2p: Object, db: Object, onRequest: Function, onDeviceLinked?: Function): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Unregister the link-device handler from libp2p.
|
|
31
|
+
* @param {Object} libp2p - libp2p instance
|
|
32
|
+
*/
|
|
33
|
+
export function unregisterLinkDeviceHandler(libp2p: Object): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Human-readable device label from navigator (Client Hints OS + legacy platform), UA OS fallback,
|
|
36
|
+
* and browser name/version from {@link navigator.userAgent}.
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
export function detectDeviceLabel(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Device B side: dial Device A and send a pairing request.
|
|
42
|
+
*
|
|
43
|
+
* @param {Object} libp2p - libp2p instance (Device B)
|
|
44
|
+
* @param {string|Object} deviceAPeerId - peerId string or PeerId object of Device A
|
|
45
|
+
* @param {Object} identity - { id, credentialId, publicKey?, deviceLabel? }
|
|
46
|
+
* @param {string[]} [hintMultiaddrs] - Known multiaddrs for Device A (from QR payload)
|
|
47
|
+
* @returns {Promise<{type: 'granted', orbitdbAddress: string}|{type: 'rejected', reason: string}>}
|
|
48
|
+
*/
|
|
49
|
+
export function sendPairingRequest(libp2p: Object, deviceAPeerId: string | Object, identity: Object, hintMultiaddrs?: string[]): Promise<{
|
|
50
|
+
type: "granted";
|
|
51
|
+
orbitdbAddress: string;
|
|
52
|
+
} | {
|
|
53
|
+
type: "rejected";
|
|
54
|
+
reason: string;
|
|
55
|
+
}>;
|
|
56
|
+
export const LINK_DEVICE_PROTOCOL: "/orbitdb/link-device/1.0.0";
|
|
57
|
+
/**
|
|
58
|
+
* Max multiaddrs to advertise and to try per pairing (sorted best-first). Avoids huge paste blobs,
|
|
59
|
+
* redundant dials, and tripping libp2p {@link https://github.com/libp2p/js-libp2p/blob/main/doc/CONFIGURATION.md connectionManager.maxPeerAddrsToDial}.
|
|
60
|
+
*/
|
|
61
|
+
export const PAIRING_HINT_ADDR_CAP: 8;
|