@leofcoin/peernet 1.1.104 → 1.2.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/exports/browser/{browser-Qcpp3EKK.js → browser-BHbuEZJu.js} +1 -1
- package/exports/browser/{browser-CfYI-6aD.js → browser-DQlwTLRn.js} +1 -1
- package/exports/browser/{client-Lwke64Zq.js → client-DCeU_UX5.js} +226 -32
- package/exports/browser/{identity-nIyW_Xm8.js → identity-B6BHwSTU.js} +2 -2
- package/exports/browser/identity.js +1 -1
- package/exports/browser/{index-DTbjK0sK.js → index-DYdP5D9L.js} +1 -1
- package/exports/browser/{messages-C22qRxnF.js → messages-CiR1YiV5.js} +2 -2
- package/exports/browser/{peernet-BsnqtUsa.js → peernet-fcX5oKJJ.js} +26 -37
- package/exports/browser/peernet.d.ts +0 -1
- package/exports/browser/peernet.js +2 -2
- package/exports/peernet.js +2 -2
- package/exports/types/peernet.d.ts +0 -1
- package/package.json +8 -21
- package/src/peernet.ts +2 -2
- package/test/peernet.test.js +31 -145
- package/exports/browser/index-ChRjMyiM.js +0 -36
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { L as LittlePubSub } from './peernet-
|
|
2
|
-
import './identity-
|
|
1
|
+
import { L as LittlePubSub, d as deflate_1, c as createDebugger, i as inflate_1 } from './peernet-fcX5oKJJ.js';
|
|
2
|
+
import './identity-B6BHwSTU.js';
|
|
3
3
|
import './value-C3vAp-wb.js';
|
|
4
4
|
|
|
5
5
|
class Api {
|
|
@@ -231,7 +231,7 @@ class SocketRequestClient {
|
|
|
231
231
|
const init = async () => {
|
|
232
232
|
// @ts-ignore
|
|
233
233
|
if (!globalThis.WebSocket && !this.#experimentalWebsocket)
|
|
234
|
-
globalThis.WebSocket = (await import('./browser-
|
|
234
|
+
globalThis.WebSocket = (await import('./browser-DQlwTLRn.js').then(function (n) { return n.b; })).default.w3cwebsocket;
|
|
235
235
|
const client = new WebSocket(this.#url, this.#protocol);
|
|
236
236
|
if (this.#experimentalWebsocket) {
|
|
237
237
|
client.addEventListener('error', this.onerror);
|
|
@@ -317,6 +317,17 @@ const defaultOptions = {
|
|
|
317
317
|
connectEvent: 'peer:connected'
|
|
318
318
|
};
|
|
319
319
|
|
|
320
|
+
// Simple CRC32 implementation
|
|
321
|
+
const crc32$1 = (data) => {
|
|
322
|
+
let crc = 0xffffffff;
|
|
323
|
+
for (let i = 0; i < data.length; i++) {
|
|
324
|
+
crc ^= data[i];
|
|
325
|
+
for (let j = 0; j < 8; j++) {
|
|
326
|
+
crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
330
|
+
};
|
|
320
331
|
const iceServers = [
|
|
321
332
|
{
|
|
322
333
|
urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
|
|
@@ -335,37 +346,81 @@ const iceServers = [
|
|
|
335
346
|
credential: 'openrelayproject'
|
|
336
347
|
}
|
|
337
348
|
];
|
|
338
|
-
const SimplePeer = (await import('./index-
|
|
349
|
+
const SimplePeer = (await import('./index-DYdP5D9L.js').then(function (n) { return n.i; })).default;
|
|
339
350
|
class Peer extends SimplePeer {
|
|
340
351
|
peerId;
|
|
341
352
|
channelName;
|
|
342
353
|
version;
|
|
354
|
+
compressionThreshold = 0.98;
|
|
343
355
|
bw = { up: 0, down: 0 };
|
|
344
356
|
get connected() {
|
|
345
357
|
return super.connected;
|
|
346
358
|
}
|
|
347
359
|
constructor(options) {
|
|
348
|
-
const { from, to, initiator, trickle, config, version } = options;
|
|
360
|
+
const { from, to, initiator, trickle, config, version, wrtc, compressionThreshold } = options;
|
|
349
361
|
const channelName = initiator ? `${from}:${to}` : `${to}:${from}`;
|
|
350
362
|
super({
|
|
351
363
|
channelName,
|
|
352
364
|
initiator,
|
|
353
|
-
trickle: trickle
|
|
365
|
+
trickle: trickle ?? true,
|
|
354
366
|
config: { iceServers, ...config },
|
|
355
|
-
wrtc: globalThis.wrtc
|
|
367
|
+
wrtc: wrtc ?? globalThis.wrtc
|
|
356
368
|
});
|
|
357
369
|
this.version = String(version);
|
|
358
370
|
this.peerId = to;
|
|
359
371
|
this.channelName = channelName;
|
|
372
|
+
if (compressionThreshold !== undefined)
|
|
373
|
+
this.compressionThreshold = compressionThreshold;
|
|
360
374
|
}
|
|
361
375
|
async #chunkit(data, id) {
|
|
362
376
|
this.bw.up = data.length;
|
|
363
|
-
|
|
377
|
+
// attempt compression; use compressed only if beneficial
|
|
378
|
+
let sendData = data;
|
|
379
|
+
try {
|
|
380
|
+
const c = deflate_1(data);
|
|
381
|
+
if (c?.length && c.length < data.length * this.compressionThreshold)
|
|
382
|
+
sendData = c;
|
|
383
|
+
}
|
|
384
|
+
catch (e) {
|
|
385
|
+
// ignore
|
|
386
|
+
}
|
|
387
|
+
const size = sendData.length;
|
|
388
|
+
const encodeFrame = (idStr, totalSize, index, count, payload, flags) => {
|
|
389
|
+
const te = new TextEncoder();
|
|
390
|
+
const idBytes = te.encode(idStr);
|
|
391
|
+
const crc = crc32$1(payload);
|
|
392
|
+
const headerLen = 1 + 1 + 4 + 4 + 4 + 4 + 2 + idBytes.length;
|
|
393
|
+
const buffer = new ArrayBuffer(headerLen + payload.length);
|
|
394
|
+
const view = new DataView(buffer);
|
|
395
|
+
const out = new Uint8Array(buffer);
|
|
396
|
+
let offset = 0;
|
|
397
|
+
view.setUint8(offset, 1); // version
|
|
398
|
+
offset += 1;
|
|
399
|
+
view.setUint8(offset, flags); // flags: bit0 chunked, bit1 compressed
|
|
400
|
+
offset += 1;
|
|
401
|
+
view.setUint32(offset, totalSize, true);
|
|
402
|
+
offset += 4;
|
|
403
|
+
view.setUint32(offset, index, true);
|
|
404
|
+
offset += 4;
|
|
405
|
+
view.setUint32(offset, count, true);
|
|
406
|
+
offset += 4;
|
|
407
|
+
view.setUint32(offset, crc, true); // CRC32
|
|
408
|
+
offset += 4;
|
|
409
|
+
view.setUint16(offset, idBytes.length, true);
|
|
410
|
+
offset += 2;
|
|
411
|
+
out.set(idBytes, offset);
|
|
412
|
+
offset += idBytes.length;
|
|
413
|
+
out.set(payload, offset);
|
|
414
|
+
return out;
|
|
415
|
+
};
|
|
364
416
|
// no needles chunking, keep it simple, if data is smaller then max size just send it
|
|
365
|
-
if (
|
|
366
|
-
|
|
417
|
+
if (size <= MAX_MESSAGE_SIZE) {
|
|
418
|
+
const flags = ((size > MAX_MESSAGE_SIZE ? 1 : 0) << 0) |
|
|
419
|
+
((sendData !== data ? 1 : 0) << 1);
|
|
420
|
+
super.send(encodeFrame(id, size, 0, 1, sendData, flags));
|
|
421
|
+
return;
|
|
367
422
|
}
|
|
368
|
-
|
|
423
|
+
function* chunks(data) {
|
|
369
424
|
while (data.length !== 0) {
|
|
370
425
|
const amountToSlice = data.length >= MAX_MESSAGE_SIZE ? MAX_MESSAGE_SIZE : data.length;
|
|
371
426
|
const subArray = data.subarray(0, amountToSlice);
|
|
@@ -381,8 +436,27 @@ class Peer extends SimplePeer {
|
|
|
381
436
|
// data = data.subarray(amountToSlice, data.length)
|
|
382
437
|
// super.send(JSON.stringify({ chunk: subArray, id, size }))
|
|
383
438
|
// }
|
|
384
|
-
|
|
385
|
-
|
|
439
|
+
// backpressure-aware send loop with indexed chunks
|
|
440
|
+
const count = Math.ceil(size / MAX_MESSAGE_SIZE);
|
|
441
|
+
let index = 0;
|
|
442
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
443
|
+
const threshold = 4 * 1024 * 1024; // 4MB bufferedAmount threshold
|
|
444
|
+
const flags = (1 << 0) | ((sendData !== data ? 1 : 0) << 1);
|
|
445
|
+
for (const chunk of chunks(sendData)) {
|
|
446
|
+
// wait while channel is congested
|
|
447
|
+
// eslint-disable-next-line no-await-in-loop
|
|
448
|
+
while (
|
|
449
|
+
// @ts-ignore underlying channel is not part of public types
|
|
450
|
+
this._channel?.bufferedAmount > threshold) {
|
|
451
|
+
// if connection closed, abort
|
|
452
|
+
// eslint-disable-next-line no-await-in-loop
|
|
453
|
+
if (!this.connected)
|
|
454
|
+
return;
|
|
455
|
+
// eslint-disable-next-line no-await-in-loop
|
|
456
|
+
await sleep(10);
|
|
457
|
+
}
|
|
458
|
+
super.send(encodeFrame(id, size, index, count, chunk, flags));
|
|
459
|
+
index += 1;
|
|
386
460
|
}
|
|
387
461
|
}
|
|
388
462
|
/**
|
|
@@ -402,12 +476,16 @@ class Peer extends SimplePeer {
|
|
|
402
476
|
*/
|
|
403
477
|
request(data, id = crypto.randomUUID()) {
|
|
404
478
|
return new Promise((resolve, reject) => {
|
|
405
|
-
|
|
479
|
+
let timeout;
|
|
406
480
|
const onrequest = ({ data }) => {
|
|
407
481
|
clearTimeout(timeout);
|
|
408
482
|
resolve(data);
|
|
409
483
|
globalThis.pubsub.unsubscribe(id, onrequest);
|
|
410
484
|
};
|
|
485
|
+
timeout = setTimeout(() => {
|
|
486
|
+
globalThis.pubsub.unsubscribe(id, onrequest);
|
|
487
|
+
reject(`request for ${id} timed out`);
|
|
488
|
+
}, 30_000);
|
|
411
489
|
globalThis.pubsub.subscribe(id, onrequest);
|
|
412
490
|
this.send(data, id);
|
|
413
491
|
});
|
|
@@ -422,7 +500,18 @@ class Peer extends SimplePeer {
|
|
|
422
500
|
}
|
|
423
501
|
}
|
|
424
502
|
|
|
425
|
-
|
|
503
|
+
// Simple CRC32 implementation
|
|
504
|
+
const crc32 = (data) => {
|
|
505
|
+
let crc = 0xffffffff;
|
|
506
|
+
for (let i = 0; i < data.length; i++) {
|
|
507
|
+
crc ^= data[i];
|
|
508
|
+
for (let j = 0; j < 8; j++) {
|
|
509
|
+
crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
513
|
+
};
|
|
514
|
+
const debug = createDebugger('@netpeer/swarm/client');
|
|
426
515
|
class Client {
|
|
427
516
|
#peerId;
|
|
428
517
|
#connections = {};
|
|
@@ -527,7 +616,7 @@ class Client {
|
|
|
527
616
|
}
|
|
528
617
|
async _init() {
|
|
529
618
|
if (!globalThis.RTCPeerConnection)
|
|
530
|
-
globalThis.wrtc = (await import('./browser-
|
|
619
|
+
globalThis.wrtc = (await import('./browser-BHbuEZJu.js').then(function (n) { return n.b; })).default;
|
|
531
620
|
for (const star of this.starsConfig) {
|
|
532
621
|
try {
|
|
533
622
|
await this.setupStar(star);
|
|
@@ -705,9 +794,12 @@ class Client {
|
|
|
705
794
|
globalThis.pubsub.publishVerbose(this.#connectEvent, peer.peerId);
|
|
706
795
|
};
|
|
707
796
|
#noticeMessage = (message, id, from, peer) => {
|
|
797
|
+
const dataOut = message instanceof Uint8Array
|
|
798
|
+
? message
|
|
799
|
+
: new Uint8Array(Object.values(message));
|
|
708
800
|
if (globalThis.pubsub.subscribers[id]) {
|
|
709
801
|
globalThis.pubsub.publish(id, {
|
|
710
|
-
data:
|
|
802
|
+
data: dataOut,
|
|
711
803
|
id,
|
|
712
804
|
from,
|
|
713
805
|
peer
|
|
@@ -715,7 +807,7 @@ class Client {
|
|
|
715
807
|
}
|
|
716
808
|
else {
|
|
717
809
|
globalThis.pubsub.publish('peer:data', {
|
|
718
|
-
data:
|
|
810
|
+
data: dataOut,
|
|
719
811
|
id,
|
|
720
812
|
from,
|
|
721
813
|
peer
|
|
@@ -723,22 +815,124 @@ class Client {
|
|
|
723
815
|
}
|
|
724
816
|
};
|
|
725
817
|
#peerData = (peer, data) => {
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
818
|
+
const tryJson = () => {
|
|
819
|
+
const parsed = JSON.parse(new TextDecoder().decode(data));
|
|
820
|
+
const { id, size, chunk, index, count } = parsed;
|
|
821
|
+
chunk ? Object.values(chunk).length : size;
|
|
822
|
+
return {
|
|
823
|
+
id,
|
|
824
|
+
size: Number(size),
|
|
825
|
+
index: Number(index ?? 0),
|
|
826
|
+
count: Number(count ?? 1),
|
|
827
|
+
chunk: new Uint8Array(Object.values(chunk)),
|
|
828
|
+
flags: 0,
|
|
829
|
+
crc: 0
|
|
830
|
+
};
|
|
831
|
+
};
|
|
832
|
+
const decodeBinary = () => {
|
|
833
|
+
let u8;
|
|
834
|
+
if (typeof data === 'string') {
|
|
835
|
+
// should not happen when sending binary, fallback to JSON
|
|
836
|
+
return tryJson();
|
|
837
|
+
}
|
|
838
|
+
else if (data instanceof ArrayBuffer) {
|
|
839
|
+
u8 = new Uint8Array(data);
|
|
840
|
+
}
|
|
841
|
+
else if (ArrayBuffer.isView(data)) {
|
|
842
|
+
const view = data;
|
|
843
|
+
const byteOffset = view.byteOffset || 0;
|
|
844
|
+
const byteLength = view.byteLength || data.length;
|
|
845
|
+
u8 = new Uint8Array(view.buffer, byteOffset, byteLength);
|
|
846
|
+
}
|
|
847
|
+
else if (data?.buffer) {
|
|
848
|
+
u8 = new Uint8Array(data.buffer);
|
|
849
|
+
}
|
|
850
|
+
else {
|
|
851
|
+
// last resort: attempt JSON
|
|
852
|
+
return tryJson();
|
|
853
|
+
}
|
|
854
|
+
const dv = new DataView(u8.buffer, u8.byteOffset, u8.byteLength);
|
|
855
|
+
let offset = 0;
|
|
856
|
+
dv.getUint8(offset);
|
|
857
|
+
offset += 1;
|
|
858
|
+
const flags = dv.getUint8(offset);
|
|
859
|
+
offset += 1;
|
|
860
|
+
const size = dv.getUint32(offset, true);
|
|
861
|
+
offset += 4;
|
|
862
|
+
const index = dv.getUint32(offset, true);
|
|
863
|
+
offset += 4;
|
|
864
|
+
const count = dv.getUint32(offset, true);
|
|
865
|
+
offset += 4;
|
|
866
|
+
const expectedCrc = dv.getUint32(offset, true);
|
|
867
|
+
offset += 4;
|
|
868
|
+
const idLen = dv.getUint16(offset, true);
|
|
869
|
+
offset += 2;
|
|
870
|
+
const idBytes = u8.subarray(offset, offset + idLen);
|
|
871
|
+
offset += idLen;
|
|
872
|
+
const id = new TextDecoder().decode(idBytes);
|
|
873
|
+
const chunk = u8.subarray(offset);
|
|
874
|
+
return { id, size, index, count, chunk, flags, crc: expectedCrc };
|
|
875
|
+
};
|
|
876
|
+
const frame = decodeBinary();
|
|
877
|
+
peer.bw.down += frame.chunk.length;
|
|
878
|
+
// Single frame path: if compressed, inflate before publish
|
|
879
|
+
if (frame.count === 1) {
|
|
880
|
+
let payload = frame.chunk;
|
|
881
|
+
const compressed = Boolean(frame.flags & (1 << 1));
|
|
882
|
+
if (compressed) {
|
|
883
|
+
const actualCrc = crc32(payload);
|
|
884
|
+
if (actualCrc !== frame.crc) {
|
|
885
|
+
console.warn(`CRC mismatch: expected ${frame.crc}, got ${actualCrc}`);
|
|
886
|
+
}
|
|
887
|
+
try {
|
|
888
|
+
payload = inflate_1(payload);
|
|
889
|
+
}
|
|
890
|
+
catch (e) {
|
|
891
|
+
console.warn('inflate failed, passing compressed payload');
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
this.#noticeMessage(payload, frame.id, peer.peerId, peer);
|
|
895
|
+
return;
|
|
730
896
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
this.#messagesToHandle[id] =
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
897
|
+
// Chunked message handling with indexed reassembly
|
|
898
|
+
if (!this.#messagesToHandle[frame.id] ||
|
|
899
|
+
Array.isArray(this.#messagesToHandle[frame.id])) {
|
|
900
|
+
this.#messagesToHandle[frame.id] = {
|
|
901
|
+
chunks: new Array(frame.count),
|
|
902
|
+
receivedBytes: 0,
|
|
903
|
+
expectedSize: Number(frame.size),
|
|
904
|
+
expectedCount: Number(frame.count)
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
const state = this.#messagesToHandle[frame.id];
|
|
908
|
+
// Verify CRC for this chunk
|
|
909
|
+
const actualCrc = crc32(frame.chunk);
|
|
910
|
+
if (actualCrc !== frame.crc) {
|
|
911
|
+
console.warn(`Chunk CRC mismatch for ${frame.id}[${frame.index}]: expected ${frame.crc}, got ${actualCrc}`);
|
|
912
|
+
}
|
|
913
|
+
state.chunks[frame.index] = frame.chunk;
|
|
914
|
+
state.receivedBytes += frame.chunk.length;
|
|
915
|
+
// If all chunks present and total size matches, reassemble
|
|
916
|
+
const allPresent = state.chunks.every((c) => c instanceof Uint8Array);
|
|
917
|
+
if (allPresent && state.receivedBytes === state.expectedSize) {
|
|
918
|
+
const result = new Uint8Array(state.expectedSize);
|
|
919
|
+
let offset2 = 0;
|
|
920
|
+
for (const c of state.chunks) {
|
|
921
|
+
result.set(c, offset2);
|
|
922
|
+
offset2 += c.length;
|
|
923
|
+
}
|
|
924
|
+
let payload = result;
|
|
925
|
+
const compressed = Boolean(frame.flags & (1 << 1));
|
|
926
|
+
if (compressed) {
|
|
927
|
+
try {
|
|
928
|
+
payload = inflate_1(result);
|
|
929
|
+
}
|
|
930
|
+
catch (e) {
|
|
931
|
+
console.warn('inflate failed, passing compressed payload');
|
|
932
|
+
}
|
|
741
933
|
}
|
|
934
|
+
this.#noticeMessage(payload, frame.id, peer.peerId, peer);
|
|
935
|
+
delete this.#messagesToHandle[frame.id];
|
|
742
936
|
}
|
|
743
937
|
};
|
|
744
938
|
#peerError = (peer, error) => {
|
|
@@ -17150,7 +17150,7 @@ class Identity {
|
|
|
17150
17150
|
this.selectedAccount = new TextDecoder().decode(selected);
|
|
17151
17151
|
}
|
|
17152
17152
|
else {
|
|
17153
|
-
const importee = await import(/* webpackChunkName: "generate-account" */ '
|
|
17153
|
+
const importee = await import(/* webpackChunkName: "generate-account" */ '@leofcoin/generate-account');
|
|
17154
17154
|
const { identity, accounts } = await importee.default(password, this.network);
|
|
17155
17155
|
await globalThis.accountStore.put('public', JSON.stringify({ walletId: identity.walletId }));
|
|
17156
17156
|
await globalThis.walletStore.put('version', String(1));
|
|
@@ -17196,4 +17196,4 @@ class Identity {
|
|
|
17196
17196
|
}
|
|
17197
17197
|
}
|
|
17198
17198
|
|
|
17199
|
-
export { Identity as I,
|
|
17199
|
+
export { Identity as I, base58$1 as a, base$1 as b, index$3 as c, index$2 as d, index$4 as e, commonjsGlobal as f, getDefaultExportFromCjs as g, requireInherits_browser as h, index$5 as i, require$$3 as r };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { I as default } from './identity-
|
|
1
|
+
export { I as default } from './identity-B6BHwSTU.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { f as commonjsGlobal, r as require$$3, h as requireInherits_browser, g as getDefaultExportFromCjs } from './identity-B6BHwSTU.js';
|
|
2
2
|
import require$$0 from 'events';
|
|
3
3
|
|
|
4
4
|
var browser$2 = {exports: {}};
|
|
@@ -1,42 +1,31 @@
|
|
|
1
|
-
import { b as base, a as base58$1, i as index$2, c as index$3, d as index$4, e as index$5, I as Identity } from './identity-
|
|
1
|
+
import { b as base, a as base58$1, i as index$2, c as index$3, d as index$4, e as index$5, I as Identity } from './identity-B6BHwSTU.js';
|
|
2
2
|
import { K as KeyPath, a as KeyValue } from './value-C3vAp-wb.js';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (DEBUG) {
|
|
9
|
-
globalThis.DEBUG = DEBUG.startsWith("[")
|
|
10
|
-
? JSON.parse(DEBUG).split(",")
|
|
11
|
-
: [DEBUG];
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
4
|
+
const getTargets = () => Array.from([]);
|
|
5
|
+
const isEnabled = (target) => {
|
|
6
|
+
return false;
|
|
7
|
+
};
|
|
15
8
|
|
|
16
9
|
const getLogger = (trace) => (trace ? console.trace : console.log);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
const createDebugger = (target) => {
|
|
11
|
+
// Cache the enabled check on first call
|
|
12
|
+
let enabled = null;
|
|
13
|
+
let lastTargets = undefined;
|
|
14
|
+
return (text, trace) => {
|
|
15
|
+
const targets = getTargets();
|
|
16
|
+
if (lastTargets !== targets) {
|
|
17
|
+
enabled = targets ? isEnabled() : false;
|
|
18
|
+
lastTargets = targets;
|
|
19
|
+
}
|
|
20
|
+
if (!enabled)
|
|
21
|
+
return;
|
|
22
|
+
if (text)
|
|
23
|
+
getLogger(trace)('\x1b[34m\x1b[1m%s', `${target}: ${text}`, '\x1b[0m');
|
|
24
|
+
else
|
|
25
|
+
getLogger(trace)('\x1b[34m\x1b[1m%s', `${target}`, '\x1b[0m');
|
|
26
|
+
};
|
|
30
27
|
};
|
|
31
28
|
|
|
32
|
-
const createDebugger = (target) => (text) => debug$1(target, text);
|
|
33
|
-
|
|
34
|
-
if (!globalThis.debug) {
|
|
35
|
-
globalThis.debug = debug$1;
|
|
36
|
-
// todo: deprecate
|
|
37
|
-
globalThis.createDebugger = createDebugger;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
29
|
class LittlePubSub {
|
|
41
30
|
subscribers = {};
|
|
42
31
|
verbose;
|
|
@@ -8222,7 +8211,7 @@ globalThis.LeofcoinStorage = LeofcoinStorage$1;
|
|
|
8222
8211
|
globalThis.leofcoin = globalThis.leofcoin || {};
|
|
8223
8212
|
globalThis.pubsub = globalThis.pubsub || new LittlePubSub();
|
|
8224
8213
|
globalThis.globalSub = globalThis.globalSub || new LittlePubSub();
|
|
8225
|
-
const debug =
|
|
8214
|
+
const debug = createDebugger('peernet');
|
|
8226
8215
|
/**
|
|
8227
8216
|
* @access public
|
|
8228
8217
|
* @example
|
|
@@ -8366,7 +8355,7 @@ class Peernet {
|
|
|
8366
8355
|
this.root = options.root;
|
|
8367
8356
|
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile
|
|
8368
8357
|
// FolderMessageResponse
|
|
8369
|
-
} = await import(/* webpackChunkName: "messages" */ './messages-
|
|
8358
|
+
} = await import(/* webpackChunkName: "messages" */ './messages-CiR1YiV5.js');
|
|
8370
8359
|
/**
|
|
8371
8360
|
* proto Object containing protos
|
|
8372
8361
|
* @type {Object}
|
|
@@ -8460,7 +8449,7 @@ class Peernet {
|
|
|
8460
8449
|
if (this.#starting || this.#started)
|
|
8461
8450
|
return;
|
|
8462
8451
|
this.#starting = true;
|
|
8463
|
-
const importee = await import('./client-
|
|
8452
|
+
const importee = await import('./client-DCeU_UX5.js');
|
|
8464
8453
|
/**
|
|
8465
8454
|
* @access public
|
|
8466
8455
|
* @type {PeernetClient}
|
|
@@ -8980,4 +8969,4 @@ class Peernet {
|
|
|
8980
8969
|
}
|
|
8981
8970
|
globalThis.Peernet = Peernet;
|
|
8982
8971
|
|
|
8983
|
-
export { FormatInterface as F, LittlePubSub as L, Peernet as P };
|
|
8972
|
+
export { FormatInterface as F, LittlePubSub as L, Peernet as P, createDebugger as c, deflate_1 as d, inflate_1 as i };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { P as default } from './peernet-
|
|
2
|
-
import './identity-
|
|
1
|
+
export { P as default } from './peernet-fcX5oKJJ.js';
|
|
2
|
+
import './identity-B6BHwSTU.js';
|
|
3
3
|
import './value-C3vAp-wb.js';
|
package/exports/peernet.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import '@vandeurenglenn/debug';
|
|
1
|
+
import { createDebugger } from '@vandeurenglenn/debug';
|
|
2
2
|
import PubSub from '@vandeurenglenn/little-pubsub';
|
|
3
3
|
import { Codec } from '@leofcoin/codec-format-interface';
|
|
4
4
|
import { Storage } from '@leofcoin/storage';
|
|
@@ -303,7 +303,7 @@ globalThis.LeofcoinStorage = Storage;
|
|
|
303
303
|
globalThis.leofcoin = globalThis.leofcoin || {};
|
|
304
304
|
globalThis.pubsub = globalThis.pubsub || new PubSub();
|
|
305
305
|
globalThis.globalSub = globalThis.globalSub || new PubSub();
|
|
306
|
-
const debug =
|
|
306
|
+
const debug = createDebugger('peernet');
|
|
307
307
|
/**
|
|
308
308
|
* @access public
|
|
309
309
|
* @example
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leofcoin/peernet",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "./exports/browser/peernet.js",
|
|
6
6
|
"exports": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "rollup -c",
|
|
25
25
|
"watch": "rollup -c -w",
|
|
26
|
-
"test": "
|
|
26
|
+
"test": "node --test test/peernet.test.js",
|
|
27
27
|
"server": "discovery-swarm-webrtc --port=4000",
|
|
28
28
|
"demo": "jsproject --serve ./ --port 6868"
|
|
29
29
|
},
|
|
@@ -33,38 +33,25 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@leofcoin/codec-format-interface": "^1.7.14",
|
|
35
35
|
"@leofcoin/codecs": "^1.0.7",
|
|
36
|
-
"@leofcoin/generate-account": "^2.0.3",
|
|
37
36
|
"@leofcoin/identity-utils": "^1.0.2",
|
|
38
37
|
"@leofcoin/multi-wallet": "^3.1.8",
|
|
39
38
|
"@leofcoin/storage": "^3.5.38",
|
|
40
|
-
"@netpeer/swarm": "^0.
|
|
41
|
-
"@vandeurenglenn/base32": "^1.2.4",
|
|
39
|
+
"@netpeer/swarm": "^0.9.0",
|
|
42
40
|
"@vandeurenglenn/base58": "^1.1.9",
|
|
43
|
-
"@vandeurenglenn/debug": "^1.
|
|
44
|
-
"@vandeurenglenn/is-hex": "^1.1.1",
|
|
41
|
+
"@vandeurenglenn/debug": "^1.4.0",
|
|
45
42
|
"@vandeurenglenn/little-pubsub": "^1.5.1",
|
|
46
|
-
"inquirer": "^13.0
|
|
47
|
-
"multi-signature": "^1.3.1",
|
|
43
|
+
"inquirer": "^13.1.0",
|
|
48
44
|
"qr-scanner": "^1.4.2",
|
|
49
|
-
"qrcode": "^1.5.4"
|
|
50
|
-
"socket-request-client": "^2.1.2",
|
|
51
|
-
"socket-request-server": "^1.7.2"
|
|
45
|
+
"qrcode": "^1.5.4"
|
|
52
46
|
},
|
|
53
47
|
"devDependencies": {
|
|
54
|
-
"@jest/globals": "^30.2.0",
|
|
55
48
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
56
49
|
"@rollup/plugin-json": "^6.1.0",
|
|
57
50
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
58
51
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
59
52
|
"@rollup/plugin-wasm": "^6.2.2",
|
|
60
|
-
"@types/
|
|
61
|
-
"@types/node": "^24.10.1",
|
|
53
|
+
"@types/node": "^25.0.3",
|
|
62
54
|
"@types/qrcode": "^1.5.6",
|
|
63
|
-
"
|
|
64
|
-
"@types/varint": "^6.0.3",
|
|
65
|
-
"chai": "^6.2.1",
|
|
66
|
-
"cross-env": "^10.1.0",
|
|
67
|
-
"rollup": "^4.53.3",
|
|
68
|
-
"sinon": "^21.0.0"
|
|
55
|
+
"rollup": "^4.54.0"
|
|
69
56
|
}
|
|
70
57
|
}
|
package/src/peernet.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import '@vandeurenglenn/debug'
|
|
1
|
+
import { createDebugger } from '@vandeurenglenn/debug'
|
|
2
2
|
import PubSub from '@vandeurenglenn/little-pubsub'
|
|
3
3
|
import PeerDiscovery from './discovery/peer-discovery.js'
|
|
4
4
|
import DHT, { DHTProvider, DHTProviderDistanceResult, getAddress } from './dht/dht.js'
|
|
@@ -30,7 +30,7 @@ declare global {
|
|
|
30
30
|
var chainStore: LeofcoinStorageClass
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const debug =
|
|
33
|
+
const debug = createDebugger('peernet')
|
|
34
34
|
/**
|
|
35
35
|
* @access public
|
|
36
36
|
* @example
|
package/test/peernet.test.js
CHANGED
|
@@ -1,159 +1,45 @@
|
|
|
1
|
+
import test from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
|
|
1
4
|
import Peernet from '../exports/peernet.js'
|
|
2
5
|
import Identity from '../exports/identity.js'
|
|
3
|
-
import { expect } from 'chai'
|
|
4
|
-
import sinon from 'sinon'
|
|
5
|
-
import networks from '@leofcoin/networks'
|
|
6
|
-
|
|
7
|
-
const network = networks.leofcoin.peach
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
let password
|
|
11
|
-
options = {
|
|
7
|
+
const options = {
|
|
12
8
|
network: 'leofcoin:peach',
|
|
13
|
-
stars:
|
|
9
|
+
stars: [],
|
|
14
10
|
root: '.testnet',
|
|
15
11
|
version: '1.0.0',
|
|
16
|
-
storePrefix: 'test'
|
|
12
|
+
storePrefix: 'test',
|
|
13
|
+
autoStart: false
|
|
17
14
|
}
|
|
18
|
-
password = 'password'
|
|
19
|
-
const peernet = await new Peernet(options, password)
|
|
20
|
-
|
|
21
|
-
describe('Peernet', async () => {
|
|
22
|
-
// beforeEach(async () => {
|
|
23
|
-
// })
|
|
24
|
-
|
|
25
|
-
it('should initialize with the correct network', () => {
|
|
26
|
-
expect(peernet.network).to.equal('leofcoin:peach')
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('should initialize with the correct version', () => {
|
|
30
|
-
expect(peernet.version).to.equal('1.0.0')
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should initialize with the correct store prefix', () => {
|
|
34
|
-
expect(peernet.storePrefix).to.equal('test')
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('should have an identity instance', () => {
|
|
38
|
-
expect(peernet.identity).to.be.instanceOf(Identity)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('should have a DHT instance', () => {
|
|
42
|
-
expect(peernet.dht).to.not.be.undefined
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('should start the client', async () => {
|
|
46
|
-
const startSpy = sinon.spy(peernet, 'start')
|
|
47
|
-
await peernet.start()
|
|
48
|
-
expect(startSpy.calledOnce).to.be.true
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should add a proto', () => {
|
|
52
|
-
const protoName = 'test-proto'
|
|
53
|
-
const proto = {}
|
|
54
|
-
peernet.addProto(protoName, proto)
|
|
55
|
-
expect(globalThis.peernet.protos[protoName]).to.equal(proto)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('should add a codec', () => {
|
|
59
|
-
const codec = { name: 'test-codec' }
|
|
60
|
-
const addCodecSpy = sinon.spy(peernet, 'addCodec')
|
|
61
|
-
peernet.addCodec(codec)
|
|
62
|
-
expect(addCodecSpy.calledOnceWith(codec)).to.be.true
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('should select an account', async () => {
|
|
66
|
-
const account = 'test-account'
|
|
67
|
-
const selectAccountSpy = sinon.spy(peernet.identity, 'selectAccount')
|
|
68
|
-
await peernet.selectAccount(account)
|
|
69
|
-
expect(selectAccountSpy.calledOnceWith(account)).to.be.true
|
|
70
|
-
})
|
|
71
15
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const prepareMessageSpy = sinon.spy(peernet._messageHandler, 'prepareMessage')
|
|
75
|
-
peernet.prepareMessage(data)
|
|
76
|
-
expect(prepareMessageSpy.calledOnceWith(data)).to.be.true
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('should get peers', () => {
|
|
80
|
-
const peers = peernet.peers
|
|
81
|
-
expect(peers).to.be.an('array')
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('should get connections', () => {
|
|
85
|
-
const connections = peernet.connections
|
|
86
|
-
expect(connections).to.be.an('object')
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('should get a connection by id', () => {
|
|
90
|
-
const id = 'test-id'
|
|
91
|
-
const connection = peernet.getConnection(id)
|
|
92
|
-
expect(connection).to.be.undefined // Assuming no connections are established in the test
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
// it('should handle DHT', async () => {
|
|
96
|
-
// const peer = {}
|
|
97
|
-
// const id = 'test-id'
|
|
98
|
-
// const proto = { decoded: { hash: 'test-hash', store: 'test-store' } }
|
|
99
|
-
// const handleDHTSpy = sinon.spy(peernet, 'handleDHT')
|
|
100
|
-
// await peernet.handleDHT(peer, id, proto)
|
|
101
|
-
// expect(handleDHTSpy.calledOnceWith(peer, id, proto)).to.be.true
|
|
102
|
-
// })
|
|
103
|
-
|
|
104
|
-
it('should handle data', async () => {
|
|
105
|
-
const peer = {}
|
|
106
|
-
const id = 'test-id'
|
|
107
|
-
const proto = { decoded: { hash: 'test-hash', store: 'test-store' } }
|
|
108
|
-
const handleDataSpy = sinon.spy(peernet, 'handleData')
|
|
109
|
-
await peernet.handleData(peer, id, proto)
|
|
110
|
-
expect(handleDataSpy.calledOnceWith(peer, id, proto)).to.be.true
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
it('should handle request', async () => {
|
|
114
|
-
const peer = {}
|
|
115
|
-
const id = 'test-id'
|
|
116
|
-
const proto = { decoded: { request: 'test-request' } }
|
|
117
|
-
const handleRequestSpy = sinon.spy(peernet, 'handleRequest')
|
|
118
|
-
await peernet.handleRequest(peer, id, proto)
|
|
119
|
-
expect(handleRequestSpy.calledOnceWith(peer, id, proto)).to.be.true
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('should walk the network', async () => {
|
|
123
|
-
const hash = 'test-hash'
|
|
124
|
-
const walkSpy = sinon.spy(peernet, 'walk')
|
|
125
|
-
await peernet.walk(hash)
|
|
126
|
-
expect(walkSpy.calledOnceWith(hash)).to.be.true
|
|
127
|
-
})
|
|
16
|
+
const password = 'password'
|
|
17
|
+
const peernet = await new Peernet(options, password)
|
|
128
18
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
19
|
+
test('initializes with provided options', () => {
|
|
20
|
+
assert.equal(peernet.network, options.network)
|
|
21
|
+
assert.equal(peernet.version, options.version)
|
|
22
|
+
assert.equal(peernet.storePrefix, options.storePrefix)
|
|
23
|
+
})
|
|
134
24
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// await peernet.requestData(hash, 'data')
|
|
139
|
-
// expect(requestDataSpy.calledOnceWith(hash, 'data')).to.be.true
|
|
140
|
-
// })
|
|
25
|
+
test('exposes identity instance', () => {
|
|
26
|
+
assert.ok(peernet.identity instanceof Identity)
|
|
27
|
+
})
|
|
141
28
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const publishSpy = sinon.spy(peernet, 'publish')
|
|
146
|
-
await peernet.publish(topic, data)
|
|
147
|
-
expect(publishSpy.calledOnceWith(topic, data)).to.be.true
|
|
148
|
-
})
|
|
29
|
+
test('has a DHT instance', () => {
|
|
30
|
+
assert.ok(peernet.dht)
|
|
31
|
+
})
|
|
149
32
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
expect(subscribeSpy.calledOnceWith(topic, callback)).to.be.true
|
|
33
|
+
test('returns peers and connections safely', () => {
|
|
34
|
+
assert.deepEqual(peernet.peers, [])
|
|
35
|
+
assert.deepEqual(peernet.connections, {})
|
|
36
|
+
assert.equal(peernet.getConnection('missing'), undefined)
|
|
37
|
+
})
|
|
156
38
|
|
|
157
|
-
|
|
158
|
-
|
|
39
|
+
test('provides callable helpers', () => {
|
|
40
|
+
assert.equal(typeof peernet.addProto, 'function')
|
|
41
|
+
assert.equal(typeof peernet.addCodec, 'function')
|
|
42
|
+
assert.equal(typeof peernet.prepareMessage, 'function')
|
|
43
|
+
assert.equal(typeof peernet.publish, 'function')
|
|
44
|
+
assert.equal(typeof peernet.subscribe, 'function')
|
|
159
45
|
})
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { M as MultiWallet, f as encrypt, a as base58$1 } from './identity-nIyW_Xm8.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @params {String} network
|
|
5
|
-
* @return {object} { identity, accounts, config }
|
|
6
|
-
*/
|
|
7
|
-
var index = async (password, network) => {
|
|
8
|
-
if (!password)
|
|
9
|
-
throw new Error('wallets need to be password protected.');
|
|
10
|
-
let wallet = new MultiWallet(network);
|
|
11
|
-
/**
|
|
12
|
-
* @type {string}
|
|
13
|
-
*/
|
|
14
|
-
let mnemonic = await wallet.generate(password);
|
|
15
|
-
wallet = new MultiWallet(network);
|
|
16
|
-
await wallet.recover(mnemonic, password, network);
|
|
17
|
-
mnemonic = new Uint8Array(await encrypt(password, mnemonic));
|
|
18
|
-
const multiWIF = new Uint8Array(await encrypt(password, await wallet.multiWIF));
|
|
19
|
-
/**
|
|
20
|
-
* @type {object}
|
|
21
|
-
*/
|
|
22
|
-
const external = await wallet.account(1).external(1);
|
|
23
|
-
const externalAddress = await external.address;
|
|
24
|
-
const internal = await wallet.account(1).internal(1);
|
|
25
|
-
const internalAddress = await internal.address;
|
|
26
|
-
return {
|
|
27
|
-
identity: {
|
|
28
|
-
mnemonic: base58$1.encode(mnemonic),
|
|
29
|
-
multiWIF: base58$1.encode(multiWIF),
|
|
30
|
-
walletId: await external.id
|
|
31
|
-
},
|
|
32
|
-
accounts: [['main account', externalAddress, internalAddress]]
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export { index as default };
|