@leofcoin/chain 1.7.103 → 1.7.105

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.
@@ -5347,13 +5347,13 @@ class ConnectionMonitor {
5347
5347
  void this.#restoreNetwork();
5348
5348
  };
5349
5349
  window.addEventListener('online', this.#onOnline);
5350
- this.#onVisibilityChange = () => {
5351
- if (document.visibilityState === 'visible') {
5352
- console.log('💡 Visibility regained — attempting restore');
5353
- void this.#restoreNetwork();
5354
- }
5355
- };
5356
- document.addEventListener('visibilitychange', this.#onVisibilityChange);
5350
+ // this.#onVisibilityChange = () => {
5351
+ // if (document.visibilityState === 'visible') {
5352
+ // console.log('💡 Visibility regained — attempting restore')
5353
+ // void this.#restoreNetwork()
5354
+ // }
5355
+ // }
5356
+ // document.addEventListener('visibilitychange', this.#onVisibilityChange)
5357
5357
  }
5358
5358
  if (typeof process !== 'undefined' && typeof process.on === 'function') {
5359
5359
  this.#onSigcont = () => {
@@ -5412,20 +5412,6 @@ class ConnectionMonitor {
5412
5412
  else if (compatiblePeers.length === 0) {
5413
5413
  console.warn('⚠️ No compatible peers found');
5414
5414
  await this.#attemptReconnection();
5415
- // Could attempt to find compatible peers or trigger version negotiation
5416
- }
5417
- // Log disconnected peers
5418
- const disconnectedPeers = this.disconnectedPeers;
5419
- if (disconnectedPeers.length > 0) {
5420
- console.warn(`⚠️ Disconnected peers: ${disconnectedPeers.map((peer) => peer.peerId).join(', ')}`);
5421
- // Attempt to reconnect each disconnected peer sequentially to avoid racing signaling/state
5422
- for (const peer of disconnectedPeers) {
5423
- // small spacing between attempts to reduce signaling races
5424
- // eslint-disable-next-line no-await-in-loop
5425
- await new Promise((r) => setTimeout(r, 150));
5426
- // eslint-disable-next-line no-await-in-loop
5427
- await this.#attemptPeerReconnection(peer);
5428
- }
5429
5415
  }
5430
5416
  // Publish connection status
5431
5417
  globalThis.pubsub?.publish('connection-status', {
@@ -5434,170 +5420,73 @@ class ConnectionMonitor {
5434
5420
  healthy: compatiblePeers.length > 0
5435
5421
  });
5436
5422
  }
5437
- async #attemptPeerReconnection(peer) {
5438
- if (!peer)
5439
- return;
5440
- const peerId = peer.peerId || peer.id;
5441
- if (!peerId)
5442
- return;
5443
- if (!this.#peerReconnectAttempts[peerId]) {
5444
- this.#peerReconnectAttempts[peerId] = 0;
5445
- }
5446
- if (this.#peerReconnectAttempts[peerId] >= this.#maxReconnectAttempts) {
5447
- console.error('❌ Max reconnection attempts reached for', peerId);
5448
- this.#peerReconnectAttempts[peerId] = 0;
5449
- return;
5450
- }
5451
- this.#peerReconnectAttempts[peerId]++;
5452
- console.log(`🔄 Attempting reconnection ${this.#peerReconnectAttempts[peerId]}/${this.#maxReconnectAttempts} for ${peerId}`);
5453
- try {
5454
- const peernet = globalThis.peernet;
5455
- if (!peernet) {
5456
- console.warn('⚠️ globalThis.peernet not available');
5457
- return;
5423
+ // lightweight TCP probe to detect internet connectivity in Node.js
5424
+ async #isOnLine(timeout = 1500) {
5425
+ // If not running in Node, fallback to navigator.onLine if available, otherwise assume online
5426
+ if (typeof process === 'undefined') {
5427
+ if (navigator?.onLine !== undefined) {
5428
+ return navigator.onLine;
5458
5429
  }
5459
- // Try targeted reconnect if available
5460
- if (peernet.client?.reconnect) {
5461
- try {
5462
- await peernet.client.reconnect(peerId, peernet.stars?.[0]);
5463
- return;
5464
- }
5465
- catch (err) {
5466
- const msg = String(err?.message || err);
5467
- console.warn('⚠️ Targeted reconnect failed:', msg);
5468
- // handle signaling/state mismatches by cleaning up only that peer and retrying targeted reconnect
5469
- if (msg.includes('Called in wrong state') ||
5470
- msg.includes('setRemoteDescription') ||
5471
- msg.includes('channelNames') ||
5472
- msg.includes("channelNames don't match")) {
5473
- console.warn('⚠️ Detected signaling/channel mismatch — cleaning up peer state and retrying targeted reconnect');
5474
- try {
5475
- await this.#cleanupPeerState(peerId, peernet);
5476
- // small backoff before retry
5477
- await new Promise((r) => setTimeout(r, 150));
5478
- await peernet.client.reconnect(peerId, peernet.stars?.[0]);
5479
- return;
5480
- }
5481
- catch (retryErr) {
5482
- console.warn('⚠️ Retry targeted reconnect failed:', String(retryErr?.message || retryErr));
5483
- // fall through to non-targeted fallback below
5484
- }
5430
+ return true;
5431
+ }
5432
+ return new Promise(async (resolve) => {
5433
+ try {
5434
+ // lazy require so bundlers / browser builds don't break
5435
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
5436
+ const net = await import('net');
5437
+ const socket = new net.Socket();
5438
+ let finished = false;
5439
+ const finish = (val) => {
5440
+ if (finished)
5441
+ return;
5442
+ finished = true;
5443
+ try {
5444
+ socket.destroy();
5485
5445
  }
5486
- throw err;
5487
- }
5488
- }
5489
- // If no targeted reconnect, try start/restore
5490
- if (peernet.start) {
5491
- await peernet.start();
5446
+ catch (e) {
5447
+ // ignore
5448
+ }
5449
+ resolve(val);
5450
+ };
5451
+ socket.setTimeout(timeout);
5452
+ socket.once('connect', () => finish(true));
5453
+ socket.once('error', () => finish(false));
5454
+ socket.once('timeout', () => finish(false));
5455
+ // connect to Cloudflare DNS (1.1.1.1) on TCP/53 — fast and reliable
5456
+ socket.connect(53, '1.1.1.1');
5492
5457
  }
5493
- }
5494
- catch (error) {
5495
- console.error('❌ Reconnection failed:', error?.message || error);
5496
- // As fallback, try full restart only if even the cleanup+retry failed
5497
- if (globalThis.peernet) {
5498
- await this.#performFullRestart(globalThis.peernet);
5458
+ catch (e) {
5459
+ resolve(false);
5499
5460
  }
5500
- }
5461
+ });
5501
5462
  }
5502
- // helper: try to close/destroy a single peer connection and remove it from peernet's map
5503
- async #cleanupPeerState(peerId, peernet) {
5463
+ // Called on visibility/online/resume events
5464
+ async #restoreNetwork() {
5465
+ console.log('🔁 Restoring network');
5504
5466
  try {
5505
- const conns = peernet.connections || {};
5506
- const conn = conns[peerId] || conns[Object.keys(conns).find((k) => k.includes(peerId) || peerId.includes(k))];
5507
- if (!conn)
5467
+ const online = await this.#isOnLine(1500);
5468
+ if (!online) {
5469
+ console.warn('⚠️ No internet detected, skipping restore');
5508
5470
  return;
5509
- // close underlying RTCPeerConnection if exposed
5510
- try {
5511
- if (conn.pc && typeof conn.pc.close === 'function') {
5512
- conn.pc.close();
5513
- }
5514
- }
5515
- catch (e) {
5516
- // ignore
5517
5471
  }
5518
- // call any destroy/cleanup API on the connection object
5519
- try {
5520
- if (typeof conn.destroy === 'function') {
5521
- conn.destroy();
5522
- }
5523
- else if (typeof conn.close === 'function') {
5524
- conn.close();
5525
- }
5526
- }
5527
- catch (e) {
5528
- // ignore
5529
- }
5530
- // remove reference so reconnect path will create a fresh one
5531
- try {
5532
- delete peernet.connections[peerId];
5533
- }
5534
- catch (e) {
5535
- // ignore
5536
- }
5537
- // small pause to let underlying sockets/RTCs settle
5538
- await new Promise((r) => setTimeout(r, 100));
5539
5472
  }
5540
5473
  catch (e) {
5541
- // ignore cleanup errors
5474
+ // If the probe failed for any reason, continue with restore attempt
5475
+ console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
5542
5476
  }
5543
- }
5544
- // New helper: close stale RTCPeerConnections if present and then restart peernet
5545
- async #performFullRestart(peernet) {
5546
5477
  try {
5547
- // Close underlying peer RTCPeerConnections if the library exposes them
5478
+ // prefer safe client reinit if available
5479
+ console.log('🔄 Attempting to reinitialize peernet client');
5480
+ await globalThis.peernet.client.reinit();
5481
+ }
5482
+ catch (e) {
5483
+ console.warn('⚠️ peernet.client.reinit failed, falling back to peernet.start if available', e?.message || e);
5548
5484
  try {
5549
- const conns = peernet.connections || {};
5550
- for (const id of Object.keys(conns)) {
5551
- const p = conns[id];
5552
- // try to close underlying RTCPeerConnection if exposed
5553
- if (p && p.pc && typeof p.pc.close === 'function') {
5554
- try {
5555
- p.pc.close();
5556
- }
5557
- catch (e) {
5558
- // ignore
5559
- }
5560
- }
5561
- }
5562
- }
5563
- catch (e) {
5564
- // ignore
5565
- }
5566
- // If the library supports stop -> start, do that to fully reset signaling state
5567
- if (typeof peernet.stop === 'function') {
5568
- try {
5569
- await peernet.stop();
5570
- }
5571
- catch (e) {
5572
- // ignore stop errors
5573
- }
5485
+ await globalThis.peernet.start();
5574
5486
  }
5575
- // small delay to ensure sockets/RTCs are closed
5576
- await new Promise((r) => setTimeout(r, 250));
5577
- if (typeof peernet.start === 'function') {
5578
- await peernet.start();
5487
+ catch (err) {
5488
+ console.error('❌ peernet.start also failed during restore', err?.message || err);
5579
5489
  }
5580
- else {
5581
- console.warn('⚠️ peernet.start not available for full restart');
5582
- }
5583
- // reset reconnect attempts so we can try fresh
5584
- this.#peerReconnectAttempts = {};
5585
- console.log('✅ Full peernet restart completed');
5586
- }
5587
- catch (e) {
5588
- console.error('❌ Full restart failed:', e?.message || e);
5589
- }
5590
- }
5591
- // Called on visibility/online/resume events
5592
- async #restoreNetwork() {
5593
- console.log('🔁 Restoring network after resume/wake');
5594
- // If there is a peernet instance, try a safe restore
5595
- if (globalThis.peernet) {
5596
- await this.#performFullRestart(globalThis.peernet);
5597
- }
5598
- else {
5599
- // If no global peernet, attempt a normal reconnection flow
5600
- await this.#attemptReconnection();
5601
5490
  }
5602
5491
  }
5603
5492
  async waitForPeers(timeoutMs = 30000) {
@@ -5617,21 +5506,9 @@ class ConnectionMonitor {
5617
5506
  checkPeers();
5618
5507
  });
5619
5508
  }
5620
- // New: attempt reconnection flow (gentle start + sequential per-peer reconnect)
5621
5509
  async #attemptReconnection() {
5622
- console.warn('⚠️ Attempting to reconnect to peers...');
5623
5510
  try {
5624
- // attempt targeted reconnection for disconnected peers sequentially (avoid racing WebRTC state)
5625
- const disconnected = this.disconnectedPeers;
5626
- for (const p of disconnected) {
5627
- // small spacing between attempts to reduce signaling races
5628
- // eslint-disable-next-line no-await-in-loop
5629
- await new Promise((r) => setTimeout(r, 200));
5630
- // eslint-disable-next-line no-await-in-loop
5631
- await this.#attemptPeerReconnection(p);
5632
- }
5633
- // pause before next health check cycle
5634
- await new Promise((resolve) => setTimeout(resolve, this.#reconnectDelay));
5511
+ await this.#restoreNetwork();
5635
5512
  }
5636
5513
  catch (error) {
5637
5514
  console.error('❌ Reconnection failed:', error?.message || error);
@@ -5644,6 +5521,7 @@ class ConnectionMonitor {
5644
5521
  this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
5645
5522
  console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
5646
5523
  }
5524
+ setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
5647
5525
  }
5648
5526
  }
5649
5527
  }
package/exports/chain.js CHANGED
@@ -1493,13 +1493,13 @@ class ConnectionMonitor {
1493
1493
  void this.#restoreNetwork();
1494
1494
  };
1495
1495
  window.addEventListener('online', this.#onOnline);
1496
- this.#onVisibilityChange = () => {
1497
- if (document.visibilityState === 'visible') {
1498
- console.log('💡 Visibility regained — attempting restore');
1499
- void this.#restoreNetwork();
1500
- }
1501
- };
1502
- document.addEventListener('visibilitychange', this.#onVisibilityChange);
1496
+ // this.#onVisibilityChange = () => {
1497
+ // if (document.visibilityState === 'visible') {
1498
+ // console.log('💡 Visibility regained — attempting restore')
1499
+ // void this.#restoreNetwork()
1500
+ // }
1501
+ // }
1502
+ // document.addEventListener('visibilitychange', this.#onVisibilityChange)
1503
1503
  }
1504
1504
  if (typeof process !== 'undefined' && typeof process.on === 'function') {
1505
1505
  this.#onSigcont = () => {
@@ -1558,20 +1558,6 @@ class ConnectionMonitor {
1558
1558
  else if (compatiblePeers.length === 0) {
1559
1559
  console.warn('⚠️ No compatible peers found');
1560
1560
  await this.#attemptReconnection();
1561
- // Could attempt to find compatible peers or trigger version negotiation
1562
- }
1563
- // Log disconnected peers
1564
- const disconnectedPeers = this.disconnectedPeers;
1565
- if (disconnectedPeers.length > 0) {
1566
- console.warn(`⚠️ Disconnected peers: ${disconnectedPeers.map((peer) => peer.peerId).join(', ')}`);
1567
- // Attempt to reconnect each disconnected peer sequentially to avoid racing signaling/state
1568
- for (const peer of disconnectedPeers) {
1569
- // small spacing between attempts to reduce signaling races
1570
- // eslint-disable-next-line no-await-in-loop
1571
- await new Promise((r) => setTimeout(r, 150));
1572
- // eslint-disable-next-line no-await-in-loop
1573
- await this.#attemptPeerReconnection(peer);
1574
- }
1575
1561
  }
1576
1562
  // Publish connection status
1577
1563
  globalThis.pubsub?.publish('connection-status', {
@@ -1580,170 +1566,73 @@ class ConnectionMonitor {
1580
1566
  healthy: compatiblePeers.length > 0
1581
1567
  });
1582
1568
  }
1583
- async #attemptPeerReconnection(peer) {
1584
- if (!peer)
1585
- return;
1586
- const peerId = peer.peerId || peer.id;
1587
- if (!peerId)
1588
- return;
1589
- if (!this.#peerReconnectAttempts[peerId]) {
1590
- this.#peerReconnectAttempts[peerId] = 0;
1591
- }
1592
- if (this.#peerReconnectAttempts[peerId] >= this.#maxReconnectAttempts) {
1593
- console.error('❌ Max reconnection attempts reached for', peerId);
1594
- this.#peerReconnectAttempts[peerId] = 0;
1595
- return;
1596
- }
1597
- this.#peerReconnectAttempts[peerId]++;
1598
- console.log(`🔄 Attempting reconnection ${this.#peerReconnectAttempts[peerId]}/${this.#maxReconnectAttempts} for ${peerId}`);
1599
- try {
1600
- const peernet = globalThis.peernet;
1601
- if (!peernet) {
1602
- console.warn('⚠️ globalThis.peernet not available');
1603
- return;
1569
+ // lightweight TCP probe to detect internet connectivity in Node.js
1570
+ async #isOnLine(timeout = 1500) {
1571
+ // If not running in Node, fallback to navigator.onLine if available, otherwise assume online
1572
+ if (typeof process === 'undefined') {
1573
+ if (navigator?.onLine !== undefined) {
1574
+ return navigator.onLine;
1604
1575
  }
1605
- // Try targeted reconnect if available
1606
- if (peernet.client?.reconnect) {
1607
- try {
1608
- await peernet.client.reconnect(peerId, peernet.stars?.[0]);
1609
- return;
1610
- }
1611
- catch (err) {
1612
- const msg = String(err?.message || err);
1613
- console.warn('⚠️ Targeted reconnect failed:', msg);
1614
- // handle signaling/state mismatches by cleaning up only that peer and retrying targeted reconnect
1615
- if (msg.includes('Called in wrong state') ||
1616
- msg.includes('setRemoteDescription') ||
1617
- msg.includes('channelNames') ||
1618
- msg.includes("channelNames don't match")) {
1619
- console.warn('⚠️ Detected signaling/channel mismatch — cleaning up peer state and retrying targeted reconnect');
1620
- try {
1621
- await this.#cleanupPeerState(peerId, peernet);
1622
- // small backoff before retry
1623
- await new Promise((r) => setTimeout(r, 150));
1624
- await peernet.client.reconnect(peerId, peernet.stars?.[0]);
1625
- return;
1626
- }
1627
- catch (retryErr) {
1628
- console.warn('⚠️ Retry targeted reconnect failed:', String(retryErr?.message || retryErr));
1629
- // fall through to non-targeted fallback below
1630
- }
1576
+ return true;
1577
+ }
1578
+ return new Promise(async (resolve) => {
1579
+ try {
1580
+ // lazy require so bundlers / browser builds don't break
1581
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
1582
+ const net = await import('net');
1583
+ const socket = new net.Socket();
1584
+ let finished = false;
1585
+ const finish = (val) => {
1586
+ if (finished)
1587
+ return;
1588
+ finished = true;
1589
+ try {
1590
+ socket.destroy();
1631
1591
  }
1632
- throw err;
1633
- }
1634
- }
1635
- // If no targeted reconnect, try start/restore
1636
- if (peernet.start) {
1637
- await peernet.start();
1592
+ catch (e) {
1593
+ // ignore
1594
+ }
1595
+ resolve(val);
1596
+ };
1597
+ socket.setTimeout(timeout);
1598
+ socket.once('connect', () => finish(true));
1599
+ socket.once('error', () => finish(false));
1600
+ socket.once('timeout', () => finish(false));
1601
+ // connect to Cloudflare DNS (1.1.1.1) on TCP/53 — fast and reliable
1602
+ socket.connect(53, '1.1.1.1');
1638
1603
  }
1639
- }
1640
- catch (error) {
1641
- console.error('❌ Reconnection failed:', error?.message || error);
1642
- // As fallback, try full restart only if even the cleanup+retry failed
1643
- if (globalThis.peernet) {
1644
- await this.#performFullRestart(globalThis.peernet);
1604
+ catch (e) {
1605
+ resolve(false);
1645
1606
  }
1646
- }
1607
+ });
1647
1608
  }
1648
- // helper: try to close/destroy a single peer connection and remove it from peernet's map
1649
- async #cleanupPeerState(peerId, peernet) {
1609
+ // Called on visibility/online/resume events
1610
+ async #restoreNetwork() {
1611
+ console.log('🔁 Restoring network');
1650
1612
  try {
1651
- const conns = peernet.connections || {};
1652
- const conn = conns[peerId] || conns[Object.keys(conns).find((k) => k.includes(peerId) || peerId.includes(k))];
1653
- if (!conn)
1613
+ const online = await this.#isOnLine(1500);
1614
+ if (!online) {
1615
+ console.warn('⚠️ No internet detected, skipping restore');
1654
1616
  return;
1655
- // close underlying RTCPeerConnection if exposed
1656
- try {
1657
- if (conn.pc && typeof conn.pc.close === 'function') {
1658
- conn.pc.close();
1659
- }
1660
1617
  }
1661
- catch (e) {
1662
- // ignore
1663
- }
1664
- // call any destroy/cleanup API on the connection object
1665
- try {
1666
- if (typeof conn.destroy === 'function') {
1667
- conn.destroy();
1668
- }
1669
- else if (typeof conn.close === 'function') {
1670
- conn.close();
1671
- }
1672
- }
1673
- catch (e) {
1674
- // ignore
1675
- }
1676
- // remove reference so reconnect path will create a fresh one
1677
- try {
1678
- delete peernet.connections[peerId];
1679
- }
1680
- catch (e) {
1681
- // ignore
1682
- }
1683
- // small pause to let underlying sockets/RTCs settle
1684
- await new Promise((r) => setTimeout(r, 100));
1685
1618
  }
1686
1619
  catch (e) {
1687
- // ignore cleanup errors
1620
+ // If the probe failed for any reason, continue with restore attempt
1621
+ console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
1688
1622
  }
1689
- }
1690
- // New helper: close stale RTCPeerConnections if present and then restart peernet
1691
- async #performFullRestart(peernet) {
1692
1623
  try {
1693
- // Close underlying peer RTCPeerConnections if the library exposes them
1624
+ // prefer safe client reinit if available
1625
+ console.log('🔄 Attempting to reinitialize peernet client');
1626
+ await globalThis.peernet.client.reinit();
1627
+ }
1628
+ catch (e) {
1629
+ console.warn('⚠️ peernet.client.reinit failed, falling back to peernet.start if available', e?.message || e);
1694
1630
  try {
1695
- const conns = peernet.connections || {};
1696
- for (const id of Object.keys(conns)) {
1697
- const p = conns[id];
1698
- // try to close underlying RTCPeerConnection if exposed
1699
- if (p && p.pc && typeof p.pc.close === 'function') {
1700
- try {
1701
- p.pc.close();
1702
- }
1703
- catch (e) {
1704
- // ignore
1705
- }
1706
- }
1707
- }
1708
- }
1709
- catch (e) {
1710
- // ignore
1711
- }
1712
- // If the library supports stop -> start, do that to fully reset signaling state
1713
- if (typeof peernet.stop === 'function') {
1714
- try {
1715
- await peernet.stop();
1716
- }
1717
- catch (e) {
1718
- // ignore stop errors
1719
- }
1631
+ await globalThis.peernet.start();
1720
1632
  }
1721
- // small delay to ensure sockets/RTCs are closed
1722
- await new Promise((r) => setTimeout(r, 250));
1723
- if (typeof peernet.start === 'function') {
1724
- await peernet.start();
1633
+ catch (err) {
1634
+ console.error('❌ peernet.start also failed during restore', err?.message || err);
1725
1635
  }
1726
- else {
1727
- console.warn('⚠️ peernet.start not available for full restart');
1728
- }
1729
- // reset reconnect attempts so we can try fresh
1730
- this.#peerReconnectAttempts = {};
1731
- console.log('✅ Full peernet restart completed');
1732
- }
1733
- catch (e) {
1734
- console.error('❌ Full restart failed:', e?.message || e);
1735
- }
1736
- }
1737
- // Called on visibility/online/resume events
1738
- async #restoreNetwork() {
1739
- console.log('🔁 Restoring network after resume/wake');
1740
- // If there is a peernet instance, try a safe restore
1741
- if (globalThis.peernet) {
1742
- await this.#performFullRestart(globalThis.peernet);
1743
- }
1744
- else {
1745
- // If no global peernet, attempt a normal reconnection flow
1746
- await this.#attemptReconnection();
1747
1636
  }
1748
1637
  }
1749
1638
  async waitForPeers(timeoutMs = 30000) {
@@ -1763,21 +1652,9 @@ class ConnectionMonitor {
1763
1652
  checkPeers();
1764
1653
  });
1765
1654
  }
1766
- // New: attempt reconnection flow (gentle start + sequential per-peer reconnect)
1767
1655
  async #attemptReconnection() {
1768
- console.warn('⚠️ Attempting to reconnect to peers...');
1769
1656
  try {
1770
- // attempt targeted reconnection for disconnected peers sequentially (avoid racing WebRTC state)
1771
- const disconnected = this.disconnectedPeers;
1772
- for (const p of disconnected) {
1773
- // small spacing between attempts to reduce signaling races
1774
- // eslint-disable-next-line no-await-in-loop
1775
- await new Promise((r) => setTimeout(r, 200));
1776
- // eslint-disable-next-line no-await-in-loop
1777
- await this.#attemptPeerReconnection(p);
1778
- }
1779
- // pause before next health check cycle
1780
- await new Promise((resolve) => setTimeout(resolve, this.#reconnectDelay));
1657
+ await this.#restoreNetwork();
1781
1658
  }
1782
1659
  catch (error) {
1783
1660
  console.error('❌ Reconnection failed:', error?.message || error);
@@ -1790,6 +1667,7 @@ class ConnectionMonitor {
1790
1667
  this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
1791
1668
  console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
1792
1669
  }
1670
+ setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
1793
1671
  }
1794
1672
  }
1795
1673
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/chain",
3
- "version": "1.7.103",
3
+ "version": "1.7.105",
4
4
  "description": "Official javascript implementation",
5
5
  "private": false,
6
6
  "exports": {