@leofcoin/chain 1.7.73 → 1.7.74
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 +168 -5
- package/exports/browser/{client-DD7vhDK_-UAymLS2i.js → client-DD7vhDK_-BdNAdRzV.js} +1 -1
- package/exports/browser/{messages-CW17jRdc-c9cSXiiQ.js → messages-CW17jRdc-Dtrj-vba.js} +1 -1
- package/exports/browser/{node-browser-BvxzAdLe.js → node-browser-DMmrhyQS.js} +3 -3
- package/exports/browser/node-browser.js +1 -1
- package/exports/chain.js +168 -5
- package/exports/connection-monitor.d.ts +14 -0
- package/exports/sync-controller.d.ts +3 -2
- package/package.json +1 -1
package/exports/browser/chain.js
CHANGED
|
@@ -5201,6 +5201,12 @@ class State extends Contract {
|
|
|
5201
5201
|
get shouldSync() {
|
|
5202
5202
|
if (this.#chainSyncing)
|
|
5203
5203
|
return false;
|
|
5204
|
+
// Check if we have any connected peers with the same version
|
|
5205
|
+
const compatiblePeers = Object.values(globalThis.peernet.connections || {}).filter((peer) => peer.connected && peer.version === this.version);
|
|
5206
|
+
if (compatiblePeers.length === 0) {
|
|
5207
|
+
debug$1('No compatible peers available for sync');
|
|
5208
|
+
return false;
|
|
5209
|
+
}
|
|
5204
5210
|
if (!this.#chainSyncing ||
|
|
5205
5211
|
this.#resolveErrored ||
|
|
5206
5212
|
this.#syncState === 'errored' ||
|
|
@@ -5209,6 +5215,25 @@ class State extends Contract {
|
|
|
5209
5215
|
return true;
|
|
5210
5216
|
return false;
|
|
5211
5217
|
}
|
|
5218
|
+
async #waitForPeers(timeoutMs = 30000) {
|
|
5219
|
+
return new Promise((resolve) => {
|
|
5220
|
+
const checkPeers = () => {
|
|
5221
|
+
const peers = Object.values(globalThis.peernet.connections || {}).filter((peer) => peer.connected && peer.version === this.version);
|
|
5222
|
+
if (peers.length > 0) {
|
|
5223
|
+
resolve(true);
|
|
5224
|
+
}
|
|
5225
|
+
};
|
|
5226
|
+
// Check immediately
|
|
5227
|
+
checkPeers();
|
|
5228
|
+
// Set up interval to check periodically
|
|
5229
|
+
const interval = setInterval(checkPeers, 1000);
|
|
5230
|
+
// Set timeout
|
|
5231
|
+
setTimeout(() => {
|
|
5232
|
+
clearInterval(interval);
|
|
5233
|
+
resolve(false);
|
|
5234
|
+
}, timeoutMs);
|
|
5235
|
+
});
|
|
5236
|
+
}
|
|
5212
5237
|
async triggerSync() {
|
|
5213
5238
|
const latest = await this.#getLatestBlock();
|
|
5214
5239
|
return this.syncChain(latest);
|
|
@@ -5268,6 +5293,112 @@ class VersionControl extends State {
|
|
|
5268
5293
|
}
|
|
5269
5294
|
}
|
|
5270
5295
|
|
|
5296
|
+
/**
|
|
5297
|
+
* Connection Monitor - Monitors peer connections and handles reconnection logic
|
|
5298
|
+
*/
|
|
5299
|
+
class ConnectionMonitor {
|
|
5300
|
+
#isMonitoring = false;
|
|
5301
|
+
#checkInterval = null;
|
|
5302
|
+
#reconnectAttempts = 0;
|
|
5303
|
+
#maxReconnectAttempts = 10;
|
|
5304
|
+
#reconnectDelay = 5000;
|
|
5305
|
+
#healthCheckInterval = 10000;
|
|
5306
|
+
get isMonitoring() {
|
|
5307
|
+
return this.#isMonitoring;
|
|
5308
|
+
}
|
|
5309
|
+
get connectedPeers() {
|
|
5310
|
+
return Object.values(globalThis.peernet?.connections || {}).filter((peer) => peer.connected);
|
|
5311
|
+
}
|
|
5312
|
+
get compatiblePeers() {
|
|
5313
|
+
return this.connectedPeers.filter((peer) => peer.version === this.version);
|
|
5314
|
+
}
|
|
5315
|
+
constructor(version) {
|
|
5316
|
+
this.version = version;
|
|
5317
|
+
}
|
|
5318
|
+
start() {
|
|
5319
|
+
if (this.#isMonitoring)
|
|
5320
|
+
return;
|
|
5321
|
+
this.#isMonitoring = true;
|
|
5322
|
+
console.log('🔄 Starting connection monitor...');
|
|
5323
|
+
this.#checkInterval = setInterval(() => {
|
|
5324
|
+
this.#healthCheck();
|
|
5325
|
+
}, this.#healthCheckInterval);
|
|
5326
|
+
// Initial health check
|
|
5327
|
+
this.#healthCheck();
|
|
5328
|
+
}
|
|
5329
|
+
stop() {
|
|
5330
|
+
if (!this.#isMonitoring)
|
|
5331
|
+
return;
|
|
5332
|
+
this.#isMonitoring = false;
|
|
5333
|
+
if (this.#checkInterval) {
|
|
5334
|
+
clearInterval(this.#checkInterval);
|
|
5335
|
+
this.#checkInterval = null;
|
|
5336
|
+
}
|
|
5337
|
+
console.log('⏹️ Connection monitor stopped');
|
|
5338
|
+
}
|
|
5339
|
+
async #healthCheck() {
|
|
5340
|
+
const connectedPeers = this.connectedPeers;
|
|
5341
|
+
const compatiblePeers = this.compatiblePeers;
|
|
5342
|
+
console.log(`🔍 Health check: ${connectedPeers.length} connected, ${compatiblePeers.length} compatible`);
|
|
5343
|
+
if (connectedPeers.length === 0) {
|
|
5344
|
+
console.warn('⚠️ No peer connections detected');
|
|
5345
|
+
await this.#attemptReconnection();
|
|
5346
|
+
}
|
|
5347
|
+
else if (compatiblePeers.length === 0) {
|
|
5348
|
+
console.warn('⚠️ No compatible peers found');
|
|
5349
|
+
// Could attempt to find compatible peers or trigger version negotiation
|
|
5350
|
+
}
|
|
5351
|
+
else {
|
|
5352
|
+
// Reset reconnect attempts on successful connection
|
|
5353
|
+
this.#reconnectAttempts = 0;
|
|
5354
|
+
}
|
|
5355
|
+
// Publish connection status
|
|
5356
|
+
globalThis.pubsub?.publish('connection-status', {
|
|
5357
|
+
connected: connectedPeers.length,
|
|
5358
|
+
compatible: compatiblePeers.length,
|
|
5359
|
+
healthy: compatiblePeers.length > 0
|
|
5360
|
+
});
|
|
5361
|
+
}
|
|
5362
|
+
async #attemptReconnection() {
|
|
5363
|
+
if (this.#reconnectAttempts >= this.#maxReconnectAttempts) {
|
|
5364
|
+
console.error('❌ Max reconnection attempts reached');
|
|
5365
|
+
return;
|
|
5366
|
+
}
|
|
5367
|
+
this.#reconnectAttempts++;
|
|
5368
|
+
console.log(`🔄 Attempting reconnection ${this.#reconnectAttempts}/${this.#maxReconnectAttempts}`);
|
|
5369
|
+
try {
|
|
5370
|
+
// Try to restart the network
|
|
5371
|
+
if (globalThis.peernet?.start) {
|
|
5372
|
+
await globalThis.peernet.start();
|
|
5373
|
+
}
|
|
5374
|
+
// Wait a bit before next check
|
|
5375
|
+
await new Promise((resolve) => setTimeout(resolve, this.#reconnectDelay));
|
|
5376
|
+
}
|
|
5377
|
+
catch (error) {
|
|
5378
|
+
console.error('❌ Reconnection failed:', error.message);
|
|
5379
|
+
// Exponential backoff
|
|
5380
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
5381
|
+
}
|
|
5382
|
+
}
|
|
5383
|
+
async waitForPeers(timeoutMs = 30000) {
|
|
5384
|
+
return new Promise((resolve) => {
|
|
5385
|
+
const startTime = Date.now();
|
|
5386
|
+
const checkPeers = () => {
|
|
5387
|
+
if (this.compatiblePeers.length > 0) {
|
|
5388
|
+
resolve(true);
|
|
5389
|
+
return;
|
|
5390
|
+
}
|
|
5391
|
+
if (Date.now() - startTime >= timeoutMs) {
|
|
5392
|
+
resolve(false);
|
|
5393
|
+
return;
|
|
5394
|
+
}
|
|
5395
|
+
setTimeout(checkPeers, 1000);
|
|
5396
|
+
};
|
|
5397
|
+
checkPeers();
|
|
5398
|
+
});
|
|
5399
|
+
}
|
|
5400
|
+
}
|
|
5401
|
+
|
|
5271
5402
|
const debug = globalThis.createDebugger('leofcoin/chain');
|
|
5272
5403
|
// check if browser or local
|
|
5273
5404
|
class Chain extends VersionControl {
|
|
@@ -5280,6 +5411,10 @@ class Chain extends VersionControl {
|
|
|
5280
5411
|
#participants;
|
|
5281
5412
|
#participating;
|
|
5282
5413
|
#jail;
|
|
5414
|
+
#peerConnectionRetries;
|
|
5415
|
+
#maxPeerRetries;
|
|
5416
|
+
#peerRetryDelay;
|
|
5417
|
+
#connectionMonitor;
|
|
5283
5418
|
constructor(config) {
|
|
5284
5419
|
super(config);
|
|
5285
5420
|
this.#slotTime = 10000;
|
|
@@ -5291,6 +5426,9 @@ class Chain extends VersionControl {
|
|
|
5291
5426
|
this.#participants = [];
|
|
5292
5427
|
this.#participating = false;
|
|
5293
5428
|
this.#jail = [];
|
|
5429
|
+
this.#peerConnectionRetries = new Map();
|
|
5430
|
+
this.#maxPeerRetries = 5;
|
|
5431
|
+
this.#peerRetryDelay = 5000;
|
|
5294
5432
|
this.#addTransaction = async (message) => {
|
|
5295
5433
|
const transaction = new TransactionMessage(message);
|
|
5296
5434
|
const hash = await transaction.hash();
|
|
@@ -5365,6 +5503,7 @@ class Chain extends VersionControl {
|
|
|
5365
5503
|
// this.node = await new Node()
|
|
5366
5504
|
this.#participants = [];
|
|
5367
5505
|
this.#participating = false;
|
|
5506
|
+
this.#connectionMonitor = new ConnectionMonitor(this.version);
|
|
5368
5507
|
const initialized = await globalThis.contractStore.has(addresses.contractFactory);
|
|
5369
5508
|
if (!initialized)
|
|
5370
5509
|
await this.#setup();
|
|
@@ -5372,8 +5511,11 @@ class Chain extends VersionControl {
|
|
|
5372
5511
|
// this.#state = new State()
|
|
5373
5512
|
// todo some functions rely on state
|
|
5374
5513
|
await super.init();
|
|
5514
|
+
// Start connection monitoring
|
|
5515
|
+
this.#connectionMonitor.start();
|
|
5375
5516
|
await globalThis.peernet.addRequestHandler('bw-request-message', () => {
|
|
5376
|
-
|
|
5517
|
+
const bw = globalThis.peernet.client?.bw || { up: 0, down: 0 };
|
|
5518
|
+
return new BWMessage(bw);
|
|
5377
5519
|
});
|
|
5378
5520
|
// await globalThis.peernet.addRequestHandler('peerId', () => {
|
|
5379
5521
|
// let node =
|
|
@@ -5454,7 +5596,7 @@ class Chain extends VersionControl {
|
|
|
5454
5596
|
}
|
|
5455
5597
|
}
|
|
5456
5598
|
if (this.wantList.length > 0) {
|
|
5457
|
-
const promises = await Promise.allSettled(this.wantList.map((hash) => peernet.get(hash)));
|
|
5599
|
+
const promises = await Promise.allSettled(this.wantList.map((hash) => peernet.get(hash, 'block')));
|
|
5458
5600
|
for (let i = 0; i < promises.length; i++) {
|
|
5459
5601
|
const result = promises[i];
|
|
5460
5602
|
if (result.status === 'fulfilled')
|
|
@@ -5781,7 +5923,7 @@ class Chain extends VersionControl {
|
|
|
5781
5923
|
* @returns
|
|
5782
5924
|
*/
|
|
5783
5925
|
internalCall(sender, contract, method, parameters) {
|
|
5784
|
-
globalThis.msg = this.#createMessage(sender, contract)
|
|
5926
|
+
// globalThis.msg = this.#createMessage(sender, contract) // Debug line removed
|
|
5785
5927
|
return this.machine.execute(contract, method, parameters);
|
|
5786
5928
|
}
|
|
5787
5929
|
/**
|
|
@@ -5792,11 +5934,11 @@ class Chain extends VersionControl {
|
|
|
5792
5934
|
* @returns
|
|
5793
5935
|
*/
|
|
5794
5936
|
call(contract, method, parameters) {
|
|
5795
|
-
globalThis.msg = this.#createMessage(peernet.selectedAccount, contract)
|
|
5937
|
+
// globalThis.msg = this.#createMessage(peernet.selectedAccount, contract) // Debug line removed
|
|
5796
5938
|
return this.machine.execute(contract, method, parameters);
|
|
5797
5939
|
}
|
|
5798
5940
|
staticCall(contract, method, parameters) {
|
|
5799
|
-
globalThis.msg = this.#createMessage(peernet.selectedAccount, contract)
|
|
5941
|
+
// globalThis.msg = this.#createMessage(peernet.selectedAccount, contract) // Debug line removed
|
|
5800
5942
|
return this.machine.get(contract, method, parameters);
|
|
5801
5943
|
}
|
|
5802
5944
|
mint(to, amount) {
|
|
@@ -5826,6 +5968,27 @@ class Chain extends VersionControl {
|
|
|
5826
5968
|
lookup(name) {
|
|
5827
5969
|
return this.call(addresses.nameService, 'lookup', [name]);
|
|
5828
5970
|
}
|
|
5971
|
+
#monitorPeerConnections() {
|
|
5972
|
+
setInterval(() => {
|
|
5973
|
+
const connectedPeers = Object.values(globalThis.peernet.connections).filter((peer) => peer.connected);
|
|
5974
|
+
debug(`Connected peers: ${connectedPeers.length}`);
|
|
5975
|
+
if (connectedPeers.length === 0) {
|
|
5976
|
+
debug('No peers connected, attempting to reconnect...');
|
|
5977
|
+
this.#attemptPeerReconnection();
|
|
5978
|
+
}
|
|
5979
|
+
}, 10000); // Check every 10 seconds
|
|
5980
|
+
}
|
|
5981
|
+
async #attemptPeerReconnection() {
|
|
5982
|
+
try {
|
|
5983
|
+
// Try to reconnect to star servers
|
|
5984
|
+
if (globalThis.peernet && globalThis.peernet.start) {
|
|
5985
|
+
await globalThis.peernet.start();
|
|
5986
|
+
}
|
|
5987
|
+
}
|
|
5988
|
+
catch (error) {
|
|
5989
|
+
console.warn('Failed to reconnect to peers:', error.message);
|
|
5990
|
+
}
|
|
5991
|
+
}
|
|
5829
5992
|
}
|
|
5830
5993
|
|
|
5831
5994
|
export { Chain as default };
|
|
@@ -8495,7 +8495,7 @@ class Peernet {
|
|
|
8495
8495
|
this.root = options.root;
|
|
8496
8496
|
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile
|
|
8497
8497
|
// FolderMessageResponse
|
|
8498
|
-
} = await import(/* webpackChunkName: "messages" */ './messages-CW17jRdc-
|
|
8498
|
+
} = await import(/* webpackChunkName: "messages" */ './messages-CW17jRdc-Dtrj-vba.js');
|
|
8499
8499
|
/**
|
|
8500
8500
|
* proto Object containing protos
|
|
8501
8501
|
* @type {Object}
|
|
@@ -8589,7 +8589,7 @@ class Peernet {
|
|
|
8589
8589
|
if (this.#starting || this.#started)
|
|
8590
8590
|
return;
|
|
8591
8591
|
this.#starting = true;
|
|
8592
|
-
const importee = await import('./client-DD7vhDK_-
|
|
8592
|
+
const importee = await import('./client-DD7vhDK_-BdNAdRzV.js');
|
|
8593
8593
|
/**
|
|
8594
8594
|
* @access public
|
|
8595
8595
|
* @type {PeernetClient}
|
|
@@ -9078,7 +9078,7 @@ globalThis.Peernet = Peernet;
|
|
|
9078
9078
|
var networks = {
|
|
9079
9079
|
leofcoin: {
|
|
9080
9080
|
peach: {
|
|
9081
|
-
stars: ['wss://star.leofcoin.org'] //
|
|
9081
|
+
stars: ['wss://star-testnet.leofcoin.org', 'wss://star.leofcoin.org'] // Separate testnet stars
|
|
9082
9082
|
}
|
|
9083
9083
|
}
|
|
9084
9084
|
};
|
package/exports/chain.js
CHANGED
|
@@ -1347,6 +1347,12 @@ class State extends Contract {
|
|
|
1347
1347
|
get shouldSync() {
|
|
1348
1348
|
if (this.#chainSyncing)
|
|
1349
1349
|
return false;
|
|
1350
|
+
// Check if we have any connected peers with the same version
|
|
1351
|
+
const compatiblePeers = Object.values(globalThis.peernet.connections || {}).filter((peer) => peer.connected && peer.version === this.version);
|
|
1352
|
+
if (compatiblePeers.length === 0) {
|
|
1353
|
+
debug$1('No compatible peers available for sync');
|
|
1354
|
+
return false;
|
|
1355
|
+
}
|
|
1350
1356
|
if (!this.#chainSyncing ||
|
|
1351
1357
|
this.#resolveErrored ||
|
|
1352
1358
|
this.#syncState === 'errored' ||
|
|
@@ -1355,6 +1361,25 @@ class State extends Contract {
|
|
|
1355
1361
|
return true;
|
|
1356
1362
|
return false;
|
|
1357
1363
|
}
|
|
1364
|
+
async #waitForPeers(timeoutMs = 30000) {
|
|
1365
|
+
return new Promise((resolve) => {
|
|
1366
|
+
const checkPeers = () => {
|
|
1367
|
+
const peers = Object.values(globalThis.peernet.connections || {}).filter((peer) => peer.connected && peer.version === this.version);
|
|
1368
|
+
if (peers.length > 0) {
|
|
1369
|
+
resolve(true);
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
// Check immediately
|
|
1373
|
+
checkPeers();
|
|
1374
|
+
// Set up interval to check periodically
|
|
1375
|
+
const interval = setInterval(checkPeers, 1000);
|
|
1376
|
+
// Set timeout
|
|
1377
|
+
setTimeout(() => {
|
|
1378
|
+
clearInterval(interval);
|
|
1379
|
+
resolve(false);
|
|
1380
|
+
}, timeoutMs);
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1358
1383
|
async triggerSync() {
|
|
1359
1384
|
const latest = await this.#getLatestBlock();
|
|
1360
1385
|
return this.syncChain(latest);
|
|
@@ -1414,6 +1439,112 @@ class VersionControl extends State {
|
|
|
1414
1439
|
}
|
|
1415
1440
|
}
|
|
1416
1441
|
|
|
1442
|
+
/**
|
|
1443
|
+
* Connection Monitor - Monitors peer connections and handles reconnection logic
|
|
1444
|
+
*/
|
|
1445
|
+
class ConnectionMonitor {
|
|
1446
|
+
#isMonitoring = false;
|
|
1447
|
+
#checkInterval = null;
|
|
1448
|
+
#reconnectAttempts = 0;
|
|
1449
|
+
#maxReconnectAttempts = 10;
|
|
1450
|
+
#reconnectDelay = 5000;
|
|
1451
|
+
#healthCheckInterval = 10000;
|
|
1452
|
+
get isMonitoring() {
|
|
1453
|
+
return this.#isMonitoring;
|
|
1454
|
+
}
|
|
1455
|
+
get connectedPeers() {
|
|
1456
|
+
return Object.values(globalThis.peernet?.connections || {}).filter((peer) => peer.connected);
|
|
1457
|
+
}
|
|
1458
|
+
get compatiblePeers() {
|
|
1459
|
+
return this.connectedPeers.filter((peer) => peer.version === this.version);
|
|
1460
|
+
}
|
|
1461
|
+
constructor(version) {
|
|
1462
|
+
this.version = version;
|
|
1463
|
+
}
|
|
1464
|
+
start() {
|
|
1465
|
+
if (this.#isMonitoring)
|
|
1466
|
+
return;
|
|
1467
|
+
this.#isMonitoring = true;
|
|
1468
|
+
console.log('🔄 Starting connection monitor...');
|
|
1469
|
+
this.#checkInterval = setInterval(() => {
|
|
1470
|
+
this.#healthCheck();
|
|
1471
|
+
}, this.#healthCheckInterval);
|
|
1472
|
+
// Initial health check
|
|
1473
|
+
this.#healthCheck();
|
|
1474
|
+
}
|
|
1475
|
+
stop() {
|
|
1476
|
+
if (!this.#isMonitoring)
|
|
1477
|
+
return;
|
|
1478
|
+
this.#isMonitoring = false;
|
|
1479
|
+
if (this.#checkInterval) {
|
|
1480
|
+
clearInterval(this.#checkInterval);
|
|
1481
|
+
this.#checkInterval = null;
|
|
1482
|
+
}
|
|
1483
|
+
console.log('⏹️ Connection monitor stopped');
|
|
1484
|
+
}
|
|
1485
|
+
async #healthCheck() {
|
|
1486
|
+
const connectedPeers = this.connectedPeers;
|
|
1487
|
+
const compatiblePeers = this.compatiblePeers;
|
|
1488
|
+
console.log(`🔍 Health check: ${connectedPeers.length} connected, ${compatiblePeers.length} compatible`);
|
|
1489
|
+
if (connectedPeers.length === 0) {
|
|
1490
|
+
console.warn('⚠️ No peer connections detected');
|
|
1491
|
+
await this.#attemptReconnection();
|
|
1492
|
+
}
|
|
1493
|
+
else if (compatiblePeers.length === 0) {
|
|
1494
|
+
console.warn('⚠️ No compatible peers found');
|
|
1495
|
+
// Could attempt to find compatible peers or trigger version negotiation
|
|
1496
|
+
}
|
|
1497
|
+
else {
|
|
1498
|
+
// Reset reconnect attempts on successful connection
|
|
1499
|
+
this.#reconnectAttempts = 0;
|
|
1500
|
+
}
|
|
1501
|
+
// Publish connection status
|
|
1502
|
+
globalThis.pubsub?.publish('connection-status', {
|
|
1503
|
+
connected: connectedPeers.length,
|
|
1504
|
+
compatible: compatiblePeers.length,
|
|
1505
|
+
healthy: compatiblePeers.length > 0
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
async #attemptReconnection() {
|
|
1509
|
+
if (this.#reconnectAttempts >= this.#maxReconnectAttempts) {
|
|
1510
|
+
console.error('❌ Max reconnection attempts reached');
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
this.#reconnectAttempts++;
|
|
1514
|
+
console.log(`🔄 Attempting reconnection ${this.#reconnectAttempts}/${this.#maxReconnectAttempts}`);
|
|
1515
|
+
try {
|
|
1516
|
+
// Try to restart the network
|
|
1517
|
+
if (globalThis.peernet?.start) {
|
|
1518
|
+
await globalThis.peernet.start();
|
|
1519
|
+
}
|
|
1520
|
+
// Wait a bit before next check
|
|
1521
|
+
await new Promise((resolve) => setTimeout(resolve, this.#reconnectDelay));
|
|
1522
|
+
}
|
|
1523
|
+
catch (error) {
|
|
1524
|
+
console.error('❌ Reconnection failed:', error.message);
|
|
1525
|
+
// Exponential backoff
|
|
1526
|
+
this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, 30000);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
async waitForPeers(timeoutMs = 30000) {
|
|
1530
|
+
return new Promise((resolve) => {
|
|
1531
|
+
const startTime = Date.now();
|
|
1532
|
+
const checkPeers = () => {
|
|
1533
|
+
if (this.compatiblePeers.length > 0) {
|
|
1534
|
+
resolve(true);
|
|
1535
|
+
return;
|
|
1536
|
+
}
|
|
1537
|
+
if (Date.now() - startTime >= timeoutMs) {
|
|
1538
|
+
resolve(false);
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
setTimeout(checkPeers, 1000);
|
|
1542
|
+
};
|
|
1543
|
+
checkPeers();
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1417
1548
|
const debug = globalThis.createDebugger('leofcoin/chain');
|
|
1418
1549
|
// check if browser or local
|
|
1419
1550
|
class Chain extends VersionControl {
|
|
@@ -1426,6 +1557,10 @@ class Chain extends VersionControl {
|
|
|
1426
1557
|
#participants;
|
|
1427
1558
|
#participating;
|
|
1428
1559
|
#jail;
|
|
1560
|
+
#peerConnectionRetries;
|
|
1561
|
+
#maxPeerRetries;
|
|
1562
|
+
#peerRetryDelay;
|
|
1563
|
+
#connectionMonitor;
|
|
1429
1564
|
constructor(config) {
|
|
1430
1565
|
super(config);
|
|
1431
1566
|
this.#slotTime = 10000;
|
|
@@ -1437,6 +1572,9 @@ class Chain extends VersionControl {
|
|
|
1437
1572
|
this.#participants = [];
|
|
1438
1573
|
this.#participating = false;
|
|
1439
1574
|
this.#jail = [];
|
|
1575
|
+
this.#peerConnectionRetries = new Map();
|
|
1576
|
+
this.#maxPeerRetries = 5;
|
|
1577
|
+
this.#peerRetryDelay = 5000;
|
|
1440
1578
|
this.#addTransaction = async (message) => {
|
|
1441
1579
|
const transaction = new TransactionMessage(message);
|
|
1442
1580
|
const hash = await transaction.hash();
|
|
@@ -1511,6 +1649,7 @@ class Chain extends VersionControl {
|
|
|
1511
1649
|
// this.node = await new Node()
|
|
1512
1650
|
this.#participants = [];
|
|
1513
1651
|
this.#participating = false;
|
|
1652
|
+
this.#connectionMonitor = new ConnectionMonitor(this.version);
|
|
1514
1653
|
const initialized = await globalThis.contractStore.has(addresses.contractFactory);
|
|
1515
1654
|
if (!initialized)
|
|
1516
1655
|
await this.#setup();
|
|
@@ -1518,8 +1657,11 @@ class Chain extends VersionControl {
|
|
|
1518
1657
|
// this.#state = new State()
|
|
1519
1658
|
// todo some functions rely on state
|
|
1520
1659
|
await super.init();
|
|
1660
|
+
// Start connection monitoring
|
|
1661
|
+
this.#connectionMonitor.start();
|
|
1521
1662
|
await globalThis.peernet.addRequestHandler('bw-request-message', () => {
|
|
1522
|
-
|
|
1663
|
+
const bw = globalThis.peernet.client?.bw || { up: 0, down: 0 };
|
|
1664
|
+
return new BWMessage(bw);
|
|
1523
1665
|
});
|
|
1524
1666
|
// await globalThis.peernet.addRequestHandler('peerId', () => {
|
|
1525
1667
|
// let node =
|
|
@@ -1600,7 +1742,7 @@ class Chain extends VersionControl {
|
|
|
1600
1742
|
}
|
|
1601
1743
|
}
|
|
1602
1744
|
if (this.wantList.length > 0) {
|
|
1603
|
-
const promises = await Promise.allSettled(this.wantList.map((hash) => peernet.get(hash)));
|
|
1745
|
+
const promises = await Promise.allSettled(this.wantList.map((hash) => peernet.get(hash, 'block')));
|
|
1604
1746
|
for (let i = 0; i < promises.length; i++) {
|
|
1605
1747
|
const result = promises[i];
|
|
1606
1748
|
if (result.status === 'fulfilled')
|
|
@@ -1927,7 +2069,7 @@ class Chain extends VersionControl {
|
|
|
1927
2069
|
* @returns
|
|
1928
2070
|
*/
|
|
1929
2071
|
internalCall(sender, contract, method, parameters) {
|
|
1930
|
-
globalThis.msg = this.#createMessage(sender, contract)
|
|
2072
|
+
// globalThis.msg = this.#createMessage(sender, contract) // Debug line removed
|
|
1931
2073
|
return this.machine.execute(contract, method, parameters);
|
|
1932
2074
|
}
|
|
1933
2075
|
/**
|
|
@@ -1938,11 +2080,11 @@ class Chain extends VersionControl {
|
|
|
1938
2080
|
* @returns
|
|
1939
2081
|
*/
|
|
1940
2082
|
call(contract, method, parameters) {
|
|
1941
|
-
globalThis.msg = this.#createMessage(peernet.selectedAccount, contract)
|
|
2083
|
+
// globalThis.msg = this.#createMessage(peernet.selectedAccount, contract) // Debug line removed
|
|
1942
2084
|
return this.machine.execute(contract, method, parameters);
|
|
1943
2085
|
}
|
|
1944
2086
|
staticCall(contract, method, parameters) {
|
|
1945
|
-
globalThis.msg = this.#createMessage(peernet.selectedAccount, contract)
|
|
2087
|
+
// globalThis.msg = this.#createMessage(peernet.selectedAccount, contract) // Debug line removed
|
|
1946
2088
|
return this.machine.get(contract, method, parameters);
|
|
1947
2089
|
}
|
|
1948
2090
|
mint(to, amount) {
|
|
@@ -1972,6 +2114,27 @@ class Chain extends VersionControl {
|
|
|
1972
2114
|
lookup(name) {
|
|
1973
2115
|
return this.call(addresses.nameService, 'lookup', [name]);
|
|
1974
2116
|
}
|
|
2117
|
+
#monitorPeerConnections() {
|
|
2118
|
+
setInterval(() => {
|
|
2119
|
+
const connectedPeers = Object.values(globalThis.peernet.connections).filter((peer) => peer.connected);
|
|
2120
|
+
debug(`Connected peers: ${connectedPeers.length}`);
|
|
2121
|
+
if (connectedPeers.length === 0) {
|
|
2122
|
+
debug('No peers connected, attempting to reconnect...');
|
|
2123
|
+
this.#attemptPeerReconnection();
|
|
2124
|
+
}
|
|
2125
|
+
}, 10000); // Check every 10 seconds
|
|
2126
|
+
}
|
|
2127
|
+
async #attemptPeerReconnection() {
|
|
2128
|
+
try {
|
|
2129
|
+
// Try to reconnect to star servers
|
|
2130
|
+
if (globalThis.peernet && globalThis.peernet.start) {
|
|
2131
|
+
await globalThis.peernet.start();
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
catch (error) {
|
|
2135
|
+
console.warn('Failed to reconnect to peers:', error.message);
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
1975
2138
|
}
|
|
1976
2139
|
|
|
1977
2140
|
export { Chain as default };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Monitor - Monitors peer connections and handles reconnection logic
|
|
3
|
+
*/
|
|
4
|
+
export default class ConnectionMonitor {
|
|
5
|
+
#private;
|
|
6
|
+
private version;
|
|
7
|
+
get isMonitoring(): boolean;
|
|
8
|
+
get connectedPeers(): import("@netpeer/swarm/peer").default[];
|
|
9
|
+
get compatiblePeers(): import("@netpeer/swarm/peer").default[];
|
|
10
|
+
constructor(version: string);
|
|
11
|
+
start(): void;
|
|
12
|
+
stop(): void;
|
|
13
|
+
waitForPeers(timeoutMs?: number): Promise<boolean>;
|
|
14
|
+
}
|
|
@@ -7,7 +7,8 @@ export default class SyncController {
|
|
|
7
7
|
get fullyLoaded(): boolean;
|
|
8
8
|
constructor();
|
|
9
9
|
/**
|
|
10
|
-
* Resolves/rejects a promise or rejects on timeout
|
|
10
|
+
* Resolves/rejects a promise or rejects on timeout with retry logic
|
|
11
11
|
*/
|
|
12
|
-
resolve():
|
|
12
|
+
resolve(operation: () => Promise<any>, timeoutMs?: number): Promise<any>;
|
|
13
|
+
stop(): void;
|
|
13
14
|
}
|