@pioneer-platform/markets 8.11.13 → 8.11.23

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,14 @@
1
1
  # @pioneer-platform/markets
2
2
 
3
+ ## 8.11.23
4
+
5
+ ### Patch Changes
6
+
7
+ - cache work
8
+ - Updated dependencies
9
+ - @pioneer-platform/pro-token@0.8.1
10
+ - @pioneer-platform/pioneer-discovery@8.11.23
11
+
3
12
  ## 8.11.13
4
13
 
5
14
  ### Patch Changes
package/lib/index.js CHANGED
@@ -57,6 +57,7 @@ var TAG = " | market-module | ";
57
57
  // @ts-ignore
58
58
  var pioneer_discovery_1 = require("@pioneer-platform/pioneer-discovery");
59
59
  var caip_1 = require("@shapeshiftoss/caip");
60
+ var Bottleneck = require('bottleneck');
60
61
  var axiosLib = require('axios');
61
62
  var Axios = axiosLib.default || axiosLib;
62
63
  var https = require('https');
@@ -68,15 +69,22 @@ var axios = Axios.create({
68
69
  });
69
70
  var axiosRetry = require('axios-retry');
70
71
  axiosRetry(axios, {
71
- retries: 5, // number of retries
72
+ retries: 3, // Reduced from 5 to 3
72
73
  retryDelay: function (retryCount) {
73
74
  console.log("retry attempt: ".concat(retryCount));
74
- return retryCount * 1000; // time interval between retries
75
+ return retryCount * 2000; // Increased from 1s to 2s backoff
75
76
  },
76
77
  retryCondition: function (error) {
77
- console.error(error);
78
- // if retry condition is not specified, by default idempotent requests are retried
79
- return error.response.status === 503;
78
+ var _a;
79
+ var status = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status;
80
+ // CRITICAL FIX: Never retry rate limits (429) - respect the API!
81
+ // Also never retry 4xx client errors (except 503 service unavailable)
82
+ if (status === 429 || status === 403) {
83
+ console.warn("Rate limit or forbidden (".concat(status, "), not retrying"));
84
+ return false;
85
+ }
86
+ // Only retry on actual service unavailability
87
+ return status === 503 || status === 502 || status === 504;
80
88
  },
81
89
  });
82
90
  var ProToken = require("@pioneer-platform/pro-token");
@@ -102,6 +110,30 @@ if (CMC_PRO_API_KEY) {
102
110
  var GLOBAL_RATES_COINCAP;
103
111
  var GLOBAL_RATES_COINGECKO;
104
112
  var GLOBAL_RATES_CMC;
113
+ // FIX: Request coalescing to prevent thundering herd
114
+ // Tracks in-flight API requests to prevent duplicate calls for same asset
115
+ var pendingPriceRequests = new Map();
116
+ var pendingPriceRequestsWithSource = new Map();
117
+ // FIX: Rate limiters for external APIs
118
+ // CoinGecko free tier: 50 calls/minute = 1.2s between calls (we use 1.5s for safety)
119
+ var coingeckoLimiter = new Bottleneck({
120
+ minTime: 1500, // 1.5 seconds between calls (40 calls/minute)
121
+ maxConcurrent: 1
122
+ });
123
+ // CoinMarketCap: Varies by plan, using conservative limits
124
+ // Basic plan: 333 calls/day ≈ 1 call every 4 minutes, but allow bursts
125
+ var coinmarketcapLimiter = new Bottleneck({
126
+ reservoir: 10, // Allow 10 calls initially
127
+ reservoirRefreshAmount: 10,
128
+ reservoirRefreshInterval: 60 * 1000, // Refresh 10 calls every minute
129
+ minTime: 2000, // 2 seconds between calls
130
+ maxConcurrent: 1
131
+ });
132
+ // CoinCap API 3.0: Similar to CoinGecko
133
+ var coincapLimiter = new Bottleneck({
134
+ minTime: 1500, // 1.5 seconds between calls
135
+ maxConcurrent: 1
136
+ });
105
137
  module.exports = {
106
138
  init: function (settings) {
107
139
  if (settings === null || settings === void 0 ? void 0 : settings.apiKey) {
@@ -113,6 +145,10 @@ module.exports = {
113
145
  getAssetPriceByCaip: function (caip, returnSource) {
114
146
  return get_asset_price_by_caip(caip, returnSource);
115
147
  },
148
+ // NEW: Batch price lookup (significantly reduces API calls)
149
+ getBatchPricesByCaip: function (caips, returnSource) {
150
+ return get_batch_prices_by_caip(caips, returnSource);
151
+ },
116
152
  // Legacy bulk fetch functions
117
153
  getAssetsCoinCap: function () {
118
154
  return get_assets_coincap();
@@ -684,10 +720,12 @@ var caip_to_identifiers = function (caip) {
684
720
  };
685
721
  /**
686
722
  * Get price from CoinGecko by coin ID
723
+ * Now with rate limiting to prevent API spam
687
724
  */
688
725
  var get_price_from_coingecko = function (coingeckoId) {
689
726
  return __awaiter(this, void 0, void 0, function () {
690
- var tag, url, response, price, error_1, status_3;
727
+ var tag, error_1, status_3;
728
+ var _this = this;
691
729
  var _a;
692
730
  return __generator(this, function (_b) {
693
731
  switch (_b.label) {
@@ -696,18 +734,29 @@ var get_price_from_coingecko = function (coingeckoId) {
696
734
  _b.label = 1;
697
735
  case 1:
698
736
  _b.trys.push([1, 3, , 4]);
699
- url = "".concat(URL_COINGECKO, "simple/price?ids=").concat(coingeckoId, "&vs_currencies=usd");
700
- log.debug(tag, "Fetching from CoinGecko: ".concat(url));
701
- return [4 /*yield*/, axios.get(url)];
702
- case 2:
703
- response = _b.sent();
704
- if (response.data && response.data[coingeckoId] && response.data[coingeckoId].usd) {
705
- price = parseFloat(response.data[coingeckoId].usd);
706
- log.debug(tag, "\u2705 CoinGecko price for ".concat(coingeckoId, ": $").concat(price));
707
- return [2 /*return*/, price];
708
- }
709
- log.debug(tag, "No price data from CoinGecko for ".concat(coingeckoId));
710
- return [2 /*return*/, 0];
737
+ return [4 /*yield*/, coingeckoLimiter.schedule(function () { return __awaiter(_this, void 0, void 0, function () {
738
+ var url, response, price;
739
+ return __generator(this, function (_a) {
740
+ switch (_a.label) {
741
+ case 0:
742
+ url = "".concat(URL_COINGECKO, "simple/price?ids=").concat(coingeckoId, "&vs_currencies=usd");
743
+ log.debug(tag, "Fetching from CoinGecko: ".concat(url));
744
+ return [4 /*yield*/, axios.get(url)];
745
+ case 1:
746
+ response = _a.sent();
747
+ if (response.data && response.data[coingeckoId] && response.data[coingeckoId].usd) {
748
+ price = parseFloat(response.data[coingeckoId].usd);
749
+ log.debug(tag, "\u2705 CoinGecko price for ".concat(coingeckoId, ": $").concat(price));
750
+ return [2 /*return*/, price];
751
+ }
752
+ log.debug(tag, "No price data from CoinGecko for ".concat(coingeckoId));
753
+ return [2 /*return*/, 0];
754
+ }
755
+ });
756
+ }); })];
757
+ case 2:
758
+ // Apply rate limiting
759
+ return [2 /*return*/, _b.sent()];
711
760
  case 3:
712
761
  error_1 = _b.sent();
713
762
  status_3 = ((_a = error_1.response) === null || _a === void 0 ? void 0 : _a.status) || error_1.status;
@@ -725,49 +774,63 @@ var get_price_from_coingecko = function (coingeckoId) {
725
774
  };
726
775
  /**
727
776
  * Get price from CoinMarketCap by symbol
777
+ * Now with rate limiting to prevent API spam
728
778
  */
729
779
  var get_price_from_coinmarketcap = function (symbol) {
730
780
  return __awaiter(this, void 0, void 0, function () {
731
- var tag, url, response, coinData, priceData, price, error_2, status_4;
732
- var _a, _b, _c;
733
- return __generator(this, function (_d) {
734
- switch (_d.label) {
781
+ var tag, error_2, status_4;
782
+ var _this = this;
783
+ var _a;
784
+ return __generator(this, function (_b) {
785
+ switch (_b.label) {
735
786
  case 0:
736
787
  tag = TAG + ' | get_price_from_coinmarketcap | ';
737
788
  if (!CMC_PRO_API_KEY) {
738
789
  log.debug(tag, 'CMC_PRO_API_KEY not set, skipping CoinMarketCap');
739
790
  return [2 /*return*/, 0];
740
791
  }
741
- _d.label = 1;
792
+ _b.label = 1;
742
793
  case 1:
743
- _d.trys.push([1, 3, , 4]);
744
- url = "".concat(URL_COINMARKETCAP, "cryptocurrency/quotes/latest?symbol=").concat(symbol, "&convert=USD");
745
- log.debug(tag, "Fetching from CoinMarketCap: ".concat(url));
746
- return [4 /*yield*/, axios.get(url, {
747
- headers: {
748
- 'X-CMC_PRO_API_KEY': CMC_PRO_API_KEY,
749
- 'Accept': 'application/json'
750
- }
751
- })];
752
- case 2:
753
- response = _d.sent();
754
- if (response.data && response.data.data && response.data.data[symbol]) {
755
- coinData = response.data.data[symbol];
756
- priceData = (_b = (_a = coinData.quote) === null || _a === void 0 ? void 0 : _a.USD) === null || _b === void 0 ? void 0 : _b.price;
757
- if (!priceData || isNaN(parseFloat(priceData))) {
758
- log.warn(tag, "\u26A0\uFE0F CoinMarketCap returned invalid price for ".concat(symbol));
759
- log.warn(tag, "Symbol: ".concat(coinData.symbol, ", Slug: ").concat(coinData.slug, ", Quote keys:"), Object.keys(coinData.quote || {}));
760
- return [2 /*return*/, 0];
761
- }
762
- price = parseFloat(priceData);
763
- log.debug(tag, "\u2705 CoinMarketCap price for ".concat(symbol, ": $").concat(price));
764
- return [2 /*return*/, price];
765
- }
766
- log.debug(tag, "No price data from CoinMarketCap for ".concat(symbol));
767
- return [2 /*return*/, 0];
794
+ _b.trys.push([1, 3, , 4]);
795
+ return [4 /*yield*/, coinmarketcapLimiter.schedule(function () { return __awaiter(_this, void 0, void 0, function () {
796
+ var url, response, coinData, priceData, price;
797
+ var _a, _b;
798
+ return __generator(this, function (_c) {
799
+ switch (_c.label) {
800
+ case 0:
801
+ url = "".concat(URL_COINMARKETCAP, "cryptocurrency/quotes/latest?symbol=").concat(symbol, "&convert=USD");
802
+ log.debug(tag, "Fetching from CoinMarketCap: ".concat(url));
803
+ return [4 /*yield*/, axios.get(url, {
804
+ headers: {
805
+ 'X-CMC_PRO_API_KEY': CMC_PRO_API_KEY,
806
+ 'Accept': 'application/json'
807
+ }
808
+ })];
809
+ case 1:
810
+ response = _c.sent();
811
+ if (response.data && response.data.data && response.data.data[symbol]) {
812
+ coinData = response.data.data[symbol];
813
+ priceData = (_b = (_a = coinData.quote) === null || _a === void 0 ? void 0 : _a.USD) === null || _b === void 0 ? void 0 : _b.price;
814
+ if (!priceData || isNaN(parseFloat(priceData))) {
815
+ log.warn(tag, "\u26A0\uFE0F CoinMarketCap returned invalid price for ".concat(symbol));
816
+ log.warn(tag, "Symbol: ".concat(coinData.symbol, ", Slug: ").concat(coinData.slug, ", Quote keys:"), Object.keys(coinData.quote || {}));
817
+ return [2 /*return*/, 0];
818
+ }
819
+ price = parseFloat(priceData);
820
+ log.debug(tag, "\u2705 CoinMarketCap price for ".concat(symbol, ": $").concat(price));
821
+ return [2 /*return*/, price];
822
+ }
823
+ log.debug(tag, "No price data from CoinMarketCap for ".concat(symbol));
824
+ return [2 /*return*/, 0];
825
+ }
826
+ });
827
+ }); })];
828
+ case 2:
829
+ // Apply rate limiting
830
+ return [2 /*return*/, _b.sent()];
768
831
  case 3:
769
- error_2 = _d.sent();
770
- status_4 = ((_c = error_2.response) === null || _c === void 0 ? void 0 : _c.status) || error_2.status;
832
+ error_2 = _b.sent();
833
+ status_4 = ((_a = error_2.response) === null || _a === void 0 ? void 0 : _a.status) || error_2.status;
771
834
  if (status_4 === 429 || status_4 === 403) {
772
835
  log.warn(tag, "CoinMarketCap rate limit (".concat(status_4, ") for ").concat(symbol));
773
836
  }
@@ -782,10 +845,12 @@ var get_price_from_coinmarketcap = function (symbol) {
782
845
  };
783
846
  /**
784
847
  * Get price from CoinCap by symbol
848
+ * Now with rate limiting to prevent API spam
785
849
  */
786
850
  var get_price_from_coincap = function (symbol) {
787
851
  return __awaiter(this, void 0, void 0, function () {
788
- var tag, url, response, price, error_3, status_5;
852
+ var tag, error_3, status_5;
853
+ var _this = this;
789
854
  var _a;
790
855
  return __generator(this, function (_b) {
791
856
  switch (_b.label) {
@@ -798,23 +863,34 @@ var get_price_from_coincap = function (symbol) {
798
863
  _b.label = 1;
799
864
  case 1:
800
865
  _b.trys.push([1, 3, , 4]);
801
- url = "".concat(URL_COINCAP, "assets/").concat(symbol);
802
- log.debug(tag, "Fetching from CoinCap: ".concat(url));
803
- return [4 /*yield*/, axios.get(url, {
804
- headers: {
805
- 'Accept': 'application/json',
806
- 'Authorization': "Bearer ".concat(COINCAP_API_KEY)
807
- }
808
- })];
809
- case 2:
810
- response = _b.sent();
811
- if (response.data && response.data.data && response.data.data.priceUsd) {
812
- price = parseFloat(response.data.data.priceUsd);
813
- log.debug(tag, "\u2705 CoinCap price for ".concat(symbol, ": $").concat(price));
814
- return [2 /*return*/, price];
815
- }
816
- log.debug(tag, "No price data from CoinCap for ".concat(symbol));
817
- return [2 /*return*/, 0];
866
+ return [4 /*yield*/, coincapLimiter.schedule(function () { return __awaiter(_this, void 0, void 0, function () {
867
+ var url, response, price;
868
+ return __generator(this, function (_a) {
869
+ switch (_a.label) {
870
+ case 0:
871
+ url = "".concat(URL_COINCAP, "assets/").concat(symbol);
872
+ log.debug(tag, "Fetching from CoinCap: ".concat(url));
873
+ return [4 /*yield*/, axios.get(url, {
874
+ headers: {
875
+ 'Accept': 'application/json',
876
+ 'Authorization': "Bearer ".concat(COINCAP_API_KEY)
877
+ }
878
+ })];
879
+ case 1:
880
+ response = _a.sent();
881
+ if (response.data && response.data.data && response.data.data.priceUsd) {
882
+ price = parseFloat(response.data.data.priceUsd);
883
+ log.debug(tag, "\u2705 CoinCap price for ".concat(symbol, ": $").concat(price));
884
+ return [2 /*return*/, price];
885
+ }
886
+ log.debug(tag, "No price data from CoinCap for ".concat(symbol));
887
+ return [2 /*return*/, 0];
888
+ }
889
+ });
890
+ }); })];
891
+ case 2:
892
+ // Apply rate limiting
893
+ return [2 /*return*/, _b.sent()];
818
894
  case 3:
819
895
  error_3 = _b.sent();
820
896
  status_5 = ((_a = error_3.response) === null || _a === void 0 ? void 0 : _a.status) || error_3.status;
@@ -881,14 +957,41 @@ var get_price_from_mayascan = function () {
881
957
  * Returns: { price: number, source: string } or backwards compatible number
882
958
  */
883
959
  var get_asset_price_by_caip = function (caip_2) {
960
+ return __awaiter(this, arguments, void 0, function (caip, returnSource) {
961
+ var tag, pendingMap, existingRequest, pricePromise;
962
+ if (returnSource === void 0) { returnSource = false; }
963
+ return __generator(this, function (_a) {
964
+ tag = TAG + ' | get_asset_price_by_caip | ';
965
+ log.debug(tag, "Looking up price for: ".concat(caip));
966
+ pendingMap = returnSource ? pendingPriceRequestsWithSource : pendingPriceRequests;
967
+ existingRequest = pendingMap.get(caip);
968
+ if (existingRequest) {
969
+ log.debug(tag, "Coalescing duplicate request for: ".concat(caip));
970
+ return [2 /*return*/, existingRequest];
971
+ }
972
+ pricePromise = get_asset_price_by_caip_internal(caip, returnSource);
973
+ // Store promise for request coalescing
974
+ pendingMap.set(caip, pricePromise);
975
+ // Cleanup after completion (success or failure)
976
+ pricePromise.finally(function () {
977
+ pendingMap.delete(caip);
978
+ });
979
+ return [2 /*return*/, pricePromise];
980
+ });
981
+ });
982
+ };
983
+ /**
984
+ * Internal implementation (separated for request coalescing)
985
+ */
986
+ var get_asset_price_by_caip_internal = function (caip_2) {
884
987
  return __awaiter(this, arguments, void 0, function (caip, returnSource) {
885
988
  var tag, mayaPrice, isCacao, identifiers, price, cacaoPrice;
886
989
  if (returnSource === void 0) { returnSource = false; }
887
990
  return __generator(this, function (_a) {
888
991
  switch (_a.label) {
889
992
  case 0:
890
- tag = TAG + ' | get_asset_price_by_caip | ';
891
- log.debug(tag, "Looking up price for: ".concat(caip));
993
+ tag = TAG + ' | get_asset_price_by_caip_internal | ';
994
+ log.debug(tag, "Fetching price for: ".concat(caip));
892
995
  if (!(caip === 'cosmos:mayachain-mainnet-v1/denom:maya' || caip.toLowerCase().includes('denom:maya'))) return [3 /*break*/, 2];
893
996
  log.debug(tag, 'MAYA token detected, using MayaScan API');
894
997
  return [4 /*yield*/, get_price_from_mayascan('maya')];
@@ -1082,3 +1185,134 @@ var get_price = function (asset) {
1082
1185
  });
1083
1186
  });
1084
1187
  };
1188
+ /**
1189
+ * NEW: Batch price lookup by CAIP
1190
+ * Fetches multiple asset prices in a single API call (up to 250 assets)
1191
+ * Reduces API calls by 95%+ for portfolio operations
1192
+ */
1193
+ var get_batch_prices_by_caip = function (caips_1) {
1194
+ return __awaiter(this, arguments, void 0, function (caips, returnSource) {
1195
+ var tag, results, caipToIdMap, specialCaips, _i, caips_2, caip, identifiers, coingeckoIds, batchSize, i, batch, idsParam, url, response, _a, batch_1, coingeckoId, mapping, price, error_5, _b, specialCaips_1, caip, price, error_6, missingCaips, _c, missingCaips_1, caip, _d, _e, error_7;
1196
+ var _f;
1197
+ if (returnSource === void 0) { returnSource = false; }
1198
+ return __generator(this, function (_g) {
1199
+ switch (_g.label) {
1200
+ case 0:
1201
+ tag = TAG + ' | get_batch_prices_by_caip | ';
1202
+ log.info(tag, "Fetching batch prices for ".concat(caips.length, " assets"));
1203
+ results = {};
1204
+ caipToIdMap = {};
1205
+ specialCaips = [];
1206
+ for (_i = 0, caips_2 = caips; _i < caips_2.length; _i++) {
1207
+ caip = caips_2[_i];
1208
+ // Handle special cases (MAYA, CACAO)
1209
+ if (caip === 'cosmos:mayachain-mainnet-v1/denom:maya' || caip.toLowerCase().includes('denom:maya')) {
1210
+ specialCaips.push(caip);
1211
+ continue;
1212
+ }
1213
+ if (caip === 'cosmos:mayachain-mainnet-v1/slip44:931') {
1214
+ specialCaips.push(caip);
1215
+ continue;
1216
+ }
1217
+ identifiers = caip_to_identifiers(caip);
1218
+ if (identifiers === null || identifiers === void 0 ? void 0 : identifiers.coingeckoId) {
1219
+ caipToIdMap[identifiers.coingeckoId] = { caip: caip, coingeckoId: identifiers.coingeckoId };
1220
+ }
1221
+ }
1222
+ coingeckoIds = Object.keys(caipToIdMap);
1223
+ if (!(coingeckoIds.length > 0)) return [3 /*break*/, 8];
1224
+ _g.label = 1;
1225
+ case 1:
1226
+ _g.trys.push([1, 7, , 8]);
1227
+ batchSize = 250;
1228
+ i = 0;
1229
+ _g.label = 2;
1230
+ case 2:
1231
+ if (!(i < coingeckoIds.length)) return [3 /*break*/, 6];
1232
+ batch = coingeckoIds.slice(i, i + batchSize);
1233
+ idsParam = batch.join(',');
1234
+ url = "".concat(URL_COINGECKO, "simple/price?ids=").concat(idsParam, "&vs_currencies=usd");
1235
+ log.debug(tag, "Fetching batch ".concat(i / batchSize + 1, ": ").concat(batch.length, " assets"));
1236
+ return [4 /*yield*/, axios.get(url)];
1237
+ case 3:
1238
+ response = _g.sent();
1239
+ // Map results back to CAIPs
1240
+ for (_a = 0, batch_1 = batch; _a < batch_1.length; _a++) {
1241
+ coingeckoId = batch_1[_a];
1242
+ mapping = caipToIdMap[coingeckoId];
1243
+ if ((_f = response.data[coingeckoId]) === null || _f === void 0 ? void 0 : _f.usd) {
1244
+ price = parseFloat(response.data[coingeckoId].usd);
1245
+ results[mapping.caip] = returnSource
1246
+ ? { price: price, source: 'coingecko' }
1247
+ : price;
1248
+ }
1249
+ }
1250
+ if (!(i + batchSize < coingeckoIds.length)) return [3 /*break*/, 5];
1251
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 1500); })];
1252
+ case 4:
1253
+ _g.sent();
1254
+ _g.label = 5;
1255
+ case 5:
1256
+ i += batchSize;
1257
+ return [3 /*break*/, 2];
1258
+ case 6:
1259
+ log.info(tag, "\u2705 Batch fetched ".concat(Object.keys(results).length, " prices from CoinGecko"));
1260
+ return [3 /*break*/, 8];
1261
+ case 7:
1262
+ error_5 = _g.sent();
1263
+ log.error(tag, "CoinGecko batch fetch failed:", error_5.message);
1264
+ return [3 /*break*/, 8];
1265
+ case 8:
1266
+ _b = 0, specialCaips_1 = specialCaips;
1267
+ _g.label = 9;
1268
+ case 9:
1269
+ if (!(_b < specialCaips_1.length)) return [3 /*break*/, 14];
1270
+ caip = specialCaips_1[_b];
1271
+ _g.label = 10;
1272
+ case 10:
1273
+ _g.trys.push([10, 12, , 13]);
1274
+ return [4 /*yield*/, get_asset_price_by_caip(caip, returnSource)];
1275
+ case 11:
1276
+ price = _g.sent();
1277
+ results[caip] = price;
1278
+ return [3 /*break*/, 13];
1279
+ case 12:
1280
+ error_6 = _g.sent();
1281
+ log.warn(tag, "Failed to fetch special case: ".concat(caip));
1282
+ return [3 /*break*/, 13];
1283
+ case 13:
1284
+ _b++;
1285
+ return [3 /*break*/, 9];
1286
+ case 14:
1287
+ missingCaips = caips.filter(function (caip) { return !results[caip]; });
1288
+ if (!(missingCaips.length > 0)) return [3 /*break*/, 20];
1289
+ log.info(tag, "Falling back to individual fetch for ".concat(missingCaips.length, " missing prices"));
1290
+ _c = 0, missingCaips_1 = missingCaips;
1291
+ _g.label = 15;
1292
+ case 15:
1293
+ if (!(_c < missingCaips_1.length)) return [3 /*break*/, 20];
1294
+ caip = missingCaips_1[_c];
1295
+ _g.label = 16;
1296
+ case 16:
1297
+ _g.trys.push([16, 18, , 19]);
1298
+ _d = results;
1299
+ _e = caip;
1300
+ return [4 /*yield*/, get_asset_price_by_caip(caip, returnSource)];
1301
+ case 17:
1302
+ _d[_e] = _g.sent();
1303
+ return [3 /*break*/, 19];
1304
+ case 18:
1305
+ error_7 = _g.sent();
1306
+ log.warn(tag, "Failed to fetch fallback price for ".concat(caip));
1307
+ results[caip] = returnSource ? { price: 0, source: 'none' } : 0;
1308
+ return [3 /*break*/, 19];
1309
+ case 19:
1310
+ _c++;
1311
+ return [3 /*break*/, 15];
1312
+ case 20:
1313
+ log.info(tag, "\u2705 Batch complete: ".concat(Object.keys(results).length, "/").concat(caips.length, " prices fetched"));
1314
+ return [2 /*return*/, results];
1315
+ }
1316
+ });
1317
+ });
1318
+ };
package/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "@pioneer-platform/markets",
3
- "version": "8.11.13",
3
+ "version": "8.11.23",
4
4
  "main": "./lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "dependencies": {
7
- "@pioneer-platform/default-redis": "^8.11.0",
7
+ "@pioneer-platform/default-redis": "^8.11.7",
8
8
  "@pioneer-platform/loggerdog": "^8.11.0",
9
9
  "@pioneer-platform/pioneer-coins": "^9.11.0",
10
- "@pioneer-platform/pioneer-discovery": "^8.11.11",
10
+ "@pioneer-platform/pioneer-discovery": "^8.11.23",
11
11
  "@pioneer-platform/pioneer-types": "^8.11.0",
12
- "@pioneer-platform/pro-token": "^0.8.0",
12
+ "@pioneer-platform/pro-token": "^0.8.1",
13
13
  "@shapeshiftoss/caip": "^9.0.0-alpha.0",
14
14
  "axios": "^1.6.0",
15
15
  "axios-retry": "^3.2.0",
16
+ "bottleneck": "^2.19.5",
16
17
  "dotenv": "^8.2.0"
17
18
  },
18
19
  "scripts": {