@pioneer-platform/blockbook 8.27.2 → 8.27.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @pioneer-platform/blockbook
2
2
 
3
+ ## 8.27.5
4
+
5
+ ### Patch Changes
6
+
7
+ - chore: fix: transaction event channel mismatch + add networkId to event payload
8
+ - Updated dependencies
9
+ - @pioneer-platform/nodes@8.26.2
10
+
11
+ ## 8.27.4
12
+
13
+ ### Patch Changes
14
+
15
+ - fix: transaction event channel mismatch + add networkId to event payload
16
+ - Updated dependencies
17
+ - @pioneer-platform/nodes@8.26.1
18
+
19
+ ## 8.27.3
20
+
21
+ ### Patch Changes
22
+
23
+ - chore: chore: fix(utxo): calculate change index from used addresses only, not derived addresses
24
+
3
25
  ## 8.27.2
4
26
 
5
27
  ### Patch Changes
package/lib/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  declare const TAG = " | blockbook-client | ";
2
- declare const Blockbook: any;
3
2
  declare const log: any;
4
3
  /**
5
4
  * Stringify error for single-line logging
@@ -16,6 +15,7 @@ declare const axiosLib: any;
16
15
  declare const Axios: any;
17
16
  declare const https: any;
18
17
  declare const nodes: any;
18
+ declare const utxoCrypto: any;
19
19
  declare const axios: any;
20
20
  declare let NOW_NODES_API: string | undefined;
21
21
  interface NodeConfig {
@@ -33,8 +33,27 @@ interface CoinNodes {
33
33
  [symbol: string]: NodeConfig[];
34
34
  }
35
35
  declare let BLOCKBOOK_NODES: CoinNodes;
36
- declare let BLOCKBOOK_SOCKETS: any;
37
36
  declare let BLOCKBOOK_URLS: any;
37
+ /**
38
+ * Fallback: Derive addresses locally when NowNodes returns 500 for fresh xpubs
39
+ *
40
+ * NowNodes API has a bug where fresh/unused xpubs return "Internal server error" (500)
41
+ * instead of deriving addresses. This fallback derives addresses client-side.
42
+ *
43
+ * @param coin - Coin symbol (BTC, LTC, DOGE, etc.)
44
+ * @param xpub - Extended public key (xpub/ypub/zpub/tpub/upub/vpub)
45
+ * @param gap - Number of addresses to derive (default: 20, matching BIP44 gap limit)
46
+ * @returns Balance object with derived tokens array matching NowNodes format
47
+ */
48
+ declare const deriveAddressesFromXpub: (coin: string, xpub: string, gap?: number) => Promise<{
49
+ balance: string;
50
+ unconfirmedBalance: string;
51
+ totalReceived: string;
52
+ totalSent: string;
53
+ txs: number;
54
+ usedTokens: number;
55
+ tokens: any[];
56
+ }>;
38
57
  declare let add_custom_node: (coin: string, url: string, priority?: number) => boolean;
39
58
  declare let remove_node: (coin: string, url: string) => boolean;
40
59
  declare let set_node_priority: (coin: string, url: string, priority: number) => boolean;
package/lib/index.js CHANGED
@@ -40,7 +40,6 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
40
40
  }
41
41
  };
42
42
  var TAG = " | blockbook-client | ";
43
- var Blockbook = require('blockbook-client').Blockbook;
44
43
  var log = require('@pioneer-platform/loggerdog')();
45
44
  /**
46
45
  * Stringify error for single-line logging
@@ -108,6 +107,7 @@ var axiosLib = require('axios');
108
107
  var Axios = axiosLib.default || axiosLib;
109
108
  var https = require('https');
110
109
  var nodes = require("@pioneer-platform/nodes");
110
+ var utxoCrypto = require('@pioneer-platform/utxo-crypto');
111
111
  var axios = Axios.create({
112
112
  httpsAgent: new https.Agent({
113
113
  rejectUnauthorized: false
@@ -118,9 +118,105 @@ var axios = Axios.create({
118
118
  var NOW_NODES_API = process.env['NOW_NODES_API'] || process.env['NOWNODES_API_KEY'];
119
119
  // Enhanced node management
120
120
  var BLOCKBOOK_NODES = {};
121
- var BLOCKBOOK_SOCKETS = {};
122
121
  // Legacy compatibility - will be populated from BLOCKBOOK_NODES
123
122
  var BLOCKBOOK_URLS = {};
123
+ /**
124
+ * Fallback: Derive addresses locally when NowNodes returns 500 for fresh xpubs
125
+ *
126
+ * NowNodes API has a bug where fresh/unused xpubs return "Internal server error" (500)
127
+ * instead of deriving addresses. This fallback derives addresses client-side.
128
+ *
129
+ * @param coin - Coin symbol (BTC, LTC, DOGE, etc.)
130
+ * @param xpub - Extended public key (xpub/ypub/zpub/tpub/upub/vpub)
131
+ * @param gap - Number of addresses to derive (default: 20, matching BIP44 gap limit)
132
+ * @returns Balance object with derived tokens array matching NowNodes format
133
+ */
134
+ var deriveAddressesFromXpub = function (coin_1, xpub_1) {
135
+ return __awaiter(this, arguments, void 0, function (coin, xpub, gap) {
136
+ var tag, tokens, isZpub, isYpub, isXpub, i, address, path, convertedXpub, pubkey, pubkey, error_1;
137
+ if (gap === void 0) { gap = 20; }
138
+ return __generator(this, function (_a) {
139
+ switch (_a.label) {
140
+ case 0:
141
+ tag = TAG + ' | deriveAddressesFromXpub | ';
142
+ log.info(tag, "Deriving ".concat(gap, " addresses locally for ").concat(coin, " ").concat(xpub.substring(0, 20), "..."));
143
+ tokens = [];
144
+ _a.label = 1;
145
+ case 1:
146
+ _a.trys.push([1, 14, , 15]);
147
+ isZpub = xpub.startsWith('zpub');
148
+ isYpub = xpub.startsWith('ypub');
149
+ isXpub = xpub.startsWith('xpub');
150
+ i = 0;
151
+ _a.label = 2;
152
+ case 2:
153
+ if (!(i < gap)) return [3 /*break*/, 13];
154
+ address = void 0;
155
+ path = void 0;
156
+ if (!isZpub) return [3 /*break*/, 4];
157
+ return [4 /*yield*/, utxoCrypto.generateAddressZpub(xpub, i, false, 'bech32')];
158
+ case 3:
159
+ // Native Segwit (bech32) - m/84'/0'/0'/0/i
160
+ address = _a.sent();
161
+ path = "m/84'/0'/0'/0/".concat(i);
162
+ return [3 /*break*/, 11];
163
+ case 4:
164
+ if (!isYpub) return [3 /*break*/, 8];
165
+ return [4 /*yield*/, utxoCrypto.xpubConvert(xpub, 'xpub')];
166
+ case 5:
167
+ convertedXpub = _a.sent();
168
+ return [4 /*yield*/, utxoCrypto.generatePubkey(convertedXpub, i, false, 'p2sh')];
169
+ case 6:
170
+ pubkey = _a.sent();
171
+ return [4 /*yield*/, utxoCrypto.generateAddress(coin, pubkey, 'legacy')];
172
+ case 7:
173
+ address = _a.sent();
174
+ path = "m/49'/0'/0'/0/".concat(i);
175
+ return [3 /*break*/, 11];
176
+ case 8: return [4 /*yield*/, utxoCrypto.generatePubkey(xpub, i, false, 'legacy')];
177
+ case 9:
178
+ pubkey = _a.sent();
179
+ return [4 /*yield*/, utxoCrypto.generateAddress(coin, pubkey, 'legacy')];
180
+ case 10:
181
+ address = _a.sent();
182
+ path = "m/44'/0'/0'/0/".concat(i);
183
+ _a.label = 11;
184
+ case 11:
185
+ // Match NowNodes token format: { name, path, transfers, decimals, balance }
186
+ tokens.push({
187
+ name: address,
188
+ path: path,
189
+ transfers: 0,
190
+ decimals: 8,
191
+ balance: '0',
192
+ totalReceived: '0',
193
+ totalSent: '0'
194
+ });
195
+ _a.label = 12;
196
+ case 12:
197
+ i++;
198
+ return [3 /*break*/, 2];
199
+ case 13:
200
+ log.info(tag, "\u2705 Derived ".concat(tokens.length, " addresses locally for fresh xpub"));
201
+ // Return in NowNodes format
202
+ return [2 /*return*/, {
203
+ balance: '0',
204
+ unconfirmedBalance: '0',
205
+ totalReceived: '0',
206
+ totalSent: '0',
207
+ txs: 0,
208
+ usedTokens: 0,
209
+ tokens: tokens
210
+ }];
211
+ case 14:
212
+ error_1 = _a.sent();
213
+ log.error(tag, "Failed to derive addresses locally: ".concat(stringifyError(error_1)));
214
+ throw error_1;
215
+ case 15: return [2 /*return*/];
216
+ }
217
+ });
218
+ });
219
+ };
124
220
  module.exports = {
125
221
  init: function (servers) {
126
222
  return init_network(servers);
@@ -146,9 +242,6 @@ module.exports = {
146
242
  getBlockbooks: function () {
147
243
  return BLOCKBOOK_URLS;
148
244
  },
149
- getBlockbookSockets: function () {
150
- return BLOCKBOOK_SOCKETS;
151
- },
152
245
  getFees: function (coin) {
153
246
  return get_fees(coin);
154
247
  },
@@ -294,7 +387,7 @@ var update_legacy_urls = function (symbol) {
294
387
  };
295
388
  var init_network = function (servers) {
296
389
  return __awaiter(this, void 0, void 0, function () {
297
- var tag, SEED_NODES, blockbooks, i, blockbook, symbol, priority, wsUrl, symbol, nodes_1, e_1;
390
+ var tag, SEED_NODES, blockbooks, i, blockbook, symbol, serviceUrl, priority, symbol, nodes_1, e_1;
298
391
  return __generator(this, function (_a) {
299
392
  switch (_a.label) {
300
393
  case 0:
@@ -328,52 +421,34 @@ var init_network = function (servers) {
328
421
  console.log('[DEBUG] Processing blockbook', i + 1, '/', blockbooks.length, ':', blockbook.symbol);
329
422
  if (blockbook && blockbook.service) {
330
423
  symbol = blockbook.symbol.toUpperCase();
424
+ serviceUrl = blockbook.service;
425
+ // CRITICAL FIX: Replace {API_KEY} placeholder with actual API key for NowNodes
426
+ if (serviceUrl.includes('nownodes.io') && serviceUrl.includes('{API_KEY}')) {
427
+ if (NOW_NODES_API) {
428
+ serviceUrl = serviceUrl.replace('{API_KEY}', NOW_NODES_API);
429
+ console.log('[DEBUG] Replaced {API_KEY} in service URL for', blockbook.symbol);
430
+ log.info(tag, "Configured NowNodes HTTP service for ".concat(blockbook.symbol, " with API key"));
431
+ }
432
+ else {
433
+ log.error(tag, "\u26A0\uFE0F CRITICAL: NowNodes service URL contains {API_KEY} but NOW_NODES_API env var is not set for ".concat(blockbook.symbol));
434
+ console.error('[ERROR] Missing NOW_NODES_API environment variable - service will fail!');
435
+ }
436
+ }
331
437
  priority = 50;
332
- if (blockbook.service.includes('nownodes.io')) {
438
+ if (serviceUrl.includes('nownodes.io')) {
333
439
  priority = 0; // Highest priority for NowNodes (fastest)
334
440
  }
335
- else if (blockbook.service.includes('zelcore.io')) {
441
+ else if (serviceUrl.includes('zelcore.io')) {
336
442
  priority = 10; // Lower priority for Zelcore (slower)
337
443
  }
338
- else if (blockbook.service.includes('shapeshift.com')) {
444
+ else if (serviceUrl.includes('shapeshift.com')) {
339
445
  priority = 20; // Even lower for ShapeShift
340
446
  }
341
- // Add node with proper priority
342
- add_custom_node(symbol, blockbook.service, priority);
343
- }
344
- if (blockbook && blockbook.websocket) {
345
- wsUrl = blockbook.websocket;
346
- console.log('[DEBUG] Found WebSocket for', blockbook.symbol, ':', wsUrl);
347
- // Ensure proper wss:// protocol
348
- if (!wsUrl.startsWith('wss://') && !wsUrl.startsWith('ws://')) {
349
- wsUrl = 'wss://' + wsUrl;
350
- }
351
- // Append NowNodes API key if needed
352
- if (wsUrl.includes('nownodes.io') && NOW_NODES_API && !wsUrl.includes(NOW_NODES_API)) {
353
- // NowNodes format: wss://btc.nownodes.io/wss/API_KEY/websocket
354
- // Remove any existing /wss/ suffix, then add /wss/API_KEY
355
- wsUrl = wsUrl.replace(/\/wss\/?$/, ''); // Remove trailing /wss or /wss/
356
- wsUrl = wsUrl + '/wss/' + NOW_NODES_API;
357
- console.log('[DEBUG] Added API key to', blockbook.symbol, 'WebSocket');
358
- log.info(tag, "Configured NowNodes websocket for ".concat(blockbook.symbol, " with API key"));
359
- }
360
- // Ensure /websocket suffix (only if not already there)
361
- if (!wsUrl.endsWith('/websocket')) {
362
- wsUrl = wsUrl + '/websocket';
363
- }
364
- console.log('[DEBUG] Final WebSocket URL for', blockbook.symbol, ':', wsUrl);
365
- log.info(tag, "WebSocket URL for ".concat(blockbook.symbol, ": ").concat(wsUrl));
366
- // Use blockbook-client package
367
- BLOCKBOOK_SOCKETS[blockbook.symbol.toUpperCase()] = new Blockbook({
368
- nodes: [wsUrl],
369
- disableTypeValidation: true,
370
- });
371
- console.log('[DEBUG] Created Blockbook socket for', blockbook.symbol);
372
- }
373
- else {
374
- console.log('[DEBUG] NO WebSocket for', blockbook.symbol);
375
- log.info(tag, "no websocket for: ", blockbook.symbol);
447
+ // Add node with proper priority (using the URL with API key replaced)
448
+ add_custom_node(symbol, serviceUrl, priority);
376
449
  }
450
+ // WebSocket connections are handled by Rust watchtower
451
+ // Pioneer-server ONLY uses Blockbook REST API
377
452
  }
378
453
  // Log final configuration
379
454
  for (symbol in BLOCKBOOK_NODES) {
@@ -384,7 +459,6 @@ var init_network = function (servers) {
384
459
  });
385
460
  }
386
461
  log.debug(tag, "BLOCKBOOK_URLS: ", BLOCKBOOK_URLS);
387
- log.debug(tag, "BLOCKBOOK_SOCKETS: ", BLOCKBOOK_SOCKETS);
388
462
  return [2 /*return*/, true];
389
463
  case 3:
390
464
  e_1 = _a.sent();
@@ -435,15 +509,15 @@ var get_fees = function (coin) {
435
509
  };
436
510
  var get_info_by_pubkey = function (coin, pubkey, page) {
437
511
  return __awaiter(this, void 0, void 0, function () {
438
- var tag, symbol, isXpub, url, body, resp, e_3, e_4;
439
- var _a;
440
- return __generator(this, function (_b) {
441
- switch (_b.label) {
512
+ var tag, symbol, isXpub, url, addressForApi, body, resp, e_3, derivedBalance, deriveError_1, e_4;
513
+ var _a, _b;
514
+ return __generator(this, function (_c) {
515
+ switch (_c.label) {
442
516
  case 0:
443
517
  tag = TAG + " | get_info_by_pubkey | ";
444
- _b.label = 1;
518
+ _c.label = 1;
445
519
  case 1:
446
- _b.trys.push([1, 6, , 7]);
520
+ _c.trys.push([1, 10, , 11]);
447
521
  if (!page)
448
522
  page = "1";
449
523
  symbol = coin.toUpperCase();
@@ -472,9 +546,13 @@ var get_info_by_pubkey = function (coin, pubkey, page) {
472
546
  log.debug(tag, "Using xpub endpoint for ".concat(pubkey.substring(0, 20), "..."));
473
547
  }
474
548
  else {
475
- // Regular address - use address endpoint with transaction details
476
- url = BLOCKBOOK_URLS[symbol] + "/api/v2/address/" + pubkey + "?details=txs&page=" + page;
477
- log.debug(tag, "Using address endpoint for ".concat(pubkey));
549
+ addressForApi = pubkey;
550
+ if (coin.toUpperCase() === 'BCH' && (pubkey.startsWith('q') || pubkey.startsWith('p'))) {
551
+ addressForApi = "bitcoincash:".concat(pubkey);
552
+ log.debug(tag, "Adding bitcoincash: prefix for BCH CashAddr: ".concat(addressForApi));
553
+ }
554
+ url = BLOCKBOOK_URLS[symbol] + "/api/v2/address/" + addressForApi + "?details=txs&page=" + page;
555
+ log.debug(tag, "Using address endpoint for ".concat(addressForApi));
478
556
  }
479
557
  log.debug(tag, "url: ", url);
480
558
  body = {
@@ -486,15 +564,15 @@ var get_info_by_pubkey = function (coin, pubkey, page) {
486
564
  },
487
565
  };
488
566
  resp = void 0;
489
- _b.label = 2;
567
+ _c.label = 2;
490
568
  case 2:
491
- _b.trys.push([2, 4, , 5]);
569
+ _c.trys.push([2, 4, , 9]);
492
570
  return [4 /*yield*/, axios(body)];
493
571
  case 3:
494
- resp = _b.sent();
495
- return [3 /*break*/, 5];
572
+ resp = _c.sent();
573
+ return [3 /*break*/, 9];
496
574
  case 4:
497
- e_3 = _b.sent();
575
+ e_3 = _c.sent();
498
576
  // Handle 404 - pubkey doesn't exist on chain yet (no transactions)
499
577
  if (((_a = e_3.response) === null || _a === void 0 ? void 0 : _a.status) === 404 || e_3.status === 404) {
500
578
  log.debug(tag, "Pubkey not found (404) for ".concat(coin, " - treating as zero balance"));
@@ -508,10 +586,26 @@ var get_info_by_pubkey = function (coin, pubkey, page) {
508
586
  tokens: []
509
587
  }];
510
588
  }
511
- // Log detailed error information for 500 and other errors
589
+ if (!((((_b = e_3.response) === null || _b === void 0 ? void 0 : _b.status) === 500 || e_3.status === 500) && isXpub)) return [3 /*break*/, 8];
590
+ log.warn(tag, "\u26A0\uFE0F NowNodes returned 500 for ".concat(coin, " xpub - falling back to local derivation"));
591
+ log.warn(tag, "This is a known NowNodes bug with fresh/unused xpubs");
592
+ _c.label = 5;
593
+ case 5:
594
+ _c.trys.push([5, 7, , 8]);
595
+ return [4 /*yield*/, deriveAddressesFromXpub(symbol, pubkey, 20)];
596
+ case 6:
597
+ derivedBalance = _c.sent();
598
+ log.info(tag, "\u2705 Successfully derived ".concat(derivedBalance.tokens.length, " addresses locally"));
599
+ return [2 /*return*/, derivedBalance];
600
+ case 7:
601
+ deriveError_1 = _c.sent();
602
+ log.error(tag, "Failed to derive addresses locally: ".concat(stringifyError(deriveError_1)));
603
+ return [3 /*break*/, 8];
604
+ case 8:
605
+ // Log detailed error information for other errors
512
606
  log.error(tag, "getPubkeyInfo failed for ".concat(coin, ": ").concat(stringifyError(e_3)));
513
607
  throw e_3;
514
- case 5:
608
+ case 9:
515
609
  log.debug(tag, "resp: ", resp);
516
610
  // Normalize response format based on endpoint type
517
611
  if (isXpub) {
@@ -535,18 +629,18 @@ var get_info_by_pubkey = function (coin, pubkey, page) {
535
629
  }
536
630
  }
537
631
  return [2 /*return*/, resp.data];
538
- case 6:
539
- e_4 = _b.sent();
632
+ case 10:
633
+ e_4 = _c.sent();
540
634
  log.error(tag, stringifyError(e_4));
541
635
  throw e_4;
542
- case 7: return [2 /*return*/];
636
+ case 11: return [2 /*return*/];
543
637
  }
544
638
  });
545
639
  });
546
640
  };
547
641
  var get_txids_by_address = function (coin, address, page) {
548
642
  return __awaiter(this, void 0, void 0, function () {
549
- var tag, url, body, resp, e_5;
643
+ var tag, addressForApi, url, body, resp, e_5;
550
644
  return __generator(this, function (_a) {
551
645
  switch (_a.label) {
552
646
  case 0:
@@ -556,7 +650,12 @@ var get_txids_by_address = function (coin, address, page) {
556
650
  _a.trys.push([1, 3, , 4]);
557
651
  if (!page)
558
652
  page = 1;
559
- url = BLOCKBOOK_URLS[coin.toUpperCase()] + "/api/v2/address/" + address + "?page=" + page + "&details=all";
653
+ addressForApi = address;
654
+ if (coin.toUpperCase() === 'BCH' && (address.startsWith('q') || address.startsWith('p'))) {
655
+ addressForApi = "bitcoincash:".concat(address);
656
+ log.debug(tag, "Adding bitcoincash: prefix for BCH CashAddr: ".concat(addressForApi));
657
+ }
658
+ url = BLOCKBOOK_URLS[coin.toUpperCase()] + "/api/v2/address/" + addressForApi + "?page=" + page + "&details=all";
560
659
  log.debug(tag, "url: ", url);
561
660
  body = {
562
661
  method: 'GET',
@@ -584,7 +683,7 @@ var get_txids_by_address = function (coin, address, page) {
584
683
  };
585
684
  var get_info_by_address = function (coin, address, filter, options) {
586
685
  return __awaiter(this, void 0, void 0, function () {
587
- var tag, url, params, body, resp, e_6;
686
+ var tag, addressForApi, url, params, body, resp, e_6;
588
687
  return __generator(this, function (_a) {
589
688
  switch (_a.label) {
590
689
  case 0:
@@ -596,7 +695,12 @@ var get_info_by_address = function (coin, address, filter, options) {
596
695
  filter = "all";
597
696
  if (!BLOCKBOOK_URLS[coin.toUpperCase()])
598
697
  throw Error("invalid coin: " + coin);
599
- url = BLOCKBOOK_URLS[coin.toUpperCase()] + "/api/v2/address/" + address;
698
+ addressForApi = address;
699
+ if (coin.toUpperCase() === 'BCH' && (address.startsWith('q') || address.startsWith('p'))) {
700
+ addressForApi = "bitcoincash:".concat(address);
701
+ log.debug(tag, "Adding bitcoincash: prefix for BCH CashAddr: ".concat(addressForApi));
702
+ }
703
+ url = BLOCKBOOK_URLS[coin.toUpperCase()] + "/api/v2/address/" + addressForApi;
600
704
  params = [];
601
705
  if (filter === 'txs' || filter === 'all') {
602
706
  params.push('details=txs');
@@ -696,7 +800,7 @@ var broadcast_transaction = function (coin, hex) {
696
800
  if (!(retry < MAX_RETRIES)) return [3 /*break*/, 9];
697
801
  log.info(tag, "Broadcast attempt ".concat(retry + 1, "/").concat(MAX_RETRIES));
698
802
  _loop_1 = function (i) {
699
- var node, startTime, url, body, resp, responseTime, txid, error_1, responseTime, errorMessage_1, statusCode, isNodeFailure, txValidationErrors, attemptInfo;
803
+ var node, startTime, url, body, resp, responseTime, txid, error_2, responseTime, errorMessage_1, statusCode, isNodeFailure, txValidationErrors, attemptInfo;
700
804
  return __generator(this, function (_d) {
701
805
  switch (_d.label) {
702
806
  case 0:
@@ -730,26 +834,26 @@ var broadcast_transaction = function (coin, hex) {
730
834
  txid: txid
731
835
  } }];
732
836
  case 3:
733
- error_1 = _d.sent();
837
+ error_2 = _d.sent();
734
838
  responseTime = Date.now() - startTime;
735
839
  errorMessage_1 = 'Unknown error occurred';
736
840
  statusCode = null;
737
841
  isNodeFailure = true;
738
- if (error_1.response) {
739
- statusCode = error_1.response.status;
842
+ if (error_2.response) {
843
+ statusCode = error_2.response.status;
740
844
  log.error(tag, "Node ".concat(i + 1, " HTTP Status: "), statusCode);
741
- log.error(tag, "Node ".concat(i + 1, " Response headers: "), error_1.response.headers);
742
- if (error_1.response.data) {
743
- log.error(tag, "Node ".concat(i + 1, " Response data: "), error_1.response.data);
744
- if (error_1.response.data.error) {
745
- errorMessage_1 = error_1.response.data.error;
845
+ log.error(tag, "Node ".concat(i + 1, " Response headers: "), error_2.response.headers);
846
+ if (error_2.response.data) {
847
+ log.error(tag, "Node ".concat(i + 1, " Response data: "), error_2.response.data);
848
+ if (error_2.response.data.error) {
849
+ errorMessage_1 = error_2.response.data.error;
746
850
  }
747
- else if (typeof error_1.response.data === 'string') {
748
- errorMessage_1 = error_1.response.data;
851
+ else if (typeof error_2.response.data === 'string') {
852
+ errorMessage_1 = error_2.response.data;
749
853
  }
750
854
  else {
751
- errorMessage_1 = "HTTP ".concat(statusCode, ": ").concat(error_1.response.statusText || 'Request failed');
752
- log.error(tag, "Node ".concat(i + 1, " Full response object: "), JSON.stringify(error_1.response.data));
855
+ errorMessage_1 = "HTTP ".concat(statusCode, ": ").concat(error_2.response.statusText || 'Request failed');
856
+ log.error(tag, "Node ".concat(i + 1, " Full response object: "), JSON.stringify(error_2.response.data));
753
857
  }
754
858
  txValidationErrors = [
755
859
  'min relay fee',
@@ -768,15 +872,15 @@ var broadcast_transaction = function (coin, hex) {
768
872
  }
769
873
  }
770
874
  else {
771
- errorMessage_1 = "HTTP ".concat(statusCode, ": ").concat(error_1.response.statusText || 'Request failed');
875
+ errorMessage_1 = "HTTP ".concat(statusCode, ": ").concat(error_2.response.statusText || 'Request failed');
772
876
  }
773
877
  }
774
- else if (error_1.request) {
878
+ else if (error_2.request) {
775
879
  errorMessage_1 = 'Network error: No response received';
776
- log.error(tag, "Node ".concat(i + 1, " Request config: "), (_b = error_1.config) === null || _b === void 0 ? void 0 : _b.url);
880
+ log.error(tag, "Node ".concat(i + 1, " Request config: "), (_b = error_2.config) === null || _b === void 0 ? void 0 : _b.url);
777
881
  }
778
882
  else {
779
- errorMessage_1 = error_1.message || 'Request setup error';
883
+ errorMessage_1 = error_2.message || 'Request setup error';
780
884
  }
781
885
  // Update node performance metrics ONLY if this was an actual node failure
782
886
  // Don't penalize nodes for transaction validation errors
@@ -865,7 +969,7 @@ var get_transaction = function (coin, txid) {
865
969
  // Enhanced UTXO function with priority-based sequential failover
866
970
  var get_utxos_by_xpub = function (coin, xpub) {
867
971
  return __awaiter(this, void 0, void 0, function () {
868
- var tag, symbol, isBitcoin, b58, data, payload, xpubPrefix, convertedData, convertedXpub, nodes_3, activeNodes, i, node, startTime, url, body, resp, responseTime, error_2, responseTime, errorMessage, e_10;
972
+ var tag, symbol, isBitcoin, b58, data, payload, xpubPrefix, convertedData, convertedXpub, nodes_3, activeNodes, i, node, startTime, url, body, resp, responseTime, error_3, responseTime, errorMessage, e_10;
869
973
  var _a;
870
974
  return __generator(this, function (_b) {
871
975
  switch (_b.label) {
@@ -964,18 +1068,18 @@ var get_utxos_by_xpub = function (coin, xpub) {
964
1068
  // Return both data and the node URL that was used
965
1069
  return [2 /*return*/, { data: resp.data, nodeUrl: node.url }];
966
1070
  case 5:
967
- error_2 = _b.sent();
1071
+ error_3 = _b.sent();
968
1072
  responseTime = Date.now() - startTime;
969
1073
  // Update node performance metrics
970
1074
  update_node_performance(symbol, node.url, false, responseTime);
971
- errorMessage = error_2 instanceof Error ? error_2.message : String(error_2);
1075
+ errorMessage = error_3 instanceof Error ? error_3.message : String(error_3);
972
1076
  log.warn(tag, "\u274C Node ".concat(i + 1, " failed after ").concat(responseTime, "ms:"), errorMessage);
973
1077
  if (isBitcoin) {
974
1078
  log.error(tag, '🔍 [BITCOIN BLOCKBOOK] Node failed with error:', {
975
1079
  nodeUrl: node.url,
976
1080
  errorMessage: errorMessage,
977
- errorType: error_2 instanceof Error ? error_2.constructor.name : typeof error_2,
978
- fullError: error_2
1081
+ errorType: error_3 instanceof Error ? error_3.constructor.name : typeof error_3,
1082
+ fullError: error_3
979
1083
  });
980
1084
  }
981
1085
  // If this is the last node, throw the error
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pioneer-platform/blockbook",
3
- "version": "8.27.2",
3
+ "version": "8.27.5",
4
4
  "main": "./lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "scripts": {
@@ -12,8 +12,9 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@pioneer-platform/loggerdog": "^8.11.0",
15
- "@pioneer-platform/nodes": "^8.26.0",
15
+ "@pioneer-platform/nodes": "^8.26.2",
16
16
  "@pioneer-platform/pioneer-caip": "^9.19.0",
17
+ "@pioneer-platform/utxo-crypto": "^8.11.0",
17
18
  "@types/request-promise-native": "^1.0.17",
18
19
  "axiom": "^0.1.6",
19
20
  "axios": "^1.6.0",