@bsv/wallet-toolbox 1.6.15 → 1.6.17

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/docs/client.md CHANGED
@@ -9386,6 +9386,7 @@ export class Chaintracks implements ChaintracksManagementApi {
9386
9386
  let added = HeightRange.empty;
9387
9387
  let done = false;
9388
9388
  for (; !done;) {
9389
+ let bulkSyncError: WalletError | undefined;
9389
9390
  for (const bulk of this.bulkIngestors) {
9390
9391
  try {
9391
9392
  const r = await bulk.synchronize(presentHeight, before, newLiveHeaders);
@@ -9399,21 +9400,28 @@ export class Chaintracks implements ChaintracksManagementApi {
9399
9400
  break;
9400
9401
  }
9401
9402
  }
9402
- catch (uerr: unknown) {
9403
- console.error(uerr);
9403
+ catch (eu: unknown) {
9404
+ const e = (bulkSyncError = WalletError.fromUnknown(eu));
9405
+ this.log(`bulk sync error: ${e.message}`);
9404
9406
  }
9405
9407
  }
9408
+ if (!bulkDone && !this.available && bulkSyncError) {
9409
+ this.startupError = bulkSyncError;
9410
+ break;
9411
+ }
9406
9412
  if (bulkDone)
9407
9413
  break;
9408
9414
  }
9409
- this.liveHeaders.unshift(...newLiveHeaders);
9410
- added = after.bulk.above(initialRanges.bulk);
9411
- this.log(`syncBulkStorage done
9415
+ if (!this.startupError) {
9416
+ this.liveHeaders.unshift(...newLiveHeaders);
9417
+ added = after.bulk.above(initialRanges.bulk);
9418
+ this.log(`syncBulkStorage done
9412
9419
  Before sync: bulk ${initialRanges.bulk}, live ${initialRanges.live}
9413
9420
  After sync: bulk ${after.bulk}, live ${after.live}
9414
9421
  ${added.length} headers added to bulk storage
9415
9422
  ${this.liveHeaders.length} headers forwarded to live header storage
9416
9423
  `);
9424
+ }
9417
9425
  }
9418
9426
  private async mainThreadShiftLiveHeaders(): Promise<void> {
9419
9427
  this.stopMainThread = false;
@@ -9422,130 +9430,144 @@ export class Chaintracks implements ChaintracksManagementApi {
9422
9430
  const cdnSyncRepeatMsecs = 24 * 60 * 60 * 1000;
9423
9431
  const syncCheckRepeatMsecs = 30 * 60 * 1000;
9424
9432
  while (!this.stopMainThread) {
9425
- const now = Date.now();
9426
- lastSyncCheck = now;
9427
- const presentHeight = await this.getPresentHeight();
9428
- const before = await this.storage.getAvailableHeightRanges();
9429
- let skipBulkSync = !before.live.isEmpty && before.live.maxHeight >= presentHeight - this.addLiveRecursionLimit / 2;
9430
- if (skipBulkSync && now - lastSyncCheck > cdnSyncRepeatMsecs) {
9431
- skipBulkSync = false;
9432
- }
9433
- this.log(`Chaintracks Update Services: Bulk Header Sync Review
9433
+ try {
9434
+ const now = Date.now();
9435
+ lastSyncCheck = now;
9436
+ const presentHeight = await this.getPresentHeight();
9437
+ const before = await this.storage.getAvailableHeightRanges();
9438
+ let skipBulkSync = !before.live.isEmpty && before.live.maxHeight >= presentHeight - this.addLiveRecursionLimit / 2;
9439
+ if (skipBulkSync && now - lastSyncCheck > cdnSyncRepeatMsecs) {
9440
+ skipBulkSync = false;
9441
+ }
9442
+ this.log(`Chaintracks Update Services: Bulk Header Sync Review
9434
9443
  presentHeight=${presentHeight} addLiveRecursionLimit=${this.addLiveRecursionLimit}
9435
9444
  Before synchronize: bulk ${before.bulk}, live ${before.live}
9436
9445
  ${skipBulkSync ? "Skipping" : "Starting"} syncBulkStorage.
9437
9446
  `);
9438
- if (!skipBulkSync) {
9439
- lastBulkSync = now;
9440
- if (this.available)
9441
- await this.syncBulkStorage(presentHeight, before);
9442
- else
9443
- await this.syncBulkStorageNoLock(presentHeight, before);
9444
- }
9445
- let count = 0;
9446
- let liveHeaderDupes = 0;
9447
- let needSyncCheck = false;
9448
- for (; !needSyncCheck && !this.stopMainThread;) {
9449
- let header = this.liveHeaders.shift();
9450
- if (header) {
9451
- let recursions = this.addLiveRecursionLimit;
9452
- for (; !needSyncCheck && !this.stopMainThread;) {
9453
- const ihr = await this.addLiveHeader(header);
9454
- if (this.invalidInsertHeaderResult(ihr)) {
9455
- this.log(`Ignoring liveHeader ${header.height} ${header.hash} due to invalid insert result.`);
9456
- needSyncCheck = true;
9457
- }
9458
- else if (ihr.noPrev) {
9459
- if (recursions-- <= 0) {
9460
- this.log(`Ignoring liveHeader ${header.height} ${header.hash} addLiveRecursionLimit=${this.addLiveRecursionLimit} exceeded.`);
9447
+ if (!skipBulkSync) {
9448
+ lastBulkSync = now;
9449
+ if (this.available)
9450
+ await this.syncBulkStorage(presentHeight, before);
9451
+ else
9452
+ await this.syncBulkStorageNoLock(presentHeight, before);
9453
+ if (this.startupError)
9454
+ throw this.startupError;
9455
+ }
9456
+ let count = 0;
9457
+ let liveHeaderDupes = 0;
9458
+ let needSyncCheck = false;
9459
+ for (; !needSyncCheck && !this.stopMainThread;) {
9460
+ let header = this.liveHeaders.shift();
9461
+ if (header) {
9462
+ let recursions = this.addLiveRecursionLimit;
9463
+ for (; !needSyncCheck && !this.stopMainThread;) {
9464
+ const ihr = await this.addLiveHeader(header);
9465
+ if (this.invalidInsertHeaderResult(ihr)) {
9466
+ this.log(`Ignoring liveHeader ${header.height} ${header.hash} due to invalid insert result.`);
9461
9467
  needSyncCheck = true;
9462
9468
  }
9463
- else {
9464
- const hash = header.previousHash;
9465
- const prevHeader = await this.getMissingBlockHeader(hash);
9466
- if (!prevHeader) {
9467
- this.log(`Ignoring liveHeader ${header.height} ${header.hash} failed to find previous header by hash ${asString(hash)}`);
9469
+ else if (ihr.noPrev) {
9470
+ if (recursions-- <= 0) {
9471
+ this.log(`Ignoring liveHeader ${header.height} ${header.hash} addLiveRecursionLimit=${this.addLiveRecursionLimit} exceeded.`);
9468
9472
  needSyncCheck = true;
9469
9473
  }
9470
9474
  else {
9471
- this.liveHeaders.unshift(header);
9472
- header = prevHeader;
9475
+ const hash = header.previousHash;
9476
+ const prevHeader = await this.getMissingBlockHeader(hash);
9477
+ if (!prevHeader) {
9478
+ this.log(`Ignoring liveHeader ${header.height} ${header.hash} failed to find previous header by hash ${asString(hash)}`);
9479
+ needSyncCheck = true;
9480
+ }
9481
+ else {
9482
+ this.liveHeaders.unshift(header);
9483
+ header = prevHeader;
9484
+ }
9473
9485
  }
9474
9486
  }
9475
- }
9476
- else {
9477
- if (this.subscriberCallbacksEnabled)
9478
- this.log(`addLiveHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
9479
- if (ihr.dupe) {
9480
- liveHeaderDupes++;
9481
- }
9482
- if (ihr.added) {
9483
- count++;
9484
- }
9485
- break;
9486
- }
9487
- }
9488
- }
9489
- else {
9490
- const bheader = this.baseHeaders.shift();
9491
- if (bheader) {
9492
- const prev = await this.storage.findLiveHeaderForBlockHash(bheader.previousHash);
9493
- if (!prev) {
9494
- this.log(`Ignoring header with unknown previousHash ${bheader.previousHash} in live storage.`);
9495
- }
9496
- else {
9497
- const header: BlockHeader = {
9498
- ...bheader,
9499
- height: prev.height + 1,
9500
- hash: blockHash(bheader)
9501
- };
9502
- const ihr = await this.addLiveHeader(header);
9503
- if (this.invalidInsertHeaderResult(ihr)) {
9504
- this.log(`Ignoring invalid baseHeader ${header.height} ${header.hash}.`);
9505
- }
9506
9487
  else {
9507
9488
  if (this.subscriberCallbacksEnabled)
9508
- this.log(`addBaseHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
9489
+ this.log(`addLiveHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
9490
+ if (ihr.dupe) {
9491
+ liveHeaderDupes++;
9492
+ }
9509
9493
  if (ihr.added) {
9510
9494
  count++;
9511
9495
  }
9496
+ break;
9512
9497
  }
9513
9498
  }
9514
9499
  }
9515
9500
  else {
9516
- if (count > 0) {
9517
- if (liveHeaderDupes > 0) {
9518
- this.log(`${liveHeaderDupes} duplicate headers ignored.`);
9519
- liveHeaderDupes = 0;
9501
+ const bheader = this.baseHeaders.shift();
9502
+ if (bheader) {
9503
+ const prev = await this.storage.findLiveHeaderForBlockHash(bheader.previousHash);
9504
+ if (!prev) {
9505
+ this.log(`Ignoring header with unknown previousHash ${bheader.previousHash} in live storage.`);
9520
9506
  }
9521
- const updated = await this.storage.getAvailableHeightRanges();
9522
- this.log(`After adding ${count} live headers
9507
+ else {
9508
+ const header: BlockHeader = {
9509
+ ...bheader,
9510
+ height: prev.height + 1,
9511
+ hash: blockHash(bheader)
9512
+ };
9513
+ const ihr = await this.addLiveHeader(header);
9514
+ if (this.invalidInsertHeaderResult(ihr)) {
9515
+ this.log(`Ignoring invalid baseHeader ${header.height} ${header.hash}.`);
9516
+ }
9517
+ else {
9518
+ if (this.subscriberCallbacksEnabled)
9519
+ this.log(`addBaseHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
9520
+ if (ihr.added) {
9521
+ count++;
9522
+ }
9523
+ }
9524
+ }
9525
+ }
9526
+ else {
9527
+ if (count > 0) {
9528
+ if (liveHeaderDupes > 0) {
9529
+ this.log(`${liveHeaderDupes} duplicate headers ignored.`);
9530
+ liveHeaderDupes = 0;
9531
+ }
9532
+ const updated = await this.storage.getAvailableHeightRanges();
9533
+ this.log(`After adding ${count} live headers
9523
9534
  After live: bulk ${updated.bulk}, live ${updated.live}
9524
9535
  `);
9525
- count = 0;
9526
- }
9527
- if (!this.subscriberCallbacksEnabled) {
9528
- const live = await this.storage.findLiveHeightRange();
9529
- if (!live.isEmpty) {
9530
- this.subscriberCallbacksEnabled = true;
9531
- this.log(`listening at height of ${live.maxHeight}`);
9536
+ count = 0;
9532
9537
  }
9538
+ if (!this.subscriberCallbacksEnabled) {
9539
+ const live = await this.storage.findLiveHeightRange();
9540
+ if (!live.isEmpty) {
9541
+ this.subscriberCallbacksEnabled = true;
9542
+ this.log(`listening at height of ${live.maxHeight}`);
9543
+ }
9544
+ }
9545
+ if (!this.available) {
9546
+ this.available = true;
9547
+ }
9548
+ needSyncCheck = Date.now() - lastSyncCheck > syncCheckRepeatMsecs;
9549
+ if (!needSyncCheck)
9550
+ await wait(1000);
9533
9551
  }
9534
- if (!this.available) {
9535
- this.available = true;
9536
- }
9537
- needSyncCheck = Date.now() - lastSyncCheck > syncCheckRepeatMsecs;
9538
- if (!needSyncCheck)
9539
- await wait(1000);
9540
9552
  }
9541
9553
  }
9542
9554
  }
9555
+ catch (eu: unknown) {
9556
+ const e = WalletError.fromUnknown(eu);
9557
+ if (!this.available) {
9558
+ this.startupError = e;
9559
+ this.stopMainThread = true;
9560
+ }
9561
+ else {
9562
+ this.log(`Error occurred during chaintracks main thread processing: ${e.stack || e.message}`);
9563
+ }
9564
+ }
9543
9565
  }
9544
9566
  }
9545
9567
  }
9546
9568
  ```
9547
9569
 
9548
- See also: [BaseBlockHeader](./client.md#interface-baseblockheader), [BlockHeader](./client.md#interface-blockheader), [Chain](./client.md#type-chain), [ChaintracksFsApi](./services.md#interface-chaintracksfsapi), [ChaintracksInfoApi](./services.md#interface-chaintracksinfoapi), [ChaintracksManagementApi](./services.md#interface-chaintracksmanagementapi), [ChaintracksOptions](./services.md#interface-chaintracksoptions), [HeaderListener](./services.md#type-headerlistener), [HeightRange](./services.md#class-heightrange), [HeightRanges](./services.md#interface-heightranges), [LiveBlockHeader](./services.md#interface-liveblockheader), [ReorgListener](./services.md#type-reorglistener), [Services](./services.md#class-services), [asString](./client.md#function-asstring), [blockHash](./services.md#function-blockhash), [wait](./client.md#function-wait)
9570
+ See also: [BaseBlockHeader](./client.md#interface-baseblockheader), [BlockHeader](./client.md#interface-blockheader), [Chain](./client.md#type-chain), [ChaintracksFsApi](./services.md#interface-chaintracksfsapi), [ChaintracksInfoApi](./services.md#interface-chaintracksinfoapi), [ChaintracksManagementApi](./services.md#interface-chaintracksmanagementapi), [ChaintracksOptions](./services.md#interface-chaintracksoptions), [HeaderListener](./services.md#type-headerlistener), [HeightRange](./services.md#class-heightrange), [HeightRanges](./services.md#interface-heightranges), [LiveBlockHeader](./services.md#interface-liveblockheader), [ReorgListener](./services.md#type-reorglistener), [Services](./services.md#class-services), [WalletError](./client.md#class-walleterror), [asString](./client.md#function-asstring), [blockHash](./services.md#function-blockhash), [wait](./client.md#function-wait)
9549
9571
 
9550
9572
  ###### Method addHeader
9551
9573
 
package/docs/services.md CHANGED
@@ -3463,6 +3463,7 @@ export class Chaintracks implements ChaintracksManagementApi {
3463
3463
  let added = HeightRange.empty;
3464
3464
  let done = false;
3465
3465
  for (; !done;) {
3466
+ let bulkSyncError: WalletError | undefined;
3466
3467
  for (const bulk of this.bulkIngestors) {
3467
3468
  try {
3468
3469
  const r = await bulk.synchronize(presentHeight, before, newLiveHeaders);
@@ -3476,21 +3477,28 @@ export class Chaintracks implements ChaintracksManagementApi {
3476
3477
  break;
3477
3478
  }
3478
3479
  }
3479
- catch (uerr: unknown) {
3480
- console.error(uerr);
3480
+ catch (eu: unknown) {
3481
+ const e = (bulkSyncError = WalletError.fromUnknown(eu));
3482
+ this.log(`bulk sync error: ${e.message}`);
3481
3483
  }
3482
3484
  }
3485
+ if (!bulkDone && !this.available && bulkSyncError) {
3486
+ this.startupError = bulkSyncError;
3487
+ break;
3488
+ }
3483
3489
  if (bulkDone)
3484
3490
  break;
3485
3491
  }
3486
- this.liveHeaders.unshift(...newLiveHeaders);
3487
- added = after.bulk.above(initialRanges.bulk);
3488
- this.log(`syncBulkStorage done
3492
+ if (!this.startupError) {
3493
+ this.liveHeaders.unshift(...newLiveHeaders);
3494
+ added = after.bulk.above(initialRanges.bulk);
3495
+ this.log(`syncBulkStorage done
3489
3496
  Before sync: bulk ${initialRanges.bulk}, live ${initialRanges.live}
3490
3497
  After sync: bulk ${after.bulk}, live ${after.live}
3491
3498
  ${added.length} headers added to bulk storage
3492
3499
  ${this.liveHeaders.length} headers forwarded to live header storage
3493
3500
  `);
3501
+ }
3494
3502
  }
3495
3503
  private async mainThreadShiftLiveHeaders(): Promise<void> {
3496
3504
  this.stopMainThread = false;
@@ -3499,130 +3507,144 @@ export class Chaintracks implements ChaintracksManagementApi {
3499
3507
  const cdnSyncRepeatMsecs = 24 * 60 * 60 * 1000;
3500
3508
  const syncCheckRepeatMsecs = 30 * 60 * 1000;
3501
3509
  while (!this.stopMainThread) {
3502
- const now = Date.now();
3503
- lastSyncCheck = now;
3504
- const presentHeight = await this.getPresentHeight();
3505
- const before = await this.storage.getAvailableHeightRanges();
3506
- let skipBulkSync = !before.live.isEmpty && before.live.maxHeight >= presentHeight - this.addLiveRecursionLimit / 2;
3507
- if (skipBulkSync && now - lastSyncCheck > cdnSyncRepeatMsecs) {
3508
- skipBulkSync = false;
3509
- }
3510
- this.log(`Chaintracks Update Services: Bulk Header Sync Review
3510
+ try {
3511
+ const now = Date.now();
3512
+ lastSyncCheck = now;
3513
+ const presentHeight = await this.getPresentHeight();
3514
+ const before = await this.storage.getAvailableHeightRanges();
3515
+ let skipBulkSync = !before.live.isEmpty && before.live.maxHeight >= presentHeight - this.addLiveRecursionLimit / 2;
3516
+ if (skipBulkSync && now - lastSyncCheck > cdnSyncRepeatMsecs) {
3517
+ skipBulkSync = false;
3518
+ }
3519
+ this.log(`Chaintracks Update Services: Bulk Header Sync Review
3511
3520
  presentHeight=${presentHeight} addLiveRecursionLimit=${this.addLiveRecursionLimit}
3512
3521
  Before synchronize: bulk ${before.bulk}, live ${before.live}
3513
3522
  ${skipBulkSync ? "Skipping" : "Starting"} syncBulkStorage.
3514
3523
  `);
3515
- if (!skipBulkSync) {
3516
- lastBulkSync = now;
3517
- if (this.available)
3518
- await this.syncBulkStorage(presentHeight, before);
3519
- else
3520
- await this.syncBulkStorageNoLock(presentHeight, before);
3521
- }
3522
- let count = 0;
3523
- let liveHeaderDupes = 0;
3524
- let needSyncCheck = false;
3525
- for (; !needSyncCheck && !this.stopMainThread;) {
3526
- let header = this.liveHeaders.shift();
3527
- if (header) {
3528
- let recursions = this.addLiveRecursionLimit;
3529
- for (; !needSyncCheck && !this.stopMainThread;) {
3530
- const ihr = await this.addLiveHeader(header);
3531
- if (this.invalidInsertHeaderResult(ihr)) {
3532
- this.log(`Ignoring liveHeader ${header.height} ${header.hash} due to invalid insert result.`);
3533
- needSyncCheck = true;
3534
- }
3535
- else if (ihr.noPrev) {
3536
- if (recursions-- <= 0) {
3537
- this.log(`Ignoring liveHeader ${header.height} ${header.hash} addLiveRecursionLimit=${this.addLiveRecursionLimit} exceeded.`);
3524
+ if (!skipBulkSync) {
3525
+ lastBulkSync = now;
3526
+ if (this.available)
3527
+ await this.syncBulkStorage(presentHeight, before);
3528
+ else
3529
+ await this.syncBulkStorageNoLock(presentHeight, before);
3530
+ if (this.startupError)
3531
+ throw this.startupError;
3532
+ }
3533
+ let count = 0;
3534
+ let liveHeaderDupes = 0;
3535
+ let needSyncCheck = false;
3536
+ for (; !needSyncCheck && !this.stopMainThread;) {
3537
+ let header = this.liveHeaders.shift();
3538
+ if (header) {
3539
+ let recursions = this.addLiveRecursionLimit;
3540
+ for (; !needSyncCheck && !this.stopMainThread;) {
3541
+ const ihr = await this.addLiveHeader(header);
3542
+ if (this.invalidInsertHeaderResult(ihr)) {
3543
+ this.log(`Ignoring liveHeader ${header.height} ${header.hash} due to invalid insert result.`);
3538
3544
  needSyncCheck = true;
3539
3545
  }
3540
- else {
3541
- const hash = header.previousHash;
3542
- const prevHeader = await this.getMissingBlockHeader(hash);
3543
- if (!prevHeader) {
3544
- this.log(`Ignoring liveHeader ${header.height} ${header.hash} failed to find previous header by hash ${asString(hash)}`);
3546
+ else if (ihr.noPrev) {
3547
+ if (recursions-- <= 0) {
3548
+ this.log(`Ignoring liveHeader ${header.height} ${header.hash} addLiveRecursionLimit=${this.addLiveRecursionLimit} exceeded.`);
3545
3549
  needSyncCheck = true;
3546
3550
  }
3547
3551
  else {
3548
- this.liveHeaders.unshift(header);
3549
- header = prevHeader;
3552
+ const hash = header.previousHash;
3553
+ const prevHeader = await this.getMissingBlockHeader(hash);
3554
+ if (!prevHeader) {
3555
+ this.log(`Ignoring liveHeader ${header.height} ${header.hash} failed to find previous header by hash ${asString(hash)}`);
3556
+ needSyncCheck = true;
3557
+ }
3558
+ else {
3559
+ this.liveHeaders.unshift(header);
3560
+ header = prevHeader;
3561
+ }
3550
3562
  }
3551
3563
  }
3552
- }
3553
- else {
3554
- if (this.subscriberCallbacksEnabled)
3555
- this.log(`addLiveHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
3556
- if (ihr.dupe) {
3557
- liveHeaderDupes++;
3558
- }
3559
- if (ihr.added) {
3560
- count++;
3561
- }
3562
- break;
3563
- }
3564
- }
3565
- }
3566
- else {
3567
- const bheader = this.baseHeaders.shift();
3568
- if (bheader) {
3569
- const prev = await this.storage.findLiveHeaderForBlockHash(bheader.previousHash);
3570
- if (!prev) {
3571
- this.log(`Ignoring header with unknown previousHash ${bheader.previousHash} in live storage.`);
3572
- }
3573
- else {
3574
- const header: BlockHeader = {
3575
- ...bheader,
3576
- height: prev.height + 1,
3577
- hash: blockHash(bheader)
3578
- };
3579
- const ihr = await this.addLiveHeader(header);
3580
- if (this.invalidInsertHeaderResult(ihr)) {
3581
- this.log(`Ignoring invalid baseHeader ${header.height} ${header.hash}.`);
3582
- }
3583
3564
  else {
3584
3565
  if (this.subscriberCallbacksEnabled)
3585
- this.log(`addBaseHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
3566
+ this.log(`addLiveHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
3567
+ if (ihr.dupe) {
3568
+ liveHeaderDupes++;
3569
+ }
3586
3570
  if (ihr.added) {
3587
3571
  count++;
3588
3572
  }
3573
+ break;
3589
3574
  }
3590
3575
  }
3591
3576
  }
3592
3577
  else {
3593
- if (count > 0) {
3594
- if (liveHeaderDupes > 0) {
3595
- this.log(`${liveHeaderDupes} duplicate headers ignored.`);
3596
- liveHeaderDupes = 0;
3578
+ const bheader = this.baseHeaders.shift();
3579
+ if (bheader) {
3580
+ const prev = await this.storage.findLiveHeaderForBlockHash(bheader.previousHash);
3581
+ if (!prev) {
3582
+ this.log(`Ignoring header with unknown previousHash ${bheader.previousHash} in live storage.`);
3597
3583
  }
3598
- const updated = await this.storage.getAvailableHeightRanges();
3599
- this.log(`After adding ${count} live headers
3584
+ else {
3585
+ const header: BlockHeader = {
3586
+ ...bheader,
3587
+ height: prev.height + 1,
3588
+ hash: blockHash(bheader)
3589
+ };
3590
+ const ihr = await this.addLiveHeader(header);
3591
+ if (this.invalidInsertHeaderResult(ihr)) {
3592
+ this.log(`Ignoring invalid baseHeader ${header.height} ${header.hash}.`);
3593
+ }
3594
+ else {
3595
+ if (this.subscriberCallbacksEnabled)
3596
+ this.log(`addBaseHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
3597
+ if (ihr.added) {
3598
+ count++;
3599
+ }
3600
+ }
3601
+ }
3602
+ }
3603
+ else {
3604
+ if (count > 0) {
3605
+ if (liveHeaderDupes > 0) {
3606
+ this.log(`${liveHeaderDupes} duplicate headers ignored.`);
3607
+ liveHeaderDupes = 0;
3608
+ }
3609
+ const updated = await this.storage.getAvailableHeightRanges();
3610
+ this.log(`After adding ${count} live headers
3600
3611
  After live: bulk ${updated.bulk}, live ${updated.live}
3601
3612
  `);
3602
- count = 0;
3603
- }
3604
- if (!this.subscriberCallbacksEnabled) {
3605
- const live = await this.storage.findLiveHeightRange();
3606
- if (!live.isEmpty) {
3607
- this.subscriberCallbacksEnabled = true;
3608
- this.log(`listening at height of ${live.maxHeight}`);
3613
+ count = 0;
3609
3614
  }
3615
+ if (!this.subscriberCallbacksEnabled) {
3616
+ const live = await this.storage.findLiveHeightRange();
3617
+ if (!live.isEmpty) {
3618
+ this.subscriberCallbacksEnabled = true;
3619
+ this.log(`listening at height of ${live.maxHeight}`);
3620
+ }
3621
+ }
3622
+ if (!this.available) {
3623
+ this.available = true;
3624
+ }
3625
+ needSyncCheck = Date.now() - lastSyncCheck > syncCheckRepeatMsecs;
3626
+ if (!needSyncCheck)
3627
+ await wait(1000);
3610
3628
  }
3611
- if (!this.available) {
3612
- this.available = true;
3613
- }
3614
- needSyncCheck = Date.now() - lastSyncCheck > syncCheckRepeatMsecs;
3615
- if (!needSyncCheck)
3616
- await wait(1000);
3617
3629
  }
3618
3630
  }
3619
3631
  }
3632
+ catch (eu: unknown) {
3633
+ const e = WalletError.fromUnknown(eu);
3634
+ if (!this.available) {
3635
+ this.startupError = e;
3636
+ this.stopMainThread = true;
3637
+ }
3638
+ else {
3639
+ this.log(`Error occurred during chaintracks main thread processing: ${e.stack || e.message}`);
3640
+ }
3641
+ }
3620
3642
  }
3621
3643
  }
3622
3644
  }
3623
3645
  ```
3624
3646
 
3625
- See also: [BaseBlockHeader](./client.md#interface-baseblockheader), [BlockHeader](./client.md#interface-blockheader), [Chain](./client.md#type-chain), [ChaintracksFsApi](./services.md#interface-chaintracksfsapi), [ChaintracksInfoApi](./services.md#interface-chaintracksinfoapi), [ChaintracksManagementApi](./services.md#interface-chaintracksmanagementapi), [ChaintracksOptions](./services.md#interface-chaintracksoptions), [HeaderListener](./services.md#type-headerlistener), [HeightRange](./services.md#class-heightrange), [HeightRanges](./services.md#interface-heightranges), [LiveBlockHeader](./services.md#interface-liveblockheader), [ReorgListener](./services.md#type-reorglistener), [Services](./services.md#class-services), [asString](./client.md#function-asstring), [blockHash](./services.md#function-blockhash), [wait](./client.md#function-wait)
3647
+ See also: [BaseBlockHeader](./client.md#interface-baseblockheader), [BlockHeader](./client.md#interface-blockheader), [Chain](./client.md#type-chain), [ChaintracksFsApi](./services.md#interface-chaintracksfsapi), [ChaintracksInfoApi](./services.md#interface-chaintracksinfoapi), [ChaintracksManagementApi](./services.md#interface-chaintracksmanagementapi), [ChaintracksOptions](./services.md#interface-chaintracksoptions), [HeaderListener](./services.md#type-headerlistener), [HeightRange](./services.md#class-heightrange), [HeightRanges](./services.md#interface-heightranges), [LiveBlockHeader](./services.md#interface-liveblockheader), [ReorgListener](./services.md#type-reorglistener), [Services](./services.md#class-services), [WalletError](./client.md#class-walleterror), [asString](./client.md#function-asstring), [blockHash](./services.md#function-blockhash), [wait](./client.md#function-wait)
3626
3648
 
3627
3649
  ###### Method addHeader
3628
3650