@pioneer-platform/markets 8.3.13 → 8.3.16

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.
Files changed (2) hide show
  1. package/lib/index.js +135 -31
  2. package/package.json +10 -10
package/lib/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  /*
3
3
 
4
4
  https://www.coingecko.com/api/documentations/v3
5
+ https://rest.coincap.io/api-docs.json
5
6
 
6
7
  */
7
8
  var __assign = (this && this.__assign) || function () {
@@ -59,10 +60,7 @@ var Axios = require('axios');
59
60
  var https = require('https');
60
61
  var axios = Axios.create({
61
62
  httpsAgent: new https.Agent({
62
- rejectUnauthorized: false,
63
- headers: {
64
- "Authorization": "Bearer " + process.env['COINCAP_API_KEY'],
65
- }
63
+ rejectUnauthorized: false
66
64
  })
67
65
  });
68
66
  var axiosRetry = require('axios-retry');
@@ -82,9 +80,17 @@ var ProToken = require("@pioneer-platform/pro-token");
82
80
  var log = require('@pioneer-platform/loggerdog')();
83
81
  var _a = require("@pioneer-platform/pioneer-coins"), getExplorerAddressUrl = _a.getExplorerAddressUrl, needsMemoByNetwork = _a.needsMemoByNetwork, COIN_MAP_LONG = _a.COIN_MAP_LONG;
84
82
  var _b = require('@pioneer-platform/default-redis'), subscriber = _b.subscriber, publisher = _b.publisher, redis = _b.redis, redisQueue = _b.redisQueue;
85
- var URL_COINCAP = "https://api.coincap.io/v2/";
83
+ // API Documentation URLs
84
+ // https://rest.coincap.io/api-docs.json
85
+ // API Base URLs
86
+ var URL_COINCAP = "https://rest.coincap.io/v3/";
86
87
  var URL_COINGECKO = "https://api.coingecko.com/api/v3/";
88
+ // API Keys
89
+ var COINCAP_API_KEY = process.env['COINCAP_API_KEY'];
87
90
  var COINGECKO_API_KEY = process.env['COINGECKO_API_KEY'];
91
+ if (!COINCAP_API_KEY) {
92
+ console.warn("COINCAP_API_KEY not found in environment variables. CoinCap API 3.0 requires an API key.");
93
+ }
88
94
  var GLOBAL_RATES_COINCAP;
89
95
  var GLOBAL_RATES_COINGECKO;
90
96
  module.exports = {
@@ -126,6 +132,11 @@ var update_cache = function () {
126
132
  _a.label = 1;
127
133
  case 1:
128
134
  _a.trys.push([1, 16, , 17]);
135
+ // Validate API key is available
136
+ if (!COINCAP_API_KEY) {
137
+ log.error(tag, "COINCAP_API_KEY is required for CoinCap API 3.0");
138
+ return [2 /*return*/, ["COINCAP_API_KEY_MISSING"]];
139
+ }
129
140
  entries = Object.entries(pioneer_discovery_1.assetData).map(function (_a) {
130
141
  var caip = _a[0], asset = _a[1];
131
142
  if (typeof asset === 'object' && asset !== null) {
@@ -138,11 +149,15 @@ var update_cache = function () {
138
149
  log.debug(tag, "entries: ", entries);
139
150
  log.info(tag, "entries: ", entries[0]);
140
151
  log.info(tag, "entries: ", entries.length);
141
- url = URL_COINCAP + 'assets?limit=2000';
152
+ url = "".concat(URL_COINCAP, "assets?limit=2000");
142
153
  log.debug(tag, "url: ", url);
143
154
  return [4 /*yield*/, axios({
144
155
  url: url,
145
- method: 'GET'
156
+ method: 'GET',
157
+ headers: {
158
+ 'Accept': 'application/json',
159
+ 'Authorization': "Bearer ".concat(COINCAP_API_KEY)
160
+ }
146
161
  })];
147
162
  case 2:
148
163
  result = _a.sent();
@@ -162,10 +177,12 @@ var update_cache = function () {
162
177
  if (!(j < assetsMatchSymbol.length)) return [3 /*break*/, 4];
163
178
  asset = assetsMatchSymbol[j];
164
179
  key = "coincap:" + asset.caip;
165
- return [4 /*yield*/, redis.setex(key, 3600, JSON.stringify(entry))];
180
+ // No expiration - old price is better than no price
181
+ return [4 /*yield*/, redis.set(key, JSON.stringify(entry))];
166
182
  case 2:
183
+ // No expiration - old price is better than no price
167
184
  _b.sent();
168
- log.info(tag, "saved: " + key + " result: ", result);
185
+ log.info(tag, "saved: " + key);
169
186
  populatedCaips_1.add(asset.caip);
170
187
  _b.label = 3;
171
188
  case 3:
@@ -213,8 +230,10 @@ var update_cache = function () {
213
230
  if (!(_c < matchingAssets_1.length)) return [3 /*break*/, 4];
214
231
  matchingAsset = matchingAssets_1[_c];
215
232
  key = "coingecko:".concat(matchingAsset.caip);
216
- return [4 /*yield*/, redis.setex(key, 3600, JSON.stringify(coin))];
233
+ // No expiration - old price is better than no price
234
+ return [4 /*yield*/, redis.set(key, JSON.stringify(coin))];
217
235
  case 2:
236
+ // No expiration - old price is better than no price
218
237
  _d.sent();
219
238
  log.info(tag, "Saved ".concat(coin.symbol, " under ").concat(key));
220
239
  populatedCaips_1.add(matchingAsset.caip);
@@ -476,18 +495,27 @@ var get_assets_coincap = function () {
476
495
  return __generator(this, function (_a) {
477
496
  switch (_a.label) {
478
497
  case 0:
479
- tag = TAG + ' | get_order | ';
498
+ tag = TAG + ' | get_assets_coincap | ';
480
499
  _a.label = 1;
481
500
  case 1:
482
501
  _a.trys.push([1, 3, , 4]);
483
502
  output = {};
484
- url = URL_COINCAP + 'assets?limit=2000';
503
+ // API 3.0 requires an API key
504
+ if (!COINCAP_API_KEY) {
505
+ log.error(tag, "COINCAP_API_KEY is required for CoinCap API 3.0");
506
+ return [2 /*return*/, {}];
507
+ }
508
+ url = "".concat(URL_COINCAP, "assets?limit=2000");
485
509
  log.debug(tag, "url: ", url);
486
510
  return [4 /*yield*/, axios({
487
511
  url: url,
488
- method: 'GET'
512
+ method: 'GET',
513
+ headers: {
514
+ 'Accept': 'application/json',
515
+ 'Authorization': "Bearer ".concat(COINCAP_API_KEY)
516
+ }
489
517
  })
490
- //parse into keys array off ticker
518
+ // Parse into keys array off ticker
491
519
  ];
492
520
  case 2:
493
521
  result = _a.sent();
@@ -502,7 +530,8 @@ var get_assets_coincap = function () {
502
530
  return [2 /*return*/, output];
503
531
  case 3:
504
532
  e_3 = _a.sent();
505
- //handle error gracefully
533
+ log.error(TAG, "Error fetching CoinCap assets: ", e_3);
534
+ // Handle error gracefully
506
535
  return [2 /*return*/, {}];
507
536
  case 4: return [2 /*return*/];
508
537
  }
@@ -554,30 +583,77 @@ var get_assets_coingecko = function (limit, skip) {
554
583
  };
555
584
  var get_prices_in_quote = function (assets, quote) {
556
585
  return __awaiter(this, void 0, void 0, function () {
557
- var tag, data, e_5;
586
+ var tag, result, _i, assets_1, asset, url, response, assetError_1, coincapError_1, data, e_5;
558
587
  return __generator(this, function (_a) {
559
588
  switch (_a.label) {
560
589
  case 0:
561
590
  tag = " | get_prices_in_quote | ";
562
591
  _a.label = 1;
563
592
  case 1:
564
- _a.trys.push([1, 3, , 4]);
565
- return [4 /*yield*/, axios.get("".concat(URL_COINGECKO, "/simple/price?ids=") + assets.toString() + "&vs_currencies=" + quote)];
593
+ _a.trys.push([1, 12, , 13]);
594
+ if (!(COINCAP_API_KEY && quote.toLowerCase() === 'usd')) return [3 /*break*/, 10];
595
+ _a.label = 2;
566
596
  case 2:
597
+ _a.trys.push([2, 9, , 10]);
598
+ result = {};
599
+ _i = 0, assets_1 = assets;
600
+ _a.label = 3;
601
+ case 3:
602
+ if (!(_i < assets_1.length)) return [3 /*break*/, 8];
603
+ asset = assets_1[_i];
604
+ _a.label = 4;
605
+ case 4:
606
+ _a.trys.push([4, 6, , 7]);
607
+ url = "".concat(URL_COINCAP, "assets/").concat(asset);
608
+ return [4 /*yield*/, axios({
609
+ url: url,
610
+ method: 'GET',
611
+ headers: {
612
+ 'Accept': 'application/json',
613
+ 'Authorization': "Bearer ".concat(COINCAP_API_KEY)
614
+ }
615
+ })];
616
+ case 5:
617
+ response = _a.sent();
618
+ if (response.data && response.data.data) {
619
+ result[asset] = {
620
+ usd: parseFloat(response.data.data.priceUsd)
621
+ };
622
+ }
623
+ return [3 /*break*/, 7];
624
+ case 6:
625
+ assetError_1 = _a.sent();
626
+ log.error(tag, "Error fetching price for ".concat(asset, " from CoinCap: "), assetError_1);
627
+ return [3 /*break*/, 7];
628
+ case 7:
629
+ _i++;
630
+ return [3 /*break*/, 3];
631
+ case 8:
632
+ // If we got at least one result, return it
633
+ if (Object.keys(result).length > 0) {
634
+ return [2 /*return*/, result];
635
+ }
636
+ return [3 /*break*/, 10];
637
+ case 9:
638
+ coincapError_1 = _a.sent();
639
+ log.error(tag, "CoinCap API error, falling back to CoinGecko: ", coincapError_1);
640
+ return [3 /*break*/, 10];
641
+ case 10: return [4 /*yield*/, axios.get("".concat(URL_COINGECKO, "/simple/price?ids=").concat(assets.toString(), "&vs_currencies=").concat(quote))];
642
+ case 11:
567
643
  data = (_a.sent()).data;
568
644
  return [2 /*return*/, data];
569
- case 3:
645
+ case 12:
570
646
  e_5 = _a.sent();
571
- log.error(tag, "e: ", e_5);
572
- return [3 /*break*/, 4];
573
- case 4: return [2 /*return*/];
647
+ log.error(tag, "Error fetching prices: ", e_5);
648
+ return [2 /*return*/, {}];
649
+ case 13: return [2 /*return*/];
574
650
  }
575
651
  });
576
652
  });
577
653
  };
578
654
  var get_price = function (asset) {
579
655
  return __awaiter(this, void 0, void 0, function () {
580
- var tag, data, currency, marketData, e_6;
656
+ var tag, url, result, coinInfo, coincapError_2, data, currency, marketData, e_6;
581
657
  var _a, _b, _c, _d;
582
658
  return __generator(this, function (_e) {
583
659
  switch (_e.label) {
@@ -585,11 +661,39 @@ var get_price = function (asset) {
585
661
  tag = " | get_price | ";
586
662
  _e.label = 1;
587
663
  case 1:
588
- _e.trys.push([1, 3, , 4]);
589
- return [4 /*yield*/, axios.get("".concat(URL_COINGECKO, "/coins/").concat(asset))
590
- // TODO: get correct localizations
591
- ];
664
+ _e.trys.push([1, 7, , 8]);
665
+ if (!COINCAP_API_KEY) return [3 /*break*/, 5];
666
+ _e.label = 2;
592
667
  case 2:
668
+ _e.trys.push([2, 4, , 5]);
669
+ url = "".concat(URL_COINCAP, "assets/").concat(asset);
670
+ log.debug(tag, "CoinCap URL: ", url);
671
+ return [4 /*yield*/, axios({
672
+ url: url,
673
+ method: 'GET',
674
+ headers: {
675
+ 'Accept': 'application/json',
676
+ 'Authorization': "Bearer ".concat(COINCAP_API_KEY)
677
+ }
678
+ })];
679
+ case 3:
680
+ result = _e.sent();
681
+ coinInfo = result.data.data;
682
+ return [2 /*return*/, {
683
+ price: parseFloat(coinInfo.priceUsd),
684
+ marketCap: parseFloat(coinInfo.marketCapUsd),
685
+ changePercent24Hr: parseFloat(coinInfo.changePercent24Hr),
686
+ volume: parseFloat(coinInfo.volumeUsd24Hr),
687
+ icon: "https://assets.coincap.io/assets/icons/".concat(coinInfo.symbol.toLowerCase(), "@2x.png")
688
+ }];
689
+ case 4:
690
+ coincapError_2 = _e.sent();
691
+ log.error(tag, "CoinCap API error, falling back to CoinGecko: ", coincapError_2);
692
+ return [3 /*break*/, 5];
693
+ case 5: return [4 /*yield*/, axios.get("".concat(URL_COINGECKO, "/coins/").concat(asset))
694
+ // TODO: get correct localizations
695
+ ];
696
+ case 6:
593
697
  data = (_e.sent()).data;
594
698
  currency = 'usd';
595
699
  marketData = data === null || data === void 0 ? void 0 : data.market_data;
@@ -600,11 +704,11 @@ var get_price = function (asset) {
600
704
  volume: (_c = marketData === null || marketData === void 0 ? void 0 : marketData.total_volume) === null || _c === void 0 ? void 0 : _c[currency],
601
705
  icon: (_d = data === null || data === void 0 ? void 0 : data.image) === null || _d === void 0 ? void 0 : _d.large
602
706
  }];
603
- case 3:
707
+ case 7:
604
708
  e_6 = _e.sent();
605
- log.error(tag, "e: ", e_6);
606
- return [3 /*break*/, 4];
607
- case 4: return [2 /*return*/];
709
+ log.error(tag, "Error fetching price data: ", e_6);
710
+ return [2 /*return*/, null];
711
+ case 8: return [2 /*return*/];
608
712
  }
609
713
  });
610
714
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pioneer-platform/markets",
3
- "version": "8.3.13",
3
+ "version": "8.3.16",
4
4
  "main": "./lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "dependencies": {
@@ -14,14 +14,6 @@
14
14
  "axios-retry": "^3.2.0",
15
15
  "dotenv": "^8.2.0"
16
16
  },
17
- "scripts": {
18
- "npm": "pnpm i",
19
- "test": "pnpm run build && node __tests__/test-module.js",
20
- "build": "tsc -p .",
21
- "build:watch": "pnpm run build && onchange 'src/**/*.ts' -- pnpm run build",
22
- "prepublish": "pnpm run build",
23
- "refresh": "rm -rf ./node_modules ./package-lock.json && pnpm install"
24
- },
25
17
  "devDependencies": {
26
18
  "@types/jest": "^25.2.3",
27
19
  "@types/node": "^18.16.0",
@@ -33,5 +25,13 @@
33
25
  "ts-jest": "^29.0.5",
34
26
  "typescript": "^5.0.4"
35
27
  },
36
- "gitHead": "aeae28273014ab69b42f22abec159c6693a56c40"
28
+ "gitHead": "aeae28273014ab69b42f22abec159c6693a56c40",
29
+ "scripts": {
30
+ "npm": "pnpm i",
31
+ "test": "pnpm run build && node __tests__/test-module.js",
32
+ "build": "tsc -p .",
33
+ "build:watch": "pnpm run build && onchange 'src/**/*.ts' -- pnpm run build",
34
+ "prepublish": "pnpm run build",
35
+ "refresh": "rm -rf ./node_modules ./package-lock.json && pnpm install"
36
+ }
37
37
  }