@leofcoin/chain 1.7.104 → 1.7.106
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 +81 -67
- package/exports/chain.js +81 -67
- package/package.json +1 -1
package/exports/browser/chain.js
CHANGED
|
@@ -5405,27 +5405,12 @@ class ConnectionMonitor {
|
|
|
5405
5405
|
const connectedPeers = this.connectedPeers;
|
|
5406
5406
|
const compatiblePeers = this.compatiblePeers;
|
|
5407
5407
|
console.log(`🔍 Health check: ${connectedPeers.length} connected, ${compatiblePeers.length} compatible`);
|
|
5408
|
-
if (connectedPeers.length === 0) {
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
}
|
|
5412
|
-
|
|
5413
|
-
|
|
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
|
-
// }
|
|
5408
|
+
// if (connectedPeers.length === 0) {
|
|
5409
|
+
console.warn('⚠️ No peer connections detected');
|
|
5410
|
+
// await this.#attemptReconnection()
|
|
5411
|
+
// } else if (compatiblePeers.length === 0) {
|
|
5412
|
+
console.warn('⚠️ No compatible peers found');
|
|
5413
|
+
// await this.#attemptReconnection()
|
|
5429
5414
|
// }
|
|
5430
5415
|
// Publish connection status
|
|
5431
5416
|
globalThis.pubsub?.publish('connection-status', {
|
|
@@ -5434,59 +5419,74 @@ class ConnectionMonitor {
|
|
|
5434
5419
|
healthy: compatiblePeers.length > 0
|
|
5435
5420
|
});
|
|
5436
5421
|
}
|
|
5437
|
-
//
|
|
5438
|
-
async #
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
return;
|
|
5444
|
-
// close underlying RTCPeerConnection if exposed
|
|
5445
|
-
try {
|
|
5446
|
-
if (conn.pc && typeof conn.pc.close === 'function') {
|
|
5447
|
-
conn.pc.close();
|
|
5448
|
-
}
|
|
5422
|
+
// lightweight TCP probe to detect internet connectivity in Node.js
|
|
5423
|
+
async #isOnLine(timeout = 1500) {
|
|
5424
|
+
// If not running in Node, fallback to navigator.onLine if available, otherwise assume online
|
|
5425
|
+
if (typeof process === 'undefined') {
|
|
5426
|
+
if (navigator?.onLine !== undefined) {
|
|
5427
|
+
return navigator.onLine;
|
|
5449
5428
|
}
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
// call any destroy/cleanup API on the connection object
|
|
5429
|
+
return true;
|
|
5430
|
+
}
|
|
5431
|
+
return new Promise(async (resolve) => {
|
|
5454
5432
|
try {
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5433
|
+
// lazy require so bundlers / browser builds don't break
|
|
5434
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
5435
|
+
const net = await import('net');
|
|
5436
|
+
const socket = new net.Socket();
|
|
5437
|
+
let finished = false;
|
|
5438
|
+
const finish = (val) => {
|
|
5439
|
+
if (finished)
|
|
5440
|
+
return;
|
|
5441
|
+
finished = true;
|
|
5442
|
+
try {
|
|
5443
|
+
socket.destroy();
|
|
5444
|
+
}
|
|
5445
|
+
catch (e) {
|
|
5446
|
+
// ignore
|
|
5447
|
+
}
|
|
5448
|
+
resolve(val);
|
|
5449
|
+
};
|
|
5450
|
+
socket.setTimeout(timeout);
|
|
5451
|
+
socket.once('connect', () => finish(true));
|
|
5452
|
+
socket.once('error', () => finish(false));
|
|
5453
|
+
socket.once('timeout', () => finish(false));
|
|
5454
|
+
// connect to Cloudflare DNS (1.1.1.1) on TCP/53 — fast and reliable
|
|
5455
|
+
socket.connect(53, '1.1.1.1');
|
|
5461
5456
|
}
|
|
5462
5457
|
catch (e) {
|
|
5463
|
-
|
|
5464
|
-
}
|
|
5465
|
-
// remove reference so reconnect path will create a fresh one
|
|
5466
|
-
try {
|
|
5467
|
-
delete peernet.connections[peerId];
|
|
5458
|
+
resolve(false);
|
|
5468
5459
|
}
|
|
5469
|
-
|
|
5470
|
-
|
|
5460
|
+
});
|
|
5461
|
+
}
|
|
5462
|
+
// Called on visibility/online/resume events
|
|
5463
|
+
async #restoreNetwork() {
|
|
5464
|
+
console.log('🔁 Restoring network');
|
|
5465
|
+
try {
|
|
5466
|
+
const online = await this.#isOnLine(1500);
|
|
5467
|
+
if (!online) {
|
|
5468
|
+
console.warn('⚠️ No internet detected, skipping restore');
|
|
5469
|
+
return;
|
|
5471
5470
|
}
|
|
5472
|
-
// small pause to let underlying sockets/RTCs settle
|
|
5473
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
5474
5471
|
}
|
|
5475
5472
|
catch (e) {
|
|
5476
|
-
//
|
|
5473
|
+
// If the probe failed for any reason, continue with restore attempt
|
|
5474
|
+
console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
|
|
5475
|
+
}
|
|
5476
|
+
try {
|
|
5477
|
+
// prefer safe client reinit if available
|
|
5478
|
+
console.log('🔄 Attempting to reinitialize peernet client');
|
|
5479
|
+
await globalThis.peernet.client.reinit();
|
|
5480
|
+
}
|
|
5481
|
+
catch (e) {
|
|
5482
|
+
console.warn('⚠️ peernet.client.reinit failed, falling back to peernet.start if available', e?.message || e);
|
|
5483
|
+
try {
|
|
5484
|
+
await globalThis.peernet.start();
|
|
5485
|
+
}
|
|
5486
|
+
catch (err) {
|
|
5487
|
+
console.error('❌ peernet.start also failed during restore', err?.message || err);
|
|
5488
|
+
}
|
|
5477
5489
|
}
|
|
5478
|
-
}
|
|
5479
|
-
// Called on visibility/online/resume events
|
|
5480
|
-
async #restoreNetwork() {
|
|
5481
|
-
console.log('🔁 Restoring network after resume/wake');
|
|
5482
|
-
globalThis.peernet.client.reinit();
|
|
5483
|
-
// If there is a peernet instance, try a safe restore
|
|
5484
|
-
// if (globalThis.peernet) {
|
|
5485
|
-
// await this.#performFullRestart(globalThis.peernet)
|
|
5486
|
-
// } else {
|
|
5487
|
-
// // If no global peernet, attempt a normal reconnection flow
|
|
5488
|
-
// await this.#attemptReconnection()
|
|
5489
|
-
// }
|
|
5490
5490
|
}
|
|
5491
5491
|
async waitForPeers(timeoutMs = 30000) {
|
|
5492
5492
|
return new Promise((resolve) => {
|
|
@@ -5505,9 +5505,23 @@ class ConnectionMonitor {
|
|
|
5505
5505
|
checkPeers();
|
|
5506
5506
|
});
|
|
5507
5507
|
}
|
|
5508
|
-
// New: attempt reconnection flow (gentle start + sequential per-peer reconnect)
|
|
5509
5508
|
async #attemptReconnection() {
|
|
5510
|
-
|
|
5509
|
+
try {
|
|
5510
|
+
await this.#restoreNetwork();
|
|
5511
|
+
}
|
|
5512
|
+
catch (error) {
|
|
5513
|
+
console.error('❌ Reconnection failed:', error?.message || error);
|
|
5514
|
+
if (this.#reconnectDelay >= 30000) {
|
|
5515
|
+
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
5516
|
+
this.#reconnectDelay = 5000;
|
|
5517
|
+
}
|
|
5518
|
+
else {
|
|
5519
|
+
// exponential-ish backoff
|
|
5520
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
5521
|
+
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
5522
|
+
}
|
|
5523
|
+
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
5524
|
+
}
|
|
5511
5525
|
}
|
|
5512
5526
|
}
|
|
5513
5527
|
|
package/exports/chain.js
CHANGED
|
@@ -1551,27 +1551,12 @@ class ConnectionMonitor {
|
|
|
1551
1551
|
const connectedPeers = this.connectedPeers;
|
|
1552
1552
|
const compatiblePeers = this.compatiblePeers;
|
|
1553
1553
|
console.log(`🔍 Health check: ${connectedPeers.length} connected, ${compatiblePeers.length} compatible`);
|
|
1554
|
-
if (connectedPeers.length === 0) {
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
|
|
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
|
-
// }
|
|
1554
|
+
// if (connectedPeers.length === 0) {
|
|
1555
|
+
console.warn('⚠️ No peer connections detected');
|
|
1556
|
+
// await this.#attemptReconnection()
|
|
1557
|
+
// } else if (compatiblePeers.length === 0) {
|
|
1558
|
+
console.warn('⚠️ No compatible peers found');
|
|
1559
|
+
// await this.#attemptReconnection()
|
|
1575
1560
|
// }
|
|
1576
1561
|
// Publish connection status
|
|
1577
1562
|
globalThis.pubsub?.publish('connection-status', {
|
|
@@ -1580,59 +1565,74 @@ class ConnectionMonitor {
|
|
|
1580
1565
|
healthy: compatiblePeers.length > 0
|
|
1581
1566
|
});
|
|
1582
1567
|
}
|
|
1583
|
-
//
|
|
1584
|
-
async #
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
return;
|
|
1590
|
-
// close underlying RTCPeerConnection if exposed
|
|
1591
|
-
try {
|
|
1592
|
-
if (conn.pc && typeof conn.pc.close === 'function') {
|
|
1593
|
-
conn.pc.close();
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
catch (e) {
|
|
1597
|
-
// ignore
|
|
1568
|
+
// lightweight TCP probe to detect internet connectivity in Node.js
|
|
1569
|
+
async #isOnLine(timeout = 1500) {
|
|
1570
|
+
// If not running in Node, fallback to navigator.onLine if available, otherwise assume online
|
|
1571
|
+
if (typeof process === 'undefined') {
|
|
1572
|
+
if (navigator?.onLine !== undefined) {
|
|
1573
|
+
return navigator.onLine;
|
|
1598
1574
|
}
|
|
1599
|
-
|
|
1575
|
+
return true;
|
|
1576
|
+
}
|
|
1577
|
+
return new Promise(async (resolve) => {
|
|
1600
1578
|
try {
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1579
|
+
// lazy require so bundlers / browser builds don't break
|
|
1580
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
1581
|
+
const net = await import('net');
|
|
1582
|
+
const socket = new net.Socket();
|
|
1583
|
+
let finished = false;
|
|
1584
|
+
const finish = (val) => {
|
|
1585
|
+
if (finished)
|
|
1586
|
+
return;
|
|
1587
|
+
finished = true;
|
|
1588
|
+
try {
|
|
1589
|
+
socket.destroy();
|
|
1590
|
+
}
|
|
1591
|
+
catch (e) {
|
|
1592
|
+
// ignore
|
|
1593
|
+
}
|
|
1594
|
+
resolve(val);
|
|
1595
|
+
};
|
|
1596
|
+
socket.setTimeout(timeout);
|
|
1597
|
+
socket.once('connect', () => finish(true));
|
|
1598
|
+
socket.once('error', () => finish(false));
|
|
1599
|
+
socket.once('timeout', () => finish(false));
|
|
1600
|
+
// connect to Cloudflare DNS (1.1.1.1) on TCP/53 — fast and reliable
|
|
1601
|
+
socket.connect(53, '1.1.1.1');
|
|
1607
1602
|
}
|
|
1608
1603
|
catch (e) {
|
|
1609
|
-
|
|
1610
|
-
}
|
|
1611
|
-
// remove reference so reconnect path will create a fresh one
|
|
1612
|
-
try {
|
|
1613
|
-
delete peernet.connections[peerId];
|
|
1604
|
+
resolve(false);
|
|
1614
1605
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
// Called on visibility/online/resume events
|
|
1609
|
+
async #restoreNetwork() {
|
|
1610
|
+
console.log('🔁 Restoring network');
|
|
1611
|
+
try {
|
|
1612
|
+
const online = await this.#isOnLine(1500);
|
|
1613
|
+
if (!online) {
|
|
1614
|
+
console.warn('⚠️ No internet detected, skipping restore');
|
|
1615
|
+
return;
|
|
1617
1616
|
}
|
|
1618
|
-
// small pause to let underlying sockets/RTCs settle
|
|
1619
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
1620
1617
|
}
|
|
1621
1618
|
catch (e) {
|
|
1622
|
-
//
|
|
1619
|
+
// If the probe failed for any reason, continue with restore attempt
|
|
1620
|
+
console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
|
|
1621
|
+
}
|
|
1622
|
+
try {
|
|
1623
|
+
// prefer safe client reinit if available
|
|
1624
|
+
console.log('🔄 Attempting to reinitialize peernet client');
|
|
1625
|
+
await globalThis.peernet.client.reinit();
|
|
1626
|
+
}
|
|
1627
|
+
catch (e) {
|
|
1628
|
+
console.warn('⚠️ peernet.client.reinit failed, falling back to peernet.start if available', e?.message || e);
|
|
1629
|
+
try {
|
|
1630
|
+
await globalThis.peernet.start();
|
|
1631
|
+
}
|
|
1632
|
+
catch (err) {
|
|
1633
|
+
console.error('❌ peernet.start also failed during restore', err?.message || err);
|
|
1634
|
+
}
|
|
1623
1635
|
}
|
|
1624
|
-
}
|
|
1625
|
-
// Called on visibility/online/resume events
|
|
1626
|
-
async #restoreNetwork() {
|
|
1627
|
-
console.log('🔁 Restoring network after resume/wake');
|
|
1628
|
-
globalThis.peernet.client.reinit();
|
|
1629
|
-
// If there is a peernet instance, try a safe restore
|
|
1630
|
-
// if (globalThis.peernet) {
|
|
1631
|
-
// await this.#performFullRestart(globalThis.peernet)
|
|
1632
|
-
// } else {
|
|
1633
|
-
// // If no global peernet, attempt a normal reconnection flow
|
|
1634
|
-
// await this.#attemptReconnection()
|
|
1635
|
-
// }
|
|
1636
1636
|
}
|
|
1637
1637
|
async waitForPeers(timeoutMs = 30000) {
|
|
1638
1638
|
return new Promise((resolve) => {
|
|
@@ -1651,9 +1651,23 @@ class ConnectionMonitor {
|
|
|
1651
1651
|
checkPeers();
|
|
1652
1652
|
});
|
|
1653
1653
|
}
|
|
1654
|
-
// New: attempt reconnection flow (gentle start + sequential per-peer reconnect)
|
|
1655
1654
|
async #attemptReconnection() {
|
|
1656
|
-
|
|
1655
|
+
try {
|
|
1656
|
+
await this.#restoreNetwork();
|
|
1657
|
+
}
|
|
1658
|
+
catch (error) {
|
|
1659
|
+
console.error('❌ Reconnection failed:', error?.message || error);
|
|
1660
|
+
if (this.#reconnectDelay >= 30000) {
|
|
1661
|
+
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
1662
|
+
this.#reconnectDelay = 5000;
|
|
1663
|
+
}
|
|
1664
|
+
else {
|
|
1665
|
+
// exponential-ish backoff
|
|
1666
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
1667
|
+
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
1668
|
+
}
|
|
1669
|
+
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
1670
|
+
}
|
|
1657
1671
|
}
|
|
1658
1672
|
}
|
|
1659
1673
|
|