@leofcoin/chain 1.7.112 → 1.7.114
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/chain.js +110 -14
- package/exports/browser/{client-DgmVTCEc-WVRX01s7.js → client-bgSiSUVr-CGsjlhKP.js} +24 -81
- package/exports/browser/{messages-Bx4w-Pqo-DSXPMvjy.js → messages-C3VxYRj3-CAcEAWj1.js} +2 -1
- package/exports/browser/networks-BdMfU1ag.js +25 -0
- package/exports/browser/{node-browser-Dk2CzshW.js → node-browser-B11ddGmL.js} +3 -14
- package/exports/browser/node-browser.js +2 -1
- package/exports/browser/workers/block-worker.js +13 -23
- package/exports/chain.js +110 -14
- package/exports/workers/block-worker.js +13 -23
- package/package.json +3 -3
package/exports/browser/chain.js
CHANGED
|
@@ -5334,9 +5334,10 @@ class ConnectionMonitor {
|
|
|
5334
5334
|
#peerReconnectAttempts = {};
|
|
5335
5335
|
#maxReconnectAttempts = 10;
|
|
5336
5336
|
#reconnectDelay = 5000;
|
|
5337
|
-
#healthCheckInterval =
|
|
5337
|
+
#healthCheckInterval = 15000; // Check every 15 seconds for faster recovery
|
|
5338
5338
|
#version;
|
|
5339
5339
|
#lastHealthCheckAt = 0;
|
|
5340
|
+
#reconnecting = false;
|
|
5340
5341
|
// event handlers to remove later
|
|
5341
5342
|
#onOnline = null;
|
|
5342
5343
|
#onVisibilityChange = null;
|
|
@@ -5442,7 +5443,7 @@ class ConnectionMonitor {
|
|
|
5442
5443
|
console.warn('⚠️ No peer connections detected — attempting reconnection');
|
|
5443
5444
|
await this.#attemptReconnection();
|
|
5444
5445
|
}
|
|
5445
|
-
else if (compatiblePeers.length === 0) {
|
|
5446
|
+
else if (compatiblePeers.length === 0 && connectedPeers.length > 0) {
|
|
5446
5447
|
console.warn('⚠️ No compatible peers found — attempting reconnection');
|
|
5447
5448
|
await this.#attemptReconnection();
|
|
5448
5449
|
}
|
|
@@ -5492,11 +5493,17 @@ class ConnectionMonitor {
|
|
|
5492
5493
|
}
|
|
5493
5494
|
// Called on visibility/online/resume events
|
|
5494
5495
|
async #restoreNetwork() {
|
|
5496
|
+
if (this.#reconnecting) {
|
|
5497
|
+
console.log('🔁 Reconnection already in progress, skipping');
|
|
5498
|
+
return;
|
|
5499
|
+
}
|
|
5500
|
+
this.#reconnecting = true;
|
|
5495
5501
|
console.log('🔁 Restoring network');
|
|
5496
5502
|
try {
|
|
5497
5503
|
const online = await this.#isOnLine(1500);
|
|
5498
5504
|
if (!online) {
|
|
5499
5505
|
console.warn('⚠️ No internet detected, skipping restore');
|
|
5506
|
+
this.#reconnecting = false;
|
|
5500
5507
|
return;
|
|
5501
5508
|
}
|
|
5502
5509
|
}
|
|
@@ -5505,18 +5512,85 @@ class ConnectionMonitor {
|
|
|
5505
5512
|
console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
|
|
5506
5513
|
}
|
|
5507
5514
|
try {
|
|
5508
|
-
//
|
|
5509
|
-
console.log('🔄 Attempting
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5515
|
+
// Try multiple restoration approaches
|
|
5516
|
+
console.log('🔄 Attempting network restoration...');
|
|
5517
|
+
// Approach 1: Try client.reinit if available
|
|
5518
|
+
if (globalThis.peernet?.client?.reinit) {
|
|
5519
|
+
console.log(' → Trying client.reinit()');
|
|
5520
|
+
try {
|
|
5521
|
+
await globalThis.peernet.client.reinit();
|
|
5522
|
+
console.log(' ✅ client.reinit() succeeded');
|
|
5523
|
+
}
|
|
5524
|
+
catch (e) {
|
|
5525
|
+
console.warn(' ⚠️ client.reinit() failed:', e?.message || e);
|
|
5526
|
+
}
|
|
5527
|
+
}
|
|
5528
|
+
// Approach 2: Try peernet.start if available
|
|
5529
|
+
if (globalThis.peernet?.start) {
|
|
5530
|
+
console.log(' → Trying peernet.start()');
|
|
5531
|
+
try {
|
|
5532
|
+
await globalThis.peernet.start();
|
|
5533
|
+
console.log(' ✅ peernet.start() succeeded');
|
|
5534
|
+
}
|
|
5535
|
+
catch (e) {
|
|
5536
|
+
console.warn(' ⚠️ peernet.start() failed:', e?.message || e);
|
|
5537
|
+
}
|
|
5538
|
+
}
|
|
5539
|
+
// Approach 3: Try client.connect if available
|
|
5540
|
+
if (globalThis.peernet?.client &&
|
|
5541
|
+
'connect' in globalThis.peernet.client &&
|
|
5542
|
+
typeof globalThis.peernet.client.connect === 'function') {
|
|
5543
|
+
console.log(' → Trying client.connect()');
|
|
5544
|
+
try {
|
|
5545
|
+
await globalThis.peernet.client.connect();
|
|
5546
|
+
console.log(' ✅ client.connect() succeeded');
|
|
5547
|
+
}
|
|
5548
|
+
catch (e) {
|
|
5549
|
+
console.warn(' ⚠️ client.connect() failed:', e?.message || e);
|
|
5550
|
+
}
|
|
5551
|
+
}
|
|
5552
|
+
// Approach 4: Explicitly dial star servers if available
|
|
5514
5553
|
try {
|
|
5515
|
-
|
|
5554
|
+
const networkName = globalThis.peernet?.network;
|
|
5555
|
+
if (networkName && typeof networkName === 'string') {
|
|
5556
|
+
// Try to import network config
|
|
5557
|
+
const { default: networks } = await import('./networks-BdMfU1ag.js');
|
|
5558
|
+
const [mainKey, subKey] = networkName.split(':');
|
|
5559
|
+
const networkConfig = networks?.[mainKey]?.[subKey];
|
|
5560
|
+
if (networkConfig?.stars && Array.isArray(networkConfig.stars)) {
|
|
5561
|
+
console.log(' → Attempting to dial star servers:', networkConfig.stars.join(', '));
|
|
5562
|
+
for (const star of networkConfig.stars) {
|
|
5563
|
+
try {
|
|
5564
|
+
if (globalThis.peernet?.client && 'dial' in globalThis.peernet.client) {
|
|
5565
|
+
await globalThis.peernet.client.dial(star);
|
|
5566
|
+
console.log(` ✅ Connected to star server: ${star}`);
|
|
5567
|
+
}
|
|
5568
|
+
else if (globalThis.peernet?.client && 'connect' in globalThis.peernet.client) {
|
|
5569
|
+
// Try connect with the star URL
|
|
5570
|
+
await globalThis.peernet.client.connect(star);
|
|
5571
|
+
console.log(` ✅ Connected to star server: ${star}`);
|
|
5572
|
+
}
|
|
5573
|
+
}
|
|
5574
|
+
catch (e) {
|
|
5575
|
+
console.warn(` ⚠️ Failed to dial ${star}:`, e?.message || e);
|
|
5576
|
+
}
|
|
5577
|
+
}
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5516
5580
|
}
|
|
5517
|
-
catch (
|
|
5518
|
-
console.
|
|
5581
|
+
catch (e) {
|
|
5582
|
+
console.warn(' ⚠️ Could not load or dial star servers:', e?.message || e);
|
|
5519
5583
|
}
|
|
5584
|
+
// Give it a moment to establish connections
|
|
5585
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
5586
|
+
const connectedAfter = this.connectedPeers.length;
|
|
5587
|
+
console.log(`🔄 Restoration complete. Connected peers: ${connectedAfter}`);
|
|
5588
|
+
}
|
|
5589
|
+
catch (error) {
|
|
5590
|
+
console.error('❌ Network restoration failed:', error?.message || error);
|
|
5591
|
+
}
|
|
5592
|
+
finally {
|
|
5593
|
+
this.#reconnecting = false;
|
|
5520
5594
|
}
|
|
5521
5595
|
}
|
|
5522
5596
|
async waitForPeers(timeoutMs = 30000) {
|
|
@@ -5537,19 +5611,41 @@ class ConnectionMonitor {
|
|
|
5537
5611
|
});
|
|
5538
5612
|
}
|
|
5539
5613
|
async #attemptReconnection() {
|
|
5614
|
+
if (this.#reconnecting) {
|
|
5615
|
+
console.log('⏭️ Reconnection already in progress');
|
|
5616
|
+
return;
|
|
5617
|
+
}
|
|
5540
5618
|
try {
|
|
5541
5619
|
await this.#restoreNetwork();
|
|
5620
|
+
// Check if reconnection was successful
|
|
5621
|
+
const hasConnections = this.connectedPeers.length > 0;
|
|
5622
|
+
if (hasConnections) {
|
|
5623
|
+
console.log('✅ Reconnection successful, resetting backoff delay');
|
|
5624
|
+
this.#reconnectDelay = 5000;
|
|
5625
|
+
}
|
|
5626
|
+
else {
|
|
5627
|
+
console.warn('⚠️ Reconnection attempt completed but no peers connected');
|
|
5628
|
+
// Schedule retry with backoff
|
|
5629
|
+
if (this.#reconnectDelay >= 30000) {
|
|
5630
|
+
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
5631
|
+
this.#reconnectDelay = 5000;
|
|
5632
|
+
}
|
|
5633
|
+
else {
|
|
5634
|
+
// exponential-ish backoff
|
|
5635
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
5636
|
+
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
5637
|
+
}
|
|
5638
|
+
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
5639
|
+
}
|
|
5542
5640
|
}
|
|
5543
5641
|
catch (error) {
|
|
5544
5642
|
console.error('❌ Reconnection failed:', error?.message || error);
|
|
5643
|
+
// Schedule retry with backoff
|
|
5545
5644
|
if (this.#reconnectDelay >= 30000) {
|
|
5546
|
-
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
5547
5645
|
this.#reconnectDelay = 5000;
|
|
5548
5646
|
}
|
|
5549
5647
|
else {
|
|
5550
|
-
// exponential-ish backoff
|
|
5551
5648
|
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
5552
|
-
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
5553
5649
|
}
|
|
5554
5650
|
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
5555
5651
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { L as LittlePubSub } from './node-browser-
|
|
1
|
+
import { L as LittlePubSub } from './node-browser-B11ddGmL.js';
|
|
2
2
|
import './identity-Cn0iQbY3-CeW0giQS.js';
|
|
3
3
|
import './index-DUfUgiQY.js';
|
|
4
|
+
import './networks-BdMfU1ag.js';
|
|
4
5
|
|
|
5
6
|
class Api {
|
|
6
7
|
_pubsub;
|
|
@@ -428,7 +429,6 @@ class Client {
|
|
|
428
429
|
#connections = {};
|
|
429
430
|
#stars = {};
|
|
430
431
|
#starListeners = {};
|
|
431
|
-
#handlersSetup = false;
|
|
432
432
|
#reinitLock = null;
|
|
433
433
|
#connectEvent = 'peer:connected';
|
|
434
434
|
#retryOptions = { retries: 5, factor: 2, minTimeout: 1000, maxTimeout: 30000 };
|
|
@@ -451,15 +451,6 @@ class Client {
|
|
|
451
451
|
getPeer(peerId) {
|
|
452
452
|
return this.#connections[peerId];
|
|
453
453
|
}
|
|
454
|
-
/**
|
|
455
|
-
*
|
|
456
|
-
* @param options {object}
|
|
457
|
-
* @param options.peerId {string}
|
|
458
|
-
* @param options.networkVersion {string}
|
|
459
|
-
* @param options.version {string}
|
|
460
|
-
* @param options.stars {string[]}
|
|
461
|
-
* @param options.connectEvent {string} defaults to peer:connected, can be renamed to handle different protocols, like peer:discovered (setup peer props before fireing the connect event)
|
|
462
|
-
*/
|
|
463
454
|
constructor(options) {
|
|
464
455
|
const { peerId, networkVersion, version, connectEvent, stars } = {
|
|
465
456
|
...defaultOptions,
|
|
@@ -486,7 +477,6 @@ class Client {
|
|
|
486
477
|
debug('reinit: start');
|
|
487
478
|
try {
|
|
488
479
|
await this.close();
|
|
489
|
-
// clear internal maps so setupStar starts fresh
|
|
490
480
|
this.#stars = {};
|
|
491
481
|
this.#connections = {};
|
|
492
482
|
for (const star of this.starsConfig) {
|
|
@@ -495,8 +485,7 @@ class Client {
|
|
|
495
485
|
}
|
|
496
486
|
catch (e) {
|
|
497
487
|
// If last star fails and none connected, surface error
|
|
498
|
-
if (
|
|
499
|
-
Object.keys(this.#stars).length === 0)
|
|
488
|
+
if (Object.keys(this.#stars).length === 0)
|
|
500
489
|
throw new Error(`No star available to connect`);
|
|
501
490
|
}
|
|
502
491
|
}
|
|
@@ -538,7 +527,6 @@ class Client {
|
|
|
538
527
|
throw lastErr;
|
|
539
528
|
}
|
|
540
529
|
async _init() {
|
|
541
|
-
// reconnectJob()
|
|
542
530
|
if (!globalThis.RTCPeerConnection)
|
|
543
531
|
globalThis.wrtc = (await import('./browser-Cjcx-T47-D0KbGYCz.js').then(function (n) { return n.b; })).default;
|
|
544
532
|
for (const star of this.starsConfig) {
|
|
@@ -561,8 +549,6 @@ class Client {
|
|
|
561
549
|
else {
|
|
562
550
|
globalThis.addEventListener('beforeunload', this.close.bind(this));
|
|
563
551
|
}
|
|
564
|
-
// Setup resume/sleep detection so we can reinit connections after wake
|
|
565
|
-
this._setupResumeHandler();
|
|
566
552
|
}
|
|
567
553
|
setupStarListeners(starConnection, starId) {
|
|
568
554
|
// create stable references to handlers so we can unsubscribe later
|
|
@@ -584,46 +570,6 @@ class Client {
|
|
|
584
570
|
{ topic: 'signal', handler: onSignal }
|
|
585
571
|
];
|
|
586
572
|
}
|
|
587
|
-
_setupResumeHandler() {
|
|
588
|
-
if (this.#handlersSetup)
|
|
589
|
-
return;
|
|
590
|
-
this.#handlersSetup = true;
|
|
591
|
-
const THRESHOLD = 10 * 1000; // 10s gap indicates sleep/wake
|
|
592
|
-
let last = Date.now();
|
|
593
|
-
const check = () => {
|
|
594
|
-
const now = Date.now();
|
|
595
|
-
const delta = now - last;
|
|
596
|
-
last = now;
|
|
597
|
-
if (delta > THRESHOLD) {
|
|
598
|
-
debug(`resume detected (gap ${delta}ms)`);
|
|
599
|
-
this.reinit().catch((e) => debug('reinit error', e));
|
|
600
|
-
}
|
|
601
|
-
};
|
|
602
|
-
// Start interval checker
|
|
603
|
-
const iv = setInterval(check, 2000);
|
|
604
|
-
// Browser specific events
|
|
605
|
-
if (typeof document !== 'undefined' && document.addEventListener) {
|
|
606
|
-
document.addEventListener('visibilitychange', () => {
|
|
607
|
-
if (document.visibilityState === 'visible') {
|
|
608
|
-
// small delay to let timers update
|
|
609
|
-
setTimeout(() => check(), 50);
|
|
610
|
-
}
|
|
611
|
-
});
|
|
612
|
-
window.addEventListener('online', () => setTimeout(() => check(), 50));
|
|
613
|
-
}
|
|
614
|
-
// Node: listen for SIGCONT (process continued) as well
|
|
615
|
-
if (globalThis.process?.on) {
|
|
616
|
-
try {
|
|
617
|
-
process.on('SIGCONT', () => setTimeout(() => check(), 50));
|
|
618
|
-
}
|
|
619
|
-
catch (e) {
|
|
620
|
-
// ignore
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
// keep reference so it can be cleared on close
|
|
624
|
-
// @ts-ignore
|
|
625
|
-
this._resumeInterval = iv;
|
|
626
|
-
}
|
|
627
573
|
#starJoined = (id) => {
|
|
628
574
|
if (this.#stars[id]) {
|
|
629
575
|
this.#stars[id].close(0);
|
|
@@ -719,6 +665,7 @@ class Client {
|
|
|
719
665
|
debug(`peer ${from} already connected`);
|
|
720
666
|
return;
|
|
721
667
|
}
|
|
668
|
+
// peer.channels[channelName]
|
|
722
669
|
if (String(peer.channelName) !== String(channelName)) {
|
|
723
670
|
console.warn(`channelNames don't match: got ${peer.channelName}, expected: ${channelName}.`);
|
|
724
671
|
// Destroy the existing peer connection
|
|
@@ -742,7 +689,8 @@ class Client {
|
|
|
742
689
|
to: peer.peerId,
|
|
743
690
|
channelName: peer.channelName,
|
|
744
691
|
version,
|
|
745
|
-
signal
|
|
692
|
+
signal,
|
|
693
|
+
initiator: peer.initiator
|
|
746
694
|
}
|
|
747
695
|
});
|
|
748
696
|
};
|
|
@@ -799,35 +747,30 @@ class Client {
|
|
|
799
747
|
peer.destroy();
|
|
800
748
|
};
|
|
801
749
|
async close() {
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
this._resumeInterval = null;
|
|
750
|
+
for (const peerId in this.#connections) {
|
|
751
|
+
const peer = this.#connections[peerId];
|
|
752
|
+
if (peer) {
|
|
753
|
+
peer.destroy();
|
|
754
|
+
delete this.#connections[peerId];
|
|
755
|
+
}
|
|
809
756
|
}
|
|
810
757
|
for (const star in this.#stars) {
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
const listeners
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
catch (e) {
|
|
821
|
-
// ignore
|
|
822
|
-
}
|
|
758
|
+
// unsubscribe handlers we registered earlier
|
|
759
|
+
const listeners = this.#starListeners[star];
|
|
760
|
+
if (listeners && listeners.length) {
|
|
761
|
+
for (const { topic, handler } of listeners) {
|
|
762
|
+
try {
|
|
763
|
+
this.#stars[star].pubsub.unsubscribe(topic, handler);
|
|
764
|
+
}
|
|
765
|
+
catch (e) {
|
|
766
|
+
// ignore
|
|
823
767
|
}
|
|
824
768
|
}
|
|
825
769
|
}
|
|
770
|
+
if (this.#stars[star].connectionState() === 'open') {
|
|
771
|
+
await this.#stars[star].send({ url: 'leave', params: this.peerId });
|
|
772
|
+
}
|
|
826
773
|
}
|
|
827
|
-
// Ensure we wait for all peer and star close/destroy operations.
|
|
828
|
-
// Previous code passed an array of arrays to Promise.allSettled which
|
|
829
|
-
// resolves immediately; flatten into a single array of promises (or
|
|
830
|
-
// values) so we actually wait for async close operations.
|
|
831
774
|
const peerClosers = Object.values(this.#connections).map((connection) => {
|
|
832
775
|
try {
|
|
833
776
|
// destroy() may be sync or return a promise
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { F as FormatInterface } from './node-browser-
|
|
1
|
+
import { F as FormatInterface } from './node-browser-B11ddGmL.js';
|
|
2
2
|
import './identity-Cn0iQbY3-CeW0giQS.js';
|
|
3
3
|
import './index-DUfUgiQY.js';
|
|
4
|
+
import './networks-BdMfU1ag.js';
|
|
4
5
|
|
|
5
6
|
var proto$b = {
|
|
6
7
|
data: new Uint8Array(),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// todo only one star needed, no need to have one for each network
|
|
2
|
+
// unless we change anything to the star protocoll
|
|
3
|
+
// version diferences should be handled in the chain
|
|
4
|
+
// maybe a good way to handle could be in p2pt-swarm
|
|
5
|
+
var networks = {
|
|
6
|
+
leofcoin: {
|
|
7
|
+
mainnet: {
|
|
8
|
+
// ports don't really matter since it is favorable to have it begind a ngninx proxy but if we change something to the proto it's easier maybe?
|
|
9
|
+
port: 44444,
|
|
10
|
+
// todo a versionhash would be nice to have as a double check?
|
|
11
|
+
versionHash: '0',
|
|
12
|
+
// a short description identifying the version
|
|
13
|
+
description: 'Main net current version',
|
|
14
|
+
stars: ['wss://star.leofcoin.org'] // todo webrtc and bittorent stars
|
|
15
|
+
},
|
|
16
|
+
peach: {
|
|
17
|
+
port: 44444,
|
|
18
|
+
description: 'Main testnet: latest step before merging into main',
|
|
19
|
+
versionHash: '1',
|
|
20
|
+
stars: ['wss://star.leofcoin.org'] // todo webrtc and bittorent stars
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { networks as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { b as base$1, I as Identity, i as index$4, a as index$5, c as base58$1, d as index$3, e as index$2 } from './identity-Cn0iQbY3-CeW0giQS.js';
|
|
2
2
|
import { F as FormatInterface$2, T as TransactionMessage, C as ContractMessage, B as BlockMessage, a as BWMessage, b as BWRequestMessage, V as ValidatorMessage } from './index-DUfUgiQY.js';
|
|
3
|
+
import networks from './networks-BdMfU1ag.js';
|
|
3
4
|
|
|
4
5
|
var proto = {
|
|
5
6
|
lastblock: Object(),
|
|
@@ -8490,7 +8491,7 @@ class Peernet {
|
|
|
8490
8491
|
this.root = options.root;
|
|
8491
8492
|
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile
|
|
8492
8493
|
// FolderMessageResponse
|
|
8493
|
-
} = await import(/* webpackChunkName: "messages" */ './messages-
|
|
8494
|
+
} = await import(/* webpackChunkName: "messages" */ './messages-C3VxYRj3-CAcEAWj1.js');
|
|
8494
8495
|
/**
|
|
8495
8496
|
* proto Object containing protos
|
|
8496
8497
|
* @type {Object}
|
|
@@ -8584,7 +8585,7 @@ class Peernet {
|
|
|
8584
8585
|
if (this.#starting || this.#started)
|
|
8585
8586
|
return;
|
|
8586
8587
|
this.#starting = true;
|
|
8587
|
-
const importee = await import('./client-
|
|
8588
|
+
const importee = await import('./client-bgSiSUVr-CGsjlhKP.js');
|
|
8588
8589
|
/**
|
|
8589
8590
|
* @access public
|
|
8590
8591
|
* @type {PeernetClient}
|
|
@@ -9104,18 +9105,6 @@ class Peernet {
|
|
|
9104
9105
|
}
|
|
9105
9106
|
globalThis.Peernet = Peernet;
|
|
9106
9107
|
|
|
9107
|
-
// todo only one star needed, no need to have one for each network
|
|
9108
|
-
// unless we change anything to the star protocoll
|
|
9109
|
-
// version diferences should be handled in the chain
|
|
9110
|
-
// maybe a good way to handle could be in p2pt-swarm
|
|
9111
|
-
var networks = {
|
|
9112
|
-
leofcoin: {
|
|
9113
|
-
peach: {
|
|
9114
|
-
stars: ['wss://star.leofcoin.org'] // todo webrtc and bittorent stars
|
|
9115
|
-
}
|
|
9116
|
-
}
|
|
9117
|
-
};
|
|
9118
|
-
|
|
9119
9108
|
const DEFAULT_NODE_OPTIONS = {
|
|
9120
9109
|
network: 'leofcoin:peach',
|
|
9121
9110
|
networkVersion: 'peach',
|
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
import { E as EasyWorker, B as BlockMessage } from './worker-CPvGlmOu-CPvGlmOu.js';
|
|
2
2
|
|
|
3
3
|
const worker = new EasyWorker();
|
|
4
|
-
|
|
5
4
|
globalThis.BigNumber = BigNumber;
|
|
6
5
|
globalThis.contracts = {};
|
|
7
|
-
|
|
8
6
|
const run = async (blocks) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const index = block.decoded.index;
|
|
21
|
-
resolve({ ...block.decoded, hash, blockInfo: { hash, size, index } });
|
|
22
|
-
})
|
|
23
|
-
)
|
|
24
|
-
);
|
|
25
|
-
return blocks
|
|
7
|
+
blocks = await Promise.all(blocks.map((block) => new BlockMessage(block)));
|
|
8
|
+
blocks = blocks.sort((a, b) => a.decoded.timestamp - b.decoded.timestamp);
|
|
9
|
+
blocks = await Promise.all(blocks.map((block) => new Promise(async (resolve, reject) => {
|
|
10
|
+
// todo: tx worker or nah?
|
|
11
|
+
await block.encode();
|
|
12
|
+
const size = block.encoded.length || block.encoded.byteLength;
|
|
13
|
+
const hash = await block.hash();
|
|
14
|
+
const index = block.decoded.index;
|
|
15
|
+
resolve({ ...block.decoded, hash, blockInfo: { hash, size, index } });
|
|
16
|
+
})));
|
|
17
|
+
return blocks;
|
|
26
18
|
};
|
|
27
|
-
|
|
28
19
|
const tasks = async (blocks) => {
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
blocks = await run(blocks);
|
|
21
|
+
worker.postMessage(blocks);
|
|
31
22
|
};
|
|
32
|
-
|
|
33
23
|
worker.onmessage((data) => tasks(data));
|
package/exports/chain.js
CHANGED
|
@@ -1461,9 +1461,10 @@ class ConnectionMonitor {
|
|
|
1461
1461
|
#peerReconnectAttempts = {};
|
|
1462
1462
|
#maxReconnectAttempts = 10;
|
|
1463
1463
|
#reconnectDelay = 5000;
|
|
1464
|
-
#healthCheckInterval =
|
|
1464
|
+
#healthCheckInterval = 15000; // Check every 15 seconds for faster recovery
|
|
1465
1465
|
#version;
|
|
1466
1466
|
#lastHealthCheckAt = 0;
|
|
1467
|
+
#reconnecting = false;
|
|
1467
1468
|
// event handlers to remove later
|
|
1468
1469
|
#onOnline = null;
|
|
1469
1470
|
#onVisibilityChange = null;
|
|
@@ -1569,7 +1570,7 @@ class ConnectionMonitor {
|
|
|
1569
1570
|
console.warn('⚠️ No peer connections detected — attempting reconnection');
|
|
1570
1571
|
await this.#attemptReconnection();
|
|
1571
1572
|
}
|
|
1572
|
-
else if (compatiblePeers.length === 0) {
|
|
1573
|
+
else if (compatiblePeers.length === 0 && connectedPeers.length > 0) {
|
|
1573
1574
|
console.warn('⚠️ No compatible peers found — attempting reconnection');
|
|
1574
1575
|
await this.#attemptReconnection();
|
|
1575
1576
|
}
|
|
@@ -1619,11 +1620,17 @@ class ConnectionMonitor {
|
|
|
1619
1620
|
}
|
|
1620
1621
|
// Called on visibility/online/resume events
|
|
1621
1622
|
async #restoreNetwork() {
|
|
1623
|
+
if (this.#reconnecting) {
|
|
1624
|
+
console.log('🔁 Reconnection already in progress, skipping');
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
this.#reconnecting = true;
|
|
1622
1628
|
console.log('🔁 Restoring network');
|
|
1623
1629
|
try {
|
|
1624
1630
|
const online = await this.#isOnLine(1500);
|
|
1625
1631
|
if (!online) {
|
|
1626
1632
|
console.warn('⚠️ No internet detected, skipping restore');
|
|
1633
|
+
this.#reconnecting = false;
|
|
1627
1634
|
return;
|
|
1628
1635
|
}
|
|
1629
1636
|
}
|
|
@@ -1632,18 +1639,85 @@ class ConnectionMonitor {
|
|
|
1632
1639
|
console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
|
|
1633
1640
|
}
|
|
1634
1641
|
try {
|
|
1635
|
-
//
|
|
1636
|
-
console.log('🔄 Attempting
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1642
|
+
// Try multiple restoration approaches
|
|
1643
|
+
console.log('🔄 Attempting network restoration...');
|
|
1644
|
+
// Approach 1: Try client.reinit if available
|
|
1645
|
+
if (globalThis.peernet?.client?.reinit) {
|
|
1646
|
+
console.log(' → Trying client.reinit()');
|
|
1647
|
+
try {
|
|
1648
|
+
await globalThis.peernet.client.reinit();
|
|
1649
|
+
console.log(' ✅ client.reinit() succeeded');
|
|
1650
|
+
}
|
|
1651
|
+
catch (e) {
|
|
1652
|
+
console.warn(' ⚠️ client.reinit() failed:', e?.message || e);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
// Approach 2: Try peernet.start if available
|
|
1656
|
+
if (globalThis.peernet?.start) {
|
|
1657
|
+
console.log(' → Trying peernet.start()');
|
|
1658
|
+
try {
|
|
1659
|
+
await globalThis.peernet.start();
|
|
1660
|
+
console.log(' ✅ peernet.start() succeeded');
|
|
1661
|
+
}
|
|
1662
|
+
catch (e) {
|
|
1663
|
+
console.warn(' ⚠️ peernet.start() failed:', e?.message || e);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
// Approach 3: Try client.connect if available
|
|
1667
|
+
if (globalThis.peernet?.client &&
|
|
1668
|
+
'connect' in globalThis.peernet.client &&
|
|
1669
|
+
typeof globalThis.peernet.client.connect === 'function') {
|
|
1670
|
+
console.log(' → Trying client.connect()');
|
|
1671
|
+
try {
|
|
1672
|
+
await globalThis.peernet.client.connect();
|
|
1673
|
+
console.log(' ✅ client.connect() succeeded');
|
|
1674
|
+
}
|
|
1675
|
+
catch (e) {
|
|
1676
|
+
console.warn(' ⚠️ client.connect() failed:', e?.message || e);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
// Approach 4: Explicitly dial star servers if available
|
|
1641
1680
|
try {
|
|
1642
|
-
|
|
1681
|
+
const networkName = globalThis.peernet?.network;
|
|
1682
|
+
if (networkName && typeof networkName === 'string') {
|
|
1683
|
+
// Try to import network config
|
|
1684
|
+
const { default: networks } = await import('@leofcoin/networks');
|
|
1685
|
+
const [mainKey, subKey] = networkName.split(':');
|
|
1686
|
+
const networkConfig = networks?.[mainKey]?.[subKey];
|
|
1687
|
+
if (networkConfig?.stars && Array.isArray(networkConfig.stars)) {
|
|
1688
|
+
console.log(' → Attempting to dial star servers:', networkConfig.stars.join(', '));
|
|
1689
|
+
for (const star of networkConfig.stars) {
|
|
1690
|
+
try {
|
|
1691
|
+
if (globalThis.peernet?.client && 'dial' in globalThis.peernet.client) {
|
|
1692
|
+
await globalThis.peernet.client.dial(star);
|
|
1693
|
+
console.log(` ✅ Connected to star server: ${star}`);
|
|
1694
|
+
}
|
|
1695
|
+
else if (globalThis.peernet?.client && 'connect' in globalThis.peernet.client) {
|
|
1696
|
+
// Try connect with the star URL
|
|
1697
|
+
await globalThis.peernet.client.connect(star);
|
|
1698
|
+
console.log(` ✅ Connected to star server: ${star}`);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
catch (e) {
|
|
1702
|
+
console.warn(` ⚠️ Failed to dial ${star}:`, e?.message || e);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1643
1707
|
}
|
|
1644
|
-
catch (
|
|
1645
|
-
console.
|
|
1708
|
+
catch (e) {
|
|
1709
|
+
console.warn(' ⚠️ Could not load or dial star servers:', e?.message || e);
|
|
1646
1710
|
}
|
|
1711
|
+
// Give it a moment to establish connections
|
|
1712
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
1713
|
+
const connectedAfter = this.connectedPeers.length;
|
|
1714
|
+
console.log(`🔄 Restoration complete. Connected peers: ${connectedAfter}`);
|
|
1715
|
+
}
|
|
1716
|
+
catch (error) {
|
|
1717
|
+
console.error('❌ Network restoration failed:', error?.message || error);
|
|
1718
|
+
}
|
|
1719
|
+
finally {
|
|
1720
|
+
this.#reconnecting = false;
|
|
1647
1721
|
}
|
|
1648
1722
|
}
|
|
1649
1723
|
async waitForPeers(timeoutMs = 30000) {
|
|
@@ -1664,19 +1738,41 @@ class ConnectionMonitor {
|
|
|
1664
1738
|
});
|
|
1665
1739
|
}
|
|
1666
1740
|
async #attemptReconnection() {
|
|
1741
|
+
if (this.#reconnecting) {
|
|
1742
|
+
console.log('⏭️ Reconnection already in progress');
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1667
1745
|
try {
|
|
1668
1746
|
await this.#restoreNetwork();
|
|
1747
|
+
// Check if reconnection was successful
|
|
1748
|
+
const hasConnections = this.connectedPeers.length > 0;
|
|
1749
|
+
if (hasConnections) {
|
|
1750
|
+
console.log('✅ Reconnection successful, resetting backoff delay');
|
|
1751
|
+
this.#reconnectDelay = 5000;
|
|
1752
|
+
}
|
|
1753
|
+
else {
|
|
1754
|
+
console.warn('⚠️ Reconnection attempt completed but no peers connected');
|
|
1755
|
+
// Schedule retry with backoff
|
|
1756
|
+
if (this.#reconnectDelay >= 30000) {
|
|
1757
|
+
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
1758
|
+
this.#reconnectDelay = 5000;
|
|
1759
|
+
}
|
|
1760
|
+
else {
|
|
1761
|
+
// exponential-ish backoff
|
|
1762
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
1763
|
+
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
1764
|
+
}
|
|
1765
|
+
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
1766
|
+
}
|
|
1669
1767
|
}
|
|
1670
1768
|
catch (error) {
|
|
1671
1769
|
console.error('❌ Reconnection failed:', error?.message || error);
|
|
1770
|
+
// Schedule retry with backoff
|
|
1672
1771
|
if (this.#reconnectDelay >= 30000) {
|
|
1673
|
-
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
1674
1772
|
this.#reconnectDelay = 5000;
|
|
1675
1773
|
}
|
|
1676
1774
|
else {
|
|
1677
|
-
// exponential-ish backoff
|
|
1678
1775
|
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
1679
|
-
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
1680
1776
|
}
|
|
1681
1777
|
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
1682
1778
|
}
|
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
import { E as EasyWorker, B as BlockMessage } from './worker-CPvGlmOu-CPvGlmOu.js';
|
|
2
2
|
|
|
3
3
|
const worker = new EasyWorker();
|
|
4
|
-
|
|
5
4
|
globalThis.BigNumber = BigNumber;
|
|
6
5
|
globalThis.contracts = {};
|
|
7
|
-
|
|
8
6
|
const run = async (blocks) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const index = block.decoded.index;
|
|
21
|
-
resolve({ ...block.decoded, hash, blockInfo: { hash, size, index } });
|
|
22
|
-
})
|
|
23
|
-
)
|
|
24
|
-
);
|
|
25
|
-
return blocks
|
|
7
|
+
blocks = await Promise.all(blocks.map((block) => new BlockMessage(block)));
|
|
8
|
+
blocks = blocks.sort((a, b) => a.decoded.timestamp - b.decoded.timestamp);
|
|
9
|
+
blocks = await Promise.all(blocks.map((block) => new Promise(async (resolve, reject) => {
|
|
10
|
+
// todo: tx worker or nah?
|
|
11
|
+
await block.encode();
|
|
12
|
+
const size = block.encoded.length || block.encoded.byteLength;
|
|
13
|
+
const hash = await block.hash();
|
|
14
|
+
const index = block.decoded.index;
|
|
15
|
+
resolve({ ...block.decoded, hash, blockInfo: { hash, size, index } });
|
|
16
|
+
})));
|
|
17
|
+
return blocks;
|
|
26
18
|
};
|
|
27
|
-
|
|
28
19
|
const tasks = async (blocks) => {
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
blocks = await run(blocks);
|
|
21
|
+
worker.postMessage(blocks);
|
|
31
22
|
};
|
|
32
|
-
|
|
33
23
|
worker.onmessage((data) => tasks(data));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leofcoin/chain",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.114",
|
|
4
4
|
"description": "Official javascript implementation",
|
|
5
5
|
"private": false,
|
|
6
6
|
"exports": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"author": "",
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@rollup/plugin-commonjs": "^
|
|
52
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
53
53
|
"@rollup/plugin-json": "^6.1.0",
|
|
54
54
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
55
55
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"@leofcoin/messages": "^1.4.40",
|
|
70
70
|
"@leofcoin/multi-wallet": "^3.1.8",
|
|
71
71
|
"@leofcoin/networks": "^1.1.25",
|
|
72
|
-
"@leofcoin/peernet": "^1.1.
|
|
72
|
+
"@leofcoin/peernet": "^1.1.102",
|
|
73
73
|
"@leofcoin/storage": "^3.5.38",
|
|
74
74
|
"@leofcoin/utils": "^1.1.40",
|
|
75
75
|
"@leofcoin/workers": "^1.5.27",
|