@leofcoin/chain 1.7.104 → 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.
- package/exports/browser/chain.js +75 -60
- package/exports/chain.js +76 -61
- package/package.json +1 -1
package/exports/browser/chain.js
CHANGED
|
@@ -5412,21 +5412,7 @@ 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
5415
|
}
|
|
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
|
-
// }
|
|
5430
5416
|
// Publish connection status
|
|
5431
5417
|
globalThis.pubsub?.publish('connection-status', {
|
|
5432
5418
|
connected: connectedPeers.length,
|
|
@@ -5434,59 +5420,74 @@ class ConnectionMonitor {
|
|
|
5434
5420
|
healthy: compatiblePeers.length > 0
|
|
5435
5421
|
});
|
|
5436
5422
|
}
|
|
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
|
-
}
|
|
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;
|
|
5449
5429
|
}
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
// call any destroy/cleanup API on the connection object
|
|
5430
|
+
return true;
|
|
5431
|
+
}
|
|
5432
|
+
return new Promise(async (resolve) => {
|
|
5454
5433
|
try {
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
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();
|
|
5445
|
+
}
|
|
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');
|
|
5461
5457
|
}
|
|
5462
5458
|
catch (e) {
|
|
5463
|
-
|
|
5464
|
-
}
|
|
5465
|
-
// remove reference so reconnect path will create a fresh one
|
|
5466
|
-
try {
|
|
5467
|
-
delete peernet.connections[peerId];
|
|
5459
|
+
resolve(false);
|
|
5468
5460
|
}
|
|
5469
|
-
|
|
5470
|
-
|
|
5461
|
+
});
|
|
5462
|
+
}
|
|
5463
|
+
// Called on visibility/online/resume events
|
|
5464
|
+
async #restoreNetwork() {
|
|
5465
|
+
console.log('🔁 Restoring network');
|
|
5466
|
+
try {
|
|
5467
|
+
const online = await this.#isOnLine(1500);
|
|
5468
|
+
if (!online) {
|
|
5469
|
+
console.warn('⚠️ No internet detected, skipping restore');
|
|
5470
|
+
return;
|
|
5471
5471
|
}
|
|
5472
|
-
// small pause to let underlying sockets/RTCs settle
|
|
5473
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
5474
5472
|
}
|
|
5475
5473
|
catch (e) {
|
|
5476
|
-
//
|
|
5474
|
+
// If the probe failed for any reason, continue with restore attempt
|
|
5475
|
+
console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
|
|
5476
|
+
}
|
|
5477
|
+
try {
|
|
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);
|
|
5484
|
+
try {
|
|
5485
|
+
await globalThis.peernet.start();
|
|
5486
|
+
}
|
|
5487
|
+
catch (err) {
|
|
5488
|
+
console.error('❌ peernet.start also failed during restore', err?.message || err);
|
|
5489
|
+
}
|
|
5477
5490
|
}
|
|
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
5491
|
}
|
|
5491
5492
|
async waitForPeers(timeoutMs = 30000) {
|
|
5492
5493
|
return new Promise((resolve) => {
|
|
@@ -5505,9 +5506,23 @@ class ConnectionMonitor {
|
|
|
5505
5506
|
checkPeers();
|
|
5506
5507
|
});
|
|
5507
5508
|
}
|
|
5508
|
-
// New: attempt reconnection flow (gentle start + sequential per-peer reconnect)
|
|
5509
5509
|
async #attemptReconnection() {
|
|
5510
|
-
|
|
5510
|
+
try {
|
|
5511
|
+
await this.#restoreNetwork();
|
|
5512
|
+
}
|
|
5513
|
+
catch (error) {
|
|
5514
|
+
console.error('❌ Reconnection failed:', error?.message || error);
|
|
5515
|
+
if (this.#reconnectDelay >= 30000) {
|
|
5516
|
+
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
5517
|
+
this.#reconnectDelay = 5000;
|
|
5518
|
+
}
|
|
5519
|
+
else {
|
|
5520
|
+
// exponential-ish backoff
|
|
5521
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
5522
|
+
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
5523
|
+
}
|
|
5524
|
+
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
5525
|
+
}
|
|
5511
5526
|
}
|
|
5512
5527
|
}
|
|
5513
5528
|
|
package/exports/chain.js
CHANGED
|
@@ -1558,21 +1558,7 @@ class ConnectionMonitor {
|
|
|
1558
1558
|
else if (compatiblePeers.length === 0) {
|
|
1559
1559
|
console.warn('⚠️ No compatible peers found');
|
|
1560
1560
|
await this.#attemptReconnection();
|
|
1561
|
-
|
|
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', {
|
|
1578
1564
|
connected: connectedPeers.length,
|
|
@@ -1580,59 +1566,74 @@ class ConnectionMonitor {
|
|
|
1580
1566
|
healthy: compatiblePeers.length > 0
|
|
1581
1567
|
});
|
|
1582
1568
|
}
|
|
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
|
-
}
|
|
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;
|
|
1595
1575
|
}
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
// call any destroy/cleanup API on the connection object
|
|
1576
|
+
return true;
|
|
1577
|
+
}
|
|
1578
|
+
return new Promise(async (resolve) => {
|
|
1600
1579
|
try {
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
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();
|
|
1591
|
+
}
|
|
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');
|
|
1607
1603
|
}
|
|
1608
1604
|
catch (e) {
|
|
1609
|
-
|
|
1610
|
-
}
|
|
1611
|
-
// remove reference so reconnect path will create a fresh one
|
|
1612
|
-
try {
|
|
1613
|
-
delete peernet.connections[peerId];
|
|
1605
|
+
resolve(false);
|
|
1614
1606
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
// Called on visibility/online/resume events
|
|
1610
|
+
async #restoreNetwork() {
|
|
1611
|
+
console.log('🔁 Restoring network');
|
|
1612
|
+
try {
|
|
1613
|
+
const online = await this.#isOnLine(1500);
|
|
1614
|
+
if (!online) {
|
|
1615
|
+
console.warn('⚠️ No internet detected, skipping restore');
|
|
1616
|
+
return;
|
|
1617
1617
|
}
|
|
1618
|
-
// small pause to let underlying sockets/RTCs settle
|
|
1619
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
1620
1618
|
}
|
|
1621
1619
|
catch (e) {
|
|
1622
|
-
//
|
|
1620
|
+
// If the probe failed for any reason, continue with restore attempt
|
|
1621
|
+
console.warn('⚠️ Online probe failed, proceeding with restore', e?.message || e);
|
|
1622
|
+
}
|
|
1623
|
+
try {
|
|
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);
|
|
1630
|
+
try {
|
|
1631
|
+
await globalThis.peernet.start();
|
|
1632
|
+
}
|
|
1633
|
+
catch (err) {
|
|
1634
|
+
console.error('❌ peernet.start also failed during restore', err?.message || err);
|
|
1635
|
+
}
|
|
1623
1636
|
}
|
|
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
1637
|
}
|
|
1637
1638
|
async waitForPeers(timeoutMs = 30000) {
|
|
1638
1639
|
return new Promise((resolve) => {
|
|
@@ -1651,9 +1652,23 @@ class ConnectionMonitor {
|
|
|
1651
1652
|
checkPeers();
|
|
1652
1653
|
});
|
|
1653
1654
|
}
|
|
1654
|
-
// New: attempt reconnection flow (gentle start + sequential per-peer reconnect)
|
|
1655
1655
|
async #attemptReconnection() {
|
|
1656
|
-
|
|
1656
|
+
try {
|
|
1657
|
+
await this.#restoreNetwork();
|
|
1658
|
+
}
|
|
1659
|
+
catch (error) {
|
|
1660
|
+
console.error('❌ Reconnection failed:', error?.message || error);
|
|
1661
|
+
if (this.#reconnectDelay >= 30000) {
|
|
1662
|
+
console.warn('⚠️ Reconnection delay reached maximum, resetting to 5 seconds');
|
|
1663
|
+
this.#reconnectDelay = 5000;
|
|
1664
|
+
}
|
|
1665
|
+
else {
|
|
1666
|
+
// exponential-ish backoff
|
|
1667
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
1668
|
+
console.warn(`⚠️ Increasing reconnection delay to ${this.#reconnectDelay} ms`);
|
|
1669
|
+
}
|
|
1670
|
+
setTimeout(() => this.#attemptReconnection(), this.#reconnectDelay);
|
|
1671
|
+
}
|
|
1657
1672
|
}
|
|
1658
1673
|
}
|
|
1659
1674
|
|