@pioneer-platform/markets 8.4.0 → 8.4.1
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 +13 -0
- package/package.json +17 -17
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -711
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @pioneer-platform/markets
|
|
2
2
|
|
|
3
|
+
## 8.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Automated patch version bump for all packages
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @pioneer-platform/pro-token@0.1.1
|
|
10
|
+
- @pioneer-platform/loggerdog@8.4.1
|
|
11
|
+
- @pioneer-platform/default-redis@8.4.1
|
|
12
|
+
- @pioneer-platform/pioneer-coins@9.4.1
|
|
13
|
+
- @pioneer-platform/pioneer-types@8.4.1
|
|
14
|
+
- @pioneer-platform/pioneer-discovery@0.1.1
|
|
15
|
+
|
|
3
16
|
## 8.4.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/package.json
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pioneer-platform/markets",
|
|
3
|
-
"version": "8.4.
|
|
3
|
+
"version": "8.4.1",
|
|
4
4
|
"main": "./lib/index.js",
|
|
5
5
|
"types": "./lib/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@pioneer-platform/default-redis": "^8.4.
|
|
8
|
-
"@pioneer-platform/loggerdog": "^8.4.
|
|
9
|
-
"@pioneer-platform/pioneer-coins": "^9.4.
|
|
10
|
-
"@pioneer-platform/pioneer-discovery": "^0.1.
|
|
11
|
-
"@pioneer-platform/pioneer-types": "^8.4.
|
|
12
|
-
"@pioneer-platform/pro-token": "^0.1.
|
|
7
|
+
"@pioneer-platform/default-redis": "^8.4.1",
|
|
8
|
+
"@pioneer-platform/loggerdog": "^8.4.1",
|
|
9
|
+
"@pioneer-platform/pioneer-coins": "^9.4.1",
|
|
10
|
+
"@pioneer-platform/pioneer-discovery": "^0.1.1",
|
|
11
|
+
"@pioneer-platform/pioneer-types": "^8.4.1",
|
|
12
|
+
"@pioneer-platform/pro-token": "^0.1.1",
|
|
13
13
|
"axios": "^1.6.0",
|
|
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
|
+
},
|
|
17
25
|
"devDependencies": {
|
|
18
26
|
"@types/jest": "^25.2.3",
|
|
19
27
|
"@types/node": "^18.16.0",
|
|
@@ -25,13 +33,5 @@
|
|
|
25
33
|
"ts-jest": "^29.0.5",
|
|
26
34
|
"typescript": "^5.0.4"
|
|
27
35
|
},
|
|
28
|
-
"gitHead": "aeae28273014ab69b42f22abec159c6693a56c40"
|
|
29
|
-
|
|
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
|
-
}
|
|
36
|
+
"gitHead": "aeae28273014ab69b42f22abec159c6693a56c40"
|
|
37
|
+
}
|
package/lib/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/lib/index.js
DELETED
|
@@ -1,711 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
|
|
4
|
-
https://www.coingecko.com/api/documentations/v3
|
|
5
|
-
https://rest.coincap.io/api-docs.json
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
var __assign = (this && this.__assign) || function () {
|
|
9
|
-
__assign = Object.assign || function(t) {
|
|
10
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
11
|
-
s = arguments[i];
|
|
12
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
}
|
|
15
|
-
return t;
|
|
16
|
-
};
|
|
17
|
-
return __assign.apply(this, arguments);
|
|
18
|
-
};
|
|
19
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
20
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
21
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
22
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
23
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
24
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
25
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
29
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
30
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
31
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
32
|
-
function step(op) {
|
|
33
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
34
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
35
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
36
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
37
|
-
switch (op[0]) {
|
|
38
|
-
case 0: case 1: t = op; break;
|
|
39
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
40
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
41
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
42
|
-
default:
|
|
43
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
44
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
45
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
46
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
47
|
-
if (t[2]) _.ops.pop();
|
|
48
|
-
_.trys.pop(); continue;
|
|
49
|
-
}
|
|
50
|
-
op = body.call(thisArg, _);
|
|
51
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
52
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
-
var TAG = " | market-module | ";
|
|
57
|
-
// @ts-ignore
|
|
58
|
-
var pioneer_discovery_1 = require("@pioneer-platform/pioneer-discovery");
|
|
59
|
-
var Axios = require('axios');
|
|
60
|
-
var https = require('https');
|
|
61
|
-
var axios = Axios.create({
|
|
62
|
-
httpsAgent: new https.Agent({
|
|
63
|
-
rejectUnauthorized: false
|
|
64
|
-
})
|
|
65
|
-
});
|
|
66
|
-
var axiosRetry = require('axios-retry');
|
|
67
|
-
axiosRetry(axios, {
|
|
68
|
-
retries: 5, // number of retries
|
|
69
|
-
retryDelay: function (retryCount) {
|
|
70
|
-
console.log("retry attempt: ".concat(retryCount));
|
|
71
|
-
return retryCount * 1000; // time interval between retries
|
|
72
|
-
},
|
|
73
|
-
retryCondition: function (error) {
|
|
74
|
-
console.error(error);
|
|
75
|
-
// if retry condition is not specified, by default idempotent requests are retried
|
|
76
|
-
return error.response.status === 503;
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
var ProToken = require("@pioneer-platform/pro-token");
|
|
80
|
-
var log = require('@pioneer-platform/loggerdog')();
|
|
81
|
-
var _a = require("@pioneer-platform/pioneer-coins"), getExplorerAddressUrl = _a.getExplorerAddressUrl, needsMemoByNetwork = _a.needsMemoByNetwork, COIN_MAP_LONG = _a.COIN_MAP_LONG;
|
|
82
|
-
var _b = require('@pioneer-platform/default-redis'), subscriber = _b.subscriber, publisher = _b.publisher, redis = _b.redis, redisQueue = _b.redisQueue;
|
|
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/";
|
|
87
|
-
var URL_COINGECKO = "https://api.coingecko.com/api/v3/";
|
|
88
|
-
// API Keys
|
|
89
|
-
var COINCAP_API_KEY = process.env['COINCAP_API_KEY'];
|
|
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
|
-
}
|
|
94
|
-
var GLOBAL_RATES_COINCAP;
|
|
95
|
-
var GLOBAL_RATES_COINGECKO;
|
|
96
|
-
module.exports = {
|
|
97
|
-
init: function (settings) {
|
|
98
|
-
if (settings === null || settings === void 0 ? void 0 : settings.apiKey) {
|
|
99
|
-
COINGECKO_API_KEY = settings.apiKey;
|
|
100
|
-
}
|
|
101
|
-
//if(!COINGECKO_API_KEY) throw Error("api key required! set env COINGECKO_API_KEY")
|
|
102
|
-
},
|
|
103
|
-
getAssetsCoinCap: function () {
|
|
104
|
-
return get_assets_coincap();
|
|
105
|
-
},
|
|
106
|
-
getAssetsCoingecko: function (limit, skip) {
|
|
107
|
-
return get_assets_coingecko(limit, skip);
|
|
108
|
-
},
|
|
109
|
-
getRatePro: function () {
|
|
110
|
-
return ProToken.getRateProUsd();
|
|
111
|
-
},
|
|
112
|
-
updateCache: function () {
|
|
113
|
-
return update_cache();
|
|
114
|
-
},
|
|
115
|
-
getPrice: function (asset) {
|
|
116
|
-
return get_price(asset);
|
|
117
|
-
},
|
|
118
|
-
getPricesInQuote: function (assets, quote) {
|
|
119
|
-
return get_prices_in_quote(assets, quote);
|
|
120
|
-
},
|
|
121
|
-
buildBalances: function (marketInfoCoinCap, marketInfoCoinGecko, pubkeys, context) {
|
|
122
|
-
return build_balances(marketInfoCoinCap, marketInfoCoinGecko, pubkeys);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
var update_cache = function () {
|
|
126
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
127
|
-
var tag, entries, url, result, allCoinsArray, populatedCaips_1, _loop_1, i, limit, totalAssets, totalPages, page, url_1, result_1, allCoinsArray_2, _loop_2, _i, allCoinsArray_1, coin, missingCaips, e_1;
|
|
128
|
-
return __generator(this, function (_a) {
|
|
129
|
-
switch (_a.label) {
|
|
130
|
-
case 0:
|
|
131
|
-
tag = TAG + ' | update_cache | ';
|
|
132
|
-
_a.label = 1;
|
|
133
|
-
case 1:
|
|
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
|
-
}
|
|
140
|
-
entries = Object.entries(pioneer_discovery_1.assetData).map(function (_a) {
|
|
141
|
-
var caip = _a[0], asset = _a[1];
|
|
142
|
-
if (typeof asset === 'object' && asset !== null) {
|
|
143
|
-
return __assign(__assign({}, asset), { caip: caip });
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
throw new Error("Invalid asset type for CAIP ".concat(caip));
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
log.debug(tag, "entries: ", entries);
|
|
150
|
-
log.info(tag, "entries: ", entries[0]);
|
|
151
|
-
log.info(tag, "entries: ", entries.length);
|
|
152
|
-
url = "".concat(URL_COINCAP, "assets?limit=2000");
|
|
153
|
-
log.debug(tag, "url: ", url);
|
|
154
|
-
return [4 /*yield*/, axios({
|
|
155
|
-
url: url,
|
|
156
|
-
method: 'GET',
|
|
157
|
-
headers: {
|
|
158
|
-
'Accept': 'application/json',
|
|
159
|
-
'Authorization': "Bearer ".concat(COINCAP_API_KEY)
|
|
160
|
-
}
|
|
161
|
-
})];
|
|
162
|
-
case 2:
|
|
163
|
-
result = _a.sent();
|
|
164
|
-
allCoinsArray = result.data.data;
|
|
165
|
-
log.debug(tag, "allCoinsArray: ", allCoinsArray.length);
|
|
166
|
-
populatedCaips_1 = new Set();
|
|
167
|
-
_loop_1 = function (i) {
|
|
168
|
-
var entry, assetsMatchSymbol, j, asset, key;
|
|
169
|
-
return __generator(this, function (_b) {
|
|
170
|
-
switch (_b.label) {
|
|
171
|
-
case 0:
|
|
172
|
-
entry = allCoinsArray[i];
|
|
173
|
-
assetsMatchSymbol = entries.filter(function (asset) { return asset.symbol === entry.symbol; });
|
|
174
|
-
j = 0;
|
|
175
|
-
_b.label = 1;
|
|
176
|
-
case 1:
|
|
177
|
-
if (!(j < assetsMatchSymbol.length)) return [3 /*break*/, 4];
|
|
178
|
-
asset = assetsMatchSymbol[j];
|
|
179
|
-
key = "coincap:" + asset.caip;
|
|
180
|
-
return [4 /*yield*/, redis.setex(key, 3600, JSON.stringify(entry))];
|
|
181
|
-
case 2:
|
|
182
|
-
_b.sent();
|
|
183
|
-
log.info(tag, "saved: " + key);
|
|
184
|
-
populatedCaips_1.add(asset.caip);
|
|
185
|
-
_b.label = 3;
|
|
186
|
-
case 3:
|
|
187
|
-
j++;
|
|
188
|
-
return [3 /*break*/, 1];
|
|
189
|
-
case 4: return [2 /*return*/];
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
};
|
|
193
|
-
i = 0;
|
|
194
|
-
_a.label = 3;
|
|
195
|
-
case 3:
|
|
196
|
-
if (!(i < allCoinsArray.length)) return [3 /*break*/, 6];
|
|
197
|
-
return [5 /*yield**/, _loop_1(i)];
|
|
198
|
-
case 4:
|
|
199
|
-
_a.sent();
|
|
200
|
-
_a.label = 5;
|
|
201
|
-
case 5:
|
|
202
|
-
i++;
|
|
203
|
-
return [3 /*break*/, 3];
|
|
204
|
-
case 6:
|
|
205
|
-
limit = 250;
|
|
206
|
-
totalAssets = 2000;
|
|
207
|
-
totalPages = Math.ceil(totalAssets / limit);
|
|
208
|
-
page = 1;
|
|
209
|
-
_a.label = 7;
|
|
210
|
-
case 7:
|
|
211
|
-
if (!(page <= totalPages)) return [3 /*break*/, 15];
|
|
212
|
-
url_1 = "".concat(URL_COINGECKO, "coins/markets?vs_currency=usd&order=market_cap_desc&per_page=").concat(limit, "&page=").concat(page, "&sparkline=false");
|
|
213
|
-
log.debug(tag, "Fetching URL: ", url_1);
|
|
214
|
-
return [4 /*yield*/, axios.get(url_1)];
|
|
215
|
-
case 8:
|
|
216
|
-
result_1 = _a.sent();
|
|
217
|
-
allCoinsArray_2 = result_1.data;
|
|
218
|
-
log.debug(tag, "Fetched ".concat(allCoinsArray_2.length, " coins for page ").concat(page));
|
|
219
|
-
_loop_2 = function (coin) {
|
|
220
|
-
var matchingAssets, _c, matchingAssets_1, matchingAsset, key;
|
|
221
|
-
return __generator(this, function (_d) {
|
|
222
|
-
switch (_d.label) {
|
|
223
|
-
case 0:
|
|
224
|
-
matchingAssets = entries.filter(function (asset) { return asset.symbol === coin.symbol.toUpperCase(); });
|
|
225
|
-
_c = 0, matchingAssets_1 = matchingAssets;
|
|
226
|
-
_d.label = 1;
|
|
227
|
-
case 1:
|
|
228
|
-
if (!(_c < matchingAssets_1.length)) return [3 /*break*/, 4];
|
|
229
|
-
matchingAsset = matchingAssets_1[_c];
|
|
230
|
-
key = "coingecko:".concat(matchingAsset.caip);
|
|
231
|
-
return [4 /*yield*/, redis.setex(key, 3600, JSON.stringify(coin))];
|
|
232
|
-
case 2:
|
|
233
|
-
_d.sent();
|
|
234
|
-
log.info(tag, "Saved ".concat(coin.symbol, " under ").concat(key));
|
|
235
|
-
populatedCaips_1.add(matchingAsset.caip);
|
|
236
|
-
_d.label = 3;
|
|
237
|
-
case 3:
|
|
238
|
-
_c++;
|
|
239
|
-
return [3 /*break*/, 1];
|
|
240
|
-
case 4: return [2 /*return*/];
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
};
|
|
244
|
-
_i = 0, allCoinsArray_1 = allCoinsArray_2;
|
|
245
|
-
_a.label = 9;
|
|
246
|
-
case 9:
|
|
247
|
-
if (!(_i < allCoinsArray_1.length)) return [3 /*break*/, 12];
|
|
248
|
-
coin = allCoinsArray_1[_i];
|
|
249
|
-
return [5 /*yield**/, _loop_2(coin)];
|
|
250
|
-
case 10:
|
|
251
|
-
_a.sent();
|
|
252
|
-
_a.label = 11;
|
|
253
|
-
case 11:
|
|
254
|
-
_i++;
|
|
255
|
-
return [3 /*break*/, 9];
|
|
256
|
-
case 12:
|
|
257
|
-
if (!(page < totalPages)) return [3 /*break*/, 14];
|
|
258
|
-
log.debug(tag, "Waiting 10 seconds before next query...");
|
|
259
|
-
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 30000); })];
|
|
260
|
-
case 13:
|
|
261
|
-
_a.sent();
|
|
262
|
-
_a.label = 14;
|
|
263
|
-
case 14:
|
|
264
|
-
page++;
|
|
265
|
-
return [3 /*break*/, 7];
|
|
266
|
-
case 15:
|
|
267
|
-
missingCaips = entries.filter(function (asset) { return !populatedCaips_1.has(asset.caip); }).map(function (asset) { return asset.caip; });
|
|
268
|
-
log.info(tag, "Missing CAIPs: ", missingCaips);
|
|
269
|
-
return [2 /*return*/, missingCaips];
|
|
270
|
-
case 16:
|
|
271
|
-
e_1 = _a.sent();
|
|
272
|
-
log.error(e_1);
|
|
273
|
-
return [3 /*break*/, 17];
|
|
274
|
-
case 17: return [2 /*return*/];
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
};
|
|
279
|
-
// const update_cache = async function() {
|
|
280
|
-
// let tag = TAG + ' | update_cache | '
|
|
281
|
-
// try{
|
|
282
|
-
// // log.info(tag,"assetData: ",assetData)
|
|
283
|
-
// // let entries = Object.values(assetData)
|
|
284
|
-
// // @ts-ignore
|
|
285
|
-
// let entries = Object.entries(assetData).map(([caip, asset]) => ({...asset, caip}));
|
|
286
|
-
//
|
|
287
|
-
// log.debug(tag,"entries: ",entries)
|
|
288
|
-
// log.info(tag,"entries: ",entries[0])
|
|
289
|
-
// log.info(tag,"entries: ",entries.length)
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
// let url = URL_COINCAP + 'assets?limit=2000'
|
|
293
|
-
// log.debug(tag,"url: ",url)
|
|
294
|
-
// let result = await axios({
|
|
295
|
-
// url: url,
|
|
296
|
-
// method: 'GET'
|
|
297
|
-
// })
|
|
298
|
-
//
|
|
299
|
-
// //parse into keys array off ticker
|
|
300
|
-
// let allCoinsArray = result.data.data
|
|
301
|
-
// log.debug(tag,"allCoinsArray: ",allCoinsArray.length)
|
|
302
|
-
//
|
|
303
|
-
// // let marketInfoCoinGecko = await get_assets_coingecko()
|
|
304
|
-
// for(let i = 0; i < allCoinsArray.length; i++){
|
|
305
|
-
// let entry = allCoinsArray[i]
|
|
306
|
-
// // log.debug(tag,"entry: ",entry)
|
|
307
|
-
//
|
|
308
|
-
// //hits by symbol
|
|
309
|
-
// // @ts-ignore
|
|
310
|
-
// let assetsMatchSymbol = entries.filter(asset => asset.symbol === entry.symbol);
|
|
311
|
-
// //for now ignore this stuffs
|
|
312
|
-
// // if(assetsMatchSymbol.length > 1){ // @ts-ignore
|
|
313
|
-
// // console.log(assetsMatchSymbol[0].symbol+ " assetsMatchSymbol: ",assetsMatchSymbol.length)
|
|
314
|
-
// // console.log("0: ",assetsMatchSymbol[0])
|
|
315
|
-
// // console.log("1: ",assetsMatchSymbol[1])
|
|
316
|
-
// // }
|
|
317
|
-
//
|
|
318
|
-
// for(let j = 0; j < assetsMatchSymbol.length; j++){
|
|
319
|
-
// let asset = assetsMatchSymbol[j]
|
|
320
|
-
// // log.debug(tag,"asset: ",asset)
|
|
321
|
-
// // @ts-ignore
|
|
322
|
-
// let key = "coincap:"+asset.caip
|
|
323
|
-
// // log.debug(tag,"key: ",key)
|
|
324
|
-
// //save cache by caip with 1hour cache
|
|
325
|
-
// let result = await redis.setex(key, 3600, JSON.stringify(entry))
|
|
326
|
-
// log.debug(tag,"saved: "+key+" result: ",result)
|
|
327
|
-
// }
|
|
328
|
-
// }
|
|
329
|
-
//
|
|
330
|
-
// // Handling pagination for CoinGecko
|
|
331
|
-
// const limit = 250; // assets per request
|
|
332
|
-
// const totalAssets = 2000; // total assets to fetch
|
|
333
|
-
// const totalPages = Math.ceil(totalAssets / limit); // calculate total pages needed
|
|
334
|
-
//
|
|
335
|
-
// for (let page = 1; page <= totalPages; page++) {
|
|
336
|
-
// let url = `${URL_COINGECKO}coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${limit}&page=${page}&sparkline=false`;
|
|
337
|
-
// log.debug(tag, "Fetching URL: ", url);
|
|
338
|
-
//
|
|
339
|
-
// let result = await axios.get(url);
|
|
340
|
-
// let allCoinsArray = result.data;
|
|
341
|
-
// log.debug(tag, `Fetched ${allCoinsArray.length} coins for page ${page}`);
|
|
342
|
-
// // log.debug(tag,"allCoinsArray: ",allCoinsArray)
|
|
343
|
-
// // Process each coin
|
|
344
|
-
// for (let coin of allCoinsArray) {
|
|
345
|
-
// // log.debug(tag,"coin: ",coin)
|
|
346
|
-
// let matchingAssets = entries.filter(asset => asset.symbol === coin.symbol.toUpperCase());
|
|
347
|
-
// for (let matchingAsset of matchingAssets) {
|
|
348
|
-
// let key = `coingecko:${matchingAsset.caip}`;
|
|
349
|
-
// await redis.setex(key, 3600, JSON.stringify(coin));
|
|
350
|
-
// log.debug(tag, `Saved ${coin.symbol} under ${key}`);
|
|
351
|
-
// }
|
|
352
|
-
// }
|
|
353
|
-
//
|
|
354
|
-
// // Wait 10 seconds before the next page request if it's not the last page
|
|
355
|
-
// if (page < totalPages) {
|
|
356
|
-
// log.debug(tag, `Waiting 10 seconds before next query...`);
|
|
357
|
-
// await new Promise(resolve => setTimeout(resolve, 30000));
|
|
358
|
-
// }
|
|
359
|
-
// }
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
// //mayachain info
|
|
363
|
-
// // const response = await axios.get('https://www.mayascan.org/api/cacao/price?days=1');
|
|
364
|
-
// // const latestCandle = response.data.candles.pop(); // Assuming you want the latest price
|
|
365
|
-
// // let cacaoPrice = latestCandle.close; // Using the close price as the current price
|
|
366
|
-
//
|
|
367
|
-
//
|
|
368
|
-
// }catch(e){
|
|
369
|
-
// log.error(e)
|
|
370
|
-
// }
|
|
371
|
-
// }
|
|
372
|
-
var build_balances = function (marketInfoCoinCap, marketInfoCoinGecko, pubkeys) {
|
|
373
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
374
|
-
var tag, valuesUsd, totalValueUsd, outputBalances, unknownTokens, unPricedTokens, i, entry, proUsdRate, coincap, coingecko, priceUsd, balance, valueUsd, e_2;
|
|
375
|
-
return __generator(this, function (_a) {
|
|
376
|
-
switch (_a.label) {
|
|
377
|
-
case 0:
|
|
378
|
-
tag = TAG + ' | build_balances | ';
|
|
379
|
-
_a.label = 1;
|
|
380
|
-
case 1:
|
|
381
|
-
_a.trys.push([1, 12, , 13]);
|
|
382
|
-
if (!pubkeys)
|
|
383
|
-
throw Error("No pubkeys given!");
|
|
384
|
-
if (!!marketInfoCoinCap) return [3 /*break*/, 3];
|
|
385
|
-
return [4 /*yield*/, get_assets_coincap()];
|
|
386
|
-
case 2:
|
|
387
|
-
marketInfoCoinCap = _a.sent();
|
|
388
|
-
_a.label = 3;
|
|
389
|
-
case 3:
|
|
390
|
-
if (!!marketInfoCoinGecko) return [3 /*break*/, 5];
|
|
391
|
-
return [4 /*yield*/, get_assets_coingecko()
|
|
392
|
-
// console.log(Object.keys(marketInfoCoinCap))
|
|
393
|
-
// console.log(Object.keys(marketInfoCoinGecko))
|
|
394
|
-
// console.log(Object.keys(marketInfoCoinCap).length)
|
|
395
|
-
// console.log(Object.keys(marketInfoCoinGecko).length)
|
|
396
|
-
];
|
|
397
|
-
case 4:
|
|
398
|
-
marketInfoCoinGecko = _a.sent();
|
|
399
|
-
_a.label = 5;
|
|
400
|
-
case 5:
|
|
401
|
-
valuesUsd = {};
|
|
402
|
-
totalValueUsd = 0;
|
|
403
|
-
outputBalances = [];
|
|
404
|
-
unknownTokens = [];
|
|
405
|
-
unPricedTokens = [];
|
|
406
|
-
i = 0;
|
|
407
|
-
_a.label = 6;
|
|
408
|
-
case 6:
|
|
409
|
-
if (!(i < pubkeys.length)) return [3 /*break*/, 11];
|
|
410
|
-
entry = pubkeys[i];
|
|
411
|
-
if (!(entry.ticker === 'PRO')) return [3 /*break*/, 8];
|
|
412
|
-
return [4 /*yield*/, ProToken.getRateProUsd()];
|
|
413
|
-
case 7:
|
|
414
|
-
proUsdRate = _a.sent();
|
|
415
|
-
redis.set('proUsdRate', proUsdRate);
|
|
416
|
-
console.log("proToUsdRate: ", proUsdRate);
|
|
417
|
-
entry.priceUsd = proUsdRate;
|
|
418
|
-
//TODO get rate in USD
|
|
419
|
-
entry.rank = 10;
|
|
420
|
-
entry.alias = [];
|
|
421
|
-
entry.alias.push('PRO');
|
|
422
|
-
entry.source = "uniswap";
|
|
423
|
-
entry.symbol = "PRO";
|
|
424
|
-
return [3 /*break*/, 9];
|
|
425
|
-
case 8:
|
|
426
|
-
coincap = marketInfoCoinCap[entry.ticker];
|
|
427
|
-
coingecko = marketInfoCoinGecko[entry.ticker];
|
|
428
|
-
// log.debug("coincap: ",coincap)
|
|
429
|
-
// log.debug("coingecko: ",coingecko)
|
|
430
|
-
if (!coincap && !coingecko) {
|
|
431
|
-
//console.error("unknown token! ",entry.symbol)
|
|
432
|
-
unknownTokens.push(entry);
|
|
433
|
-
}
|
|
434
|
-
if (coincap && coincap.priceUsd) {
|
|
435
|
-
entry.priceUsd = coincap.priceUsd;
|
|
436
|
-
entry.rank = coincap.rank;
|
|
437
|
-
entry.alias = [];
|
|
438
|
-
if (!entry.name)
|
|
439
|
-
entry.name = coincap.name;
|
|
440
|
-
if (entry.name)
|
|
441
|
-
entry.alias.push(entry.name);
|
|
442
|
-
// entry.marketInfo = coincap
|
|
443
|
-
entry.source = "coincap";
|
|
444
|
-
}
|
|
445
|
-
//preference coinGecko as more accurate
|
|
446
|
-
if (coingecko && coingecko.current_price) {
|
|
447
|
-
entry.alias = [];
|
|
448
|
-
if (entry.name)
|
|
449
|
-
entry.alias.push(entry.name);
|
|
450
|
-
entry.priceUsd = coingecko.current_price;
|
|
451
|
-
if (!entry.name)
|
|
452
|
-
entry.name = coingecko.id;
|
|
453
|
-
entry.alias = entry.alias.push(coingecko.name);
|
|
454
|
-
entry.rank = coingecko.market_cap_rank;
|
|
455
|
-
entry.source = "coingecko";
|
|
456
|
-
}
|
|
457
|
-
_a.label = 9;
|
|
458
|
-
case 9:
|
|
459
|
-
priceUsd = Number(entry.priceUsd);
|
|
460
|
-
if (!isNaN(priceUsd) && priceUsd !== 0) {
|
|
461
|
-
balance = Number(entry.balance) || 0;
|
|
462
|
-
valueUsd = balance * priceUsd;
|
|
463
|
-
// Convert valueUsd to string and store back on the entry
|
|
464
|
-
entry.valueUsd = String(valueUsd);
|
|
465
|
-
// Add valueUsd to totalValueUsd, ensure totalValueUsd is a number
|
|
466
|
-
totalValueUsd += valueUsd;
|
|
467
|
-
// Push the entry to the output balances
|
|
468
|
-
outputBalances.push(entry);
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
// Push the entry to unPricedTokens if priceUsd is not valid
|
|
472
|
-
unPricedTokens.push(entry);
|
|
473
|
-
}
|
|
474
|
-
_a.label = 10;
|
|
475
|
-
case 10:
|
|
476
|
-
i++;
|
|
477
|
-
return [3 /*break*/, 6];
|
|
478
|
-
case 11: return [2 /*return*/, { outputBalances: outputBalances, unPricedTokens: unPricedTokens, unknownTokens: unknownTokens, total: totalValueUsd }];
|
|
479
|
-
case 12:
|
|
480
|
-
e_2 = _a.sent();
|
|
481
|
-
console.error(tag, 'Error: ', e_2);
|
|
482
|
-
throw e_2;
|
|
483
|
-
case 13: return [2 /*return*/];
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
});
|
|
487
|
-
};
|
|
488
|
-
var get_assets_coincap = function () {
|
|
489
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
490
|
-
var tag, output, url, result, allCoinsArray, i, coinInfo, e_3;
|
|
491
|
-
return __generator(this, function (_a) {
|
|
492
|
-
switch (_a.label) {
|
|
493
|
-
case 0:
|
|
494
|
-
tag = TAG + ' | get_assets_coincap | ';
|
|
495
|
-
_a.label = 1;
|
|
496
|
-
case 1:
|
|
497
|
-
_a.trys.push([1, 3, , 4]);
|
|
498
|
-
output = {};
|
|
499
|
-
// API 3.0 requires an API key
|
|
500
|
-
if (!COINCAP_API_KEY) {
|
|
501
|
-
log.error(tag, "COINCAP_API_KEY is required for CoinCap API 3.0");
|
|
502
|
-
return [2 /*return*/, {}];
|
|
503
|
-
}
|
|
504
|
-
url = "".concat(URL_COINCAP, "assets?limit=2000");
|
|
505
|
-
log.debug(tag, "url: ", url);
|
|
506
|
-
return [4 /*yield*/, axios({
|
|
507
|
-
url: url,
|
|
508
|
-
method: 'GET',
|
|
509
|
-
headers: {
|
|
510
|
-
'Accept': 'application/json',
|
|
511
|
-
'Authorization': "Bearer ".concat(COINCAP_API_KEY)
|
|
512
|
-
}
|
|
513
|
-
})
|
|
514
|
-
// Parse into keys array off ticker
|
|
515
|
-
];
|
|
516
|
-
case 2:
|
|
517
|
-
result = _a.sent();
|
|
518
|
-
allCoinsArray = result.data.data;
|
|
519
|
-
log.debug(tag, "allCoinsArray: ", allCoinsArray.length);
|
|
520
|
-
for (i = 0; i < allCoinsArray.length; i++) {
|
|
521
|
-
coinInfo = allCoinsArray[i];
|
|
522
|
-
log.debug(tag, "coinInfo: ", coinInfo);
|
|
523
|
-
output[coinInfo.symbol] = coinInfo;
|
|
524
|
-
}
|
|
525
|
-
log.debug('result: ', output);
|
|
526
|
-
return [2 /*return*/, output];
|
|
527
|
-
case 3:
|
|
528
|
-
e_3 = _a.sent();
|
|
529
|
-
log.error(TAG, "Error fetching CoinCap assets: ", e_3);
|
|
530
|
-
// Handle error gracefully
|
|
531
|
-
return [2 /*return*/, {}];
|
|
532
|
-
case 4: return [2 /*return*/];
|
|
533
|
-
}
|
|
534
|
-
});
|
|
535
|
-
});
|
|
536
|
-
};
|
|
537
|
-
var get_assets_coingecko = function (limit, skip) {
|
|
538
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
539
|
-
var tag, output, url, result, allCoinsArray, i, coinInfo, e_4;
|
|
540
|
-
return __generator(this, function (_a) {
|
|
541
|
-
switch (_a.label) {
|
|
542
|
-
case 0:
|
|
543
|
-
tag = TAG + ' | get_assets_coingecko | ';
|
|
544
|
-
_a.label = 1;
|
|
545
|
-
case 1:
|
|
546
|
-
_a.trys.push([1, 3, , 4]);
|
|
547
|
-
output = {};
|
|
548
|
-
if (!limit)
|
|
549
|
-
limit = 250;
|
|
550
|
-
if (!skip)
|
|
551
|
-
skip = 0;
|
|
552
|
-
url = URL_COINGECKO + "coins/markets?vs_currency=usd&order=market_cap_desc&per_page=".concat(limit, "&page=").concat(skip, "&sparkline=false");
|
|
553
|
-
log.debug(tag, "url: ", url);
|
|
554
|
-
return [4 /*yield*/, axios({
|
|
555
|
-
url: url,
|
|
556
|
-
method: 'GET'
|
|
557
|
-
})];
|
|
558
|
-
case 2:
|
|
559
|
-
result = _a.sent();
|
|
560
|
-
log.debug(tag, "result: ", result.data);
|
|
561
|
-
allCoinsArray = result.data;
|
|
562
|
-
log.debug(tag, "allCoinsArray: ", allCoinsArray.length);
|
|
563
|
-
for (i = 0; i < allCoinsArray.length; i++) {
|
|
564
|
-
coinInfo = allCoinsArray[i];
|
|
565
|
-
log.debug(tag, "coinInfo: ", coinInfo);
|
|
566
|
-
// @ts-ignore
|
|
567
|
-
output[coinInfo.symbol.toUpperCase()] = coinInfo;
|
|
568
|
-
}
|
|
569
|
-
log.debug('result: ', output);
|
|
570
|
-
return [2 /*return*/, output];
|
|
571
|
-
case 3:
|
|
572
|
-
e_4 = _a.sent();
|
|
573
|
-
//handle error gracefully
|
|
574
|
-
return [2 /*return*/, {}];
|
|
575
|
-
case 4: return [2 /*return*/];
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
});
|
|
579
|
-
};
|
|
580
|
-
var get_prices_in_quote = function (assets, quote) {
|
|
581
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
582
|
-
var tag, result, _i, assets_1, asset, url, response, assetError_1, coincapError_1, data, e_5;
|
|
583
|
-
return __generator(this, function (_a) {
|
|
584
|
-
switch (_a.label) {
|
|
585
|
-
case 0:
|
|
586
|
-
tag = " | get_prices_in_quote | ";
|
|
587
|
-
_a.label = 1;
|
|
588
|
-
case 1:
|
|
589
|
-
_a.trys.push([1, 12, , 13]);
|
|
590
|
-
if (!(COINCAP_API_KEY && quote.toLowerCase() === 'usd')) return [3 /*break*/, 10];
|
|
591
|
-
_a.label = 2;
|
|
592
|
-
case 2:
|
|
593
|
-
_a.trys.push([2, 9, , 10]);
|
|
594
|
-
result = {};
|
|
595
|
-
_i = 0, assets_1 = assets;
|
|
596
|
-
_a.label = 3;
|
|
597
|
-
case 3:
|
|
598
|
-
if (!(_i < assets_1.length)) return [3 /*break*/, 8];
|
|
599
|
-
asset = assets_1[_i];
|
|
600
|
-
_a.label = 4;
|
|
601
|
-
case 4:
|
|
602
|
-
_a.trys.push([4, 6, , 7]);
|
|
603
|
-
url = "".concat(URL_COINCAP, "assets/").concat(asset);
|
|
604
|
-
return [4 /*yield*/, axios({
|
|
605
|
-
url: url,
|
|
606
|
-
method: 'GET',
|
|
607
|
-
headers: {
|
|
608
|
-
'Accept': 'application/json',
|
|
609
|
-
'Authorization': "Bearer ".concat(COINCAP_API_KEY)
|
|
610
|
-
}
|
|
611
|
-
})];
|
|
612
|
-
case 5:
|
|
613
|
-
response = _a.sent();
|
|
614
|
-
if (response.data && response.data.data) {
|
|
615
|
-
result[asset] = {
|
|
616
|
-
usd: parseFloat(response.data.data.priceUsd)
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
return [3 /*break*/, 7];
|
|
620
|
-
case 6:
|
|
621
|
-
assetError_1 = _a.sent();
|
|
622
|
-
log.error(tag, "Error fetching price for ".concat(asset, " from CoinCap: "), assetError_1);
|
|
623
|
-
return [3 /*break*/, 7];
|
|
624
|
-
case 7:
|
|
625
|
-
_i++;
|
|
626
|
-
return [3 /*break*/, 3];
|
|
627
|
-
case 8:
|
|
628
|
-
// If we got at least one result, return it
|
|
629
|
-
if (Object.keys(result).length > 0) {
|
|
630
|
-
return [2 /*return*/, result];
|
|
631
|
-
}
|
|
632
|
-
return [3 /*break*/, 10];
|
|
633
|
-
case 9:
|
|
634
|
-
coincapError_1 = _a.sent();
|
|
635
|
-
log.error(tag, "CoinCap API error, falling back to CoinGecko: ", coincapError_1);
|
|
636
|
-
return [3 /*break*/, 10];
|
|
637
|
-
case 10: return [4 /*yield*/, axios.get("".concat(URL_COINGECKO, "/simple/price?ids=").concat(assets.toString(), "&vs_currencies=").concat(quote))];
|
|
638
|
-
case 11:
|
|
639
|
-
data = (_a.sent()).data;
|
|
640
|
-
return [2 /*return*/, data];
|
|
641
|
-
case 12:
|
|
642
|
-
e_5 = _a.sent();
|
|
643
|
-
log.error(tag, "Error fetching prices: ", e_5);
|
|
644
|
-
return [2 /*return*/, {}];
|
|
645
|
-
case 13: return [2 /*return*/];
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
});
|
|
649
|
-
};
|
|
650
|
-
var get_price = function (asset) {
|
|
651
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
652
|
-
var tag, url, result, coinInfo, coincapError_2, data, currency, marketData, e_6;
|
|
653
|
-
var _a, _b, _c, _d;
|
|
654
|
-
return __generator(this, function (_e) {
|
|
655
|
-
switch (_e.label) {
|
|
656
|
-
case 0:
|
|
657
|
-
tag = " | get_price | ";
|
|
658
|
-
_e.label = 1;
|
|
659
|
-
case 1:
|
|
660
|
-
_e.trys.push([1, 7, , 8]);
|
|
661
|
-
if (!COINCAP_API_KEY) return [3 /*break*/, 5];
|
|
662
|
-
_e.label = 2;
|
|
663
|
-
case 2:
|
|
664
|
-
_e.trys.push([2, 4, , 5]);
|
|
665
|
-
url = "".concat(URL_COINCAP, "assets/").concat(asset);
|
|
666
|
-
log.debug(tag, "CoinCap URL: ", url);
|
|
667
|
-
return [4 /*yield*/, axios({
|
|
668
|
-
url: url,
|
|
669
|
-
method: 'GET',
|
|
670
|
-
headers: {
|
|
671
|
-
'Accept': 'application/json',
|
|
672
|
-
'Authorization': "Bearer ".concat(COINCAP_API_KEY)
|
|
673
|
-
}
|
|
674
|
-
})];
|
|
675
|
-
case 3:
|
|
676
|
-
result = _e.sent();
|
|
677
|
-
coinInfo = result.data.data;
|
|
678
|
-
return [2 /*return*/, {
|
|
679
|
-
price: parseFloat(coinInfo.priceUsd),
|
|
680
|
-
marketCap: parseFloat(coinInfo.marketCapUsd),
|
|
681
|
-
changePercent24Hr: parseFloat(coinInfo.changePercent24Hr),
|
|
682
|
-
volume: parseFloat(coinInfo.volumeUsd24Hr),
|
|
683
|
-
icon: "https://assets.coincap.io/assets/icons/".concat(coinInfo.symbol.toLowerCase(), "@2x.png")
|
|
684
|
-
}];
|
|
685
|
-
case 4:
|
|
686
|
-
coincapError_2 = _e.sent();
|
|
687
|
-
log.error(tag, "CoinCap API error, falling back to CoinGecko: ", coincapError_2);
|
|
688
|
-
return [3 /*break*/, 5];
|
|
689
|
-
case 5: return [4 /*yield*/, axios.get("".concat(URL_COINGECKO, "/coins/").concat(asset))
|
|
690
|
-
// TODO: get correct localizations
|
|
691
|
-
];
|
|
692
|
-
case 6:
|
|
693
|
-
data = (_e.sent()).data;
|
|
694
|
-
currency = 'usd';
|
|
695
|
-
marketData = data === null || data === void 0 ? void 0 : data.market_data;
|
|
696
|
-
return [2 /*return*/, {
|
|
697
|
-
price: (_a = marketData === null || marketData === void 0 ? void 0 : marketData.current_price) === null || _a === void 0 ? void 0 : _a[currency],
|
|
698
|
-
marketCap: (_b = marketData === null || marketData === void 0 ? void 0 : marketData.market_cap) === null || _b === void 0 ? void 0 : _b[currency],
|
|
699
|
-
changePercent24Hr: marketData === null || marketData === void 0 ? void 0 : marketData.price_change_percentage_24h,
|
|
700
|
-
volume: (_c = marketData === null || marketData === void 0 ? void 0 : marketData.total_volume) === null || _c === void 0 ? void 0 : _c[currency],
|
|
701
|
-
icon: (_d = data === null || data === void 0 ? void 0 : data.image) === null || _d === void 0 ? void 0 : _d.large
|
|
702
|
-
}];
|
|
703
|
-
case 7:
|
|
704
|
-
e_6 = _e.sent();
|
|
705
|
-
log.error(tag, "Error fetching price data: ", e_6);
|
|
706
|
-
return [2 /*return*/, null];
|
|
707
|
-
case 8: return [2 /*return*/];
|
|
708
|
-
}
|
|
709
|
-
});
|
|
710
|
-
});
|
|
711
|
-
};
|