@talismn/token-rates 3.0.22 → 4.0.0
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/LICENSE +253 -674
- package/dist/index.d.mts +144 -98
- package/dist/index.d.mts.map +1 -0
- package/dist/index.d.ts +144 -98
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +339 -191
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +314 -165
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -5
package/dist/index.js
CHANGED
|
@@ -1,206 +1,354 @@
|
|
|
1
|
-
"
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
2
4
|
var __defProp = Object.defineProperty;
|
|
3
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
9
|
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
17
18
|
};
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
24
|
+
let _talismn_chaindata_provider = require("@talismn/chaindata-provider");
|
|
25
|
+
let _talismn_util = require("@talismn/util");
|
|
26
|
+
let scale_ts = require("scale-ts");
|
|
27
|
+
let anylogger = require("anylogger");
|
|
28
|
+
anylogger = __toESM(anylogger);
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/log.ts
|
|
31
|
+
var log_default = (0, anylogger.default)("@talismn/token-rates");
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/types.ts
|
|
34
|
+
const SUPPORTED_CURRENCIES = {
|
|
35
|
+
btc: {
|
|
36
|
+
name: "Bitcoin",
|
|
37
|
+
symbol: "₿"
|
|
38
|
+
},
|
|
39
|
+
eth: {
|
|
40
|
+
name: "Ethereum",
|
|
41
|
+
symbol: "Ξ"
|
|
42
|
+
},
|
|
43
|
+
dot: {
|
|
44
|
+
name: "Polkadot",
|
|
45
|
+
symbol: "D"
|
|
46
|
+
},
|
|
47
|
+
tao: {
|
|
48
|
+
name: "Bittensor",
|
|
49
|
+
symbol: "τ"
|
|
50
|
+
},
|
|
51
|
+
usd: {
|
|
52
|
+
name: "US Dollar",
|
|
53
|
+
symbol: "$"
|
|
54
|
+
},
|
|
55
|
+
cny: {
|
|
56
|
+
name: "Chinese Yuan",
|
|
57
|
+
symbol: "¥"
|
|
58
|
+
},
|
|
59
|
+
eur: {
|
|
60
|
+
name: "Euro",
|
|
61
|
+
symbol: "€"
|
|
62
|
+
},
|
|
63
|
+
gbp: {
|
|
64
|
+
name: "British Pound",
|
|
65
|
+
symbol: "£"
|
|
66
|
+
},
|
|
67
|
+
cad: {
|
|
68
|
+
name: "Canadian Dollar",
|
|
69
|
+
symbol: "C$"
|
|
70
|
+
},
|
|
71
|
+
aud: {
|
|
72
|
+
name: "Australian Dollar",
|
|
73
|
+
symbol: "A$"
|
|
74
|
+
},
|
|
75
|
+
nzd: {
|
|
76
|
+
name: "New Zealand Dollar",
|
|
77
|
+
symbol: "NZ$"
|
|
78
|
+
},
|
|
79
|
+
jpy: {
|
|
80
|
+
name: "Japanese Yen",
|
|
81
|
+
symbol: "¥"
|
|
82
|
+
},
|
|
83
|
+
rub: {
|
|
84
|
+
name: "Russian Ruble",
|
|
85
|
+
symbol: "₽"
|
|
86
|
+
},
|
|
87
|
+
krw: {
|
|
88
|
+
name: "South Korean Won",
|
|
89
|
+
symbol: "₩"
|
|
90
|
+
},
|
|
91
|
+
idr: {
|
|
92
|
+
name: "Indonesian Rupiah",
|
|
93
|
+
symbol: "Rp"
|
|
94
|
+
},
|
|
95
|
+
php: {
|
|
96
|
+
name: "Philippine Peso",
|
|
97
|
+
symbol: "₱"
|
|
98
|
+
},
|
|
99
|
+
thb: {
|
|
100
|
+
name: "Thai Baht",
|
|
101
|
+
symbol: "฿"
|
|
102
|
+
},
|
|
103
|
+
vnd: {
|
|
104
|
+
name: "Vietnamese Dong",
|
|
105
|
+
symbol: "₫"
|
|
106
|
+
},
|
|
107
|
+
inr: {
|
|
108
|
+
name: "Indian Rupee",
|
|
109
|
+
symbol: "₹"
|
|
110
|
+
},
|
|
111
|
+
try: {
|
|
112
|
+
name: "Turkish Lira",
|
|
113
|
+
symbol: "₺"
|
|
114
|
+
},
|
|
115
|
+
sgd: {
|
|
116
|
+
name: "Singapore Dollar",
|
|
117
|
+
symbol: "S$"
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const newTokenRates = () => ({
|
|
121
|
+
btc: null,
|
|
122
|
+
eth: null,
|
|
123
|
+
dot: null,
|
|
124
|
+
tao: null,
|
|
125
|
+
usd: null,
|
|
126
|
+
cny: null,
|
|
127
|
+
eur: null,
|
|
128
|
+
gbp: null,
|
|
129
|
+
cad: null,
|
|
130
|
+
aud: null,
|
|
131
|
+
nzd: null,
|
|
132
|
+
jpy: null,
|
|
133
|
+
rub: null,
|
|
134
|
+
krw: null,
|
|
135
|
+
idr: null,
|
|
136
|
+
php: null,
|
|
137
|
+
thb: null,
|
|
138
|
+
vnd: null,
|
|
139
|
+
inr: null,
|
|
140
|
+
try: null,
|
|
141
|
+
sgd: null
|
|
30
142
|
});
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/getDTaoTokenRates.ts
|
|
145
|
+
/** TAO-per-alpha pool price fixed-point scale: 10^9 (TAO decimals) */
|
|
146
|
+
const SCALED_ALPHA_PRICE_SCALE = 10 ** 9;
|
|
147
|
+
/**
|
|
148
|
+
* 24h change of an alpha token in a given currency, in percent: the pool price change (alpha vs
|
|
149
|
+
* TAO) compounded with the TAO change in that currency. Unknown without the pool change.
|
|
150
|
+
*/
|
|
151
|
+
const getAlphaChange24h = (currency, taoChange24h, alphaPriceChange24h) => {
|
|
152
|
+
if (typeof alphaPriceChange24h !== "number" || !Number.isFinite(alphaPriceChange24h)) return void 0;
|
|
153
|
+
if (currency === "tao") return alphaPriceChange24h;
|
|
154
|
+
if (typeof taoChange24h !== "number" || !Number.isFinite(taoChange24h)) return void 0;
|
|
155
|
+
return ((1 + alphaPriceChange24h / 100) * (1 + taoChange24h / 100) - 1) * 100;
|
|
39
156
|
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
sgd: { name: "Singapore Dollar", symbol: "S$" }
|
|
68
|
-
// twd: { name: "Taiwanese Dollar", symbol: "NT$" },
|
|
157
|
+
/**
|
|
158
|
+
* Rates of a bittensor dtao (subnet alpha) token, derived from its network's native TAO rates
|
|
159
|
+
* scaled by the subnet pool price. To be used for tokens that don't have a coingecko id.
|
|
160
|
+
*
|
|
161
|
+
* @param token
|
|
162
|
+
* @param tokenRates must contain the rates of the network's native (TAO) token
|
|
163
|
+
* @param scaledAlphaPrice current TAO-per-alpha pool price, fixed-point scaled by 10^9 (rao)
|
|
164
|
+
* @param alphaPriceChange24h 24h change of the pool price (alpha vs TAO) in percent, when known
|
|
165
|
+
*/
|
|
166
|
+
const getDTaoTokenRates = (token, tokenRates, scaledAlphaPrice, alphaPriceChange24h) => {
|
|
167
|
+
try {
|
|
168
|
+
const taoTokenRates = tokenRates[(0, _talismn_chaindata_provider.subNativeTokenId)(token.networkId)];
|
|
169
|
+
if (!taoTokenRates) return null;
|
|
170
|
+
if (token.netuid === 0) return structuredClone(taoTokenRates);
|
|
171
|
+
const priceRatio = Number(BigInt(scaledAlphaPrice)) / SCALED_ALPHA_PRICE_SCALE;
|
|
172
|
+
const alphaRates = newTokenRates();
|
|
173
|
+
for (const [currency, taoRate] of Object.entries(taoTokenRates)) if (!taoRate) alphaRates[currency] = null;
|
|
174
|
+
else alphaRates[currency] = {
|
|
175
|
+
price: taoRate.price * priceRatio,
|
|
176
|
+
marketCap: taoRate.marketCap ? taoRate.marketCap * priceRatio : void 0,
|
|
177
|
+
change24h: getAlphaChange24h(currency, taoRate.change24h, alphaPriceChange24h)
|
|
178
|
+
};
|
|
179
|
+
return alphaRates;
|
|
180
|
+
} catch (err) {
|
|
181
|
+
log_default.error("Failed to compute dtao token rates", err);
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
69
184
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/fetchDTaoTokenRates.ts
|
|
187
|
+
const DEFAULT_BITTENSOR_NETWORK_ID = "bittensor";
|
|
188
|
+
const DEFAULT_TAO_DATA_API_URL = "https://tda.talisman.xyz";
|
|
189
|
+
const DEFAULT_TIMEOUT_MS = 1e4;
|
|
190
|
+
const alphaPricesCodec = (0, scale_ts.Vector)((0, scale_ts.Struct)({
|
|
191
|
+
netuid: scale_ts.u16,
|
|
192
|
+
price: scale_ts.u64
|
|
193
|
+
}));
|
|
194
|
+
/** Current TAO-per-alpha pool price of every subnet, keyed by netuid, in the scaledAlphaPrice fixed-point format (rao) */
|
|
195
|
+
const fetchScaledAlphaPricesByNetuid = async (connector, networkId) => {
|
|
196
|
+
const result = await connector.send(networkId, "state_call", ["SwapRuntimeApi_current_alpha_price_all", "0x"]);
|
|
197
|
+
return new Map(alphaPricesCodec.dec(result).map(({ netuid, price }) => [netuid, price]));
|
|
198
|
+
};
|
|
199
|
+
const ALPHA_PRICE_CHANGES_TTL = 5 * 6e4;
|
|
200
|
+
const alphaPriceChangesCache = /* @__PURE__ */ new Map();
|
|
201
|
+
/**
|
|
202
|
+
* 24h percent change of every subnet pool price (alpha vs TAO) from the tao-data api — the
|
|
203
|
+
* chain knows the current pool prices but not yesterday's. 5-min in-memory cache; failure is
|
|
204
|
+
* non-fatal (stale cache when available, else no change24h on the computed rates).
|
|
205
|
+
*/
|
|
206
|
+
const getAlphaPriceChangesByNetuid = async (apiUrl, customFetch, timeoutMs) => {
|
|
207
|
+
const cached = alphaPriceChangesCache.get(apiUrl);
|
|
208
|
+
if (cached && performance.now() - cached.fetchedAt < ALPHA_PRICE_CHANGES_TTL) return cached.changes;
|
|
209
|
+
try {
|
|
210
|
+
const response = await customFetch(`${apiUrl}/pools`, { signal: AbortSignal.timeout(timeoutMs) });
|
|
211
|
+
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
|
|
212
|
+
const pools = await response.json();
|
|
213
|
+
const changes = new Map(pools.map((pool) => [pool.netuid, Number(pool.price_change_1_day)]).filter(([, change]) => Number.isFinite(change)));
|
|
214
|
+
alphaPriceChangesCache.set(apiUrl, {
|
|
215
|
+
fetchedAt: performance.now(),
|
|
216
|
+
changes
|
|
217
|
+
});
|
|
218
|
+
return changes;
|
|
219
|
+
} catch (err) {
|
|
220
|
+
log_default.warn("Failed to fetch alpha price 24h changes", err);
|
|
221
|
+
return cached?.changes ?? null;
|
|
222
|
+
}
|
|
103
223
|
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Rates entries for the bittensor dtao (subnet alpha) tokens of `tokens`, priced from their
|
|
226
|
+
* subnet pool combined with the TAO rates in `tokenRates`. On chain-fetch failure, falls
|
|
227
|
+
* back to the token's entry in `previousRates` (keep-last). Never throws — a dtao pricing
|
|
228
|
+
* failure must not discard the rates list it gets merged into.
|
|
229
|
+
*
|
|
230
|
+
* Hosts remain responsible for WHEN to call this (network enabled state, refresh cadence)
|
|
231
|
+
* and for merging the result into their rates list/store.
|
|
232
|
+
*/
|
|
233
|
+
const fetchDTaoTokenRates = async ({ connector, networkId = DEFAULT_BITTENSOR_NETWORK_ID, tokens, tokenRates, previousRates, customFetch = fetch, taoDataApiUrl = DEFAULT_TAO_DATA_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS }) => {
|
|
234
|
+
const dtaoTokens = Object.values(tokens).filter((token) => token.type === "substrate-dtao" && token.networkId === networkId && !token.coingeckoId);
|
|
235
|
+
if (!dtaoTokens.length) return {};
|
|
236
|
+
if (!tokenRates[(0, _talismn_chaindata_provider.subNativeTokenId)(networkId)]) return {};
|
|
237
|
+
const [prices, changes] = await Promise.all([Promise.race([fetchScaledAlphaPricesByNetuid(connector, networkId), (0, _talismn_util.throwAfter)(timeoutMs, `Timed out after ${timeoutMs}ms`)]).catch((err) => {
|
|
238
|
+
log_default.warn("Failed to fetch alpha prices, keeping previous dtao rates", err);
|
|
239
|
+
return null;
|
|
240
|
+
}), getAlphaPriceChangesByNetuid(taoDataApiUrl, customFetch, timeoutMs)]);
|
|
241
|
+
if (!prices) return Object.fromEntries(dtaoTokens.filter((token) => previousRates[token.id]).map((token) => [token.id, previousRates[token.id]]));
|
|
242
|
+
return Object.fromEntries(dtaoTokens.map((token) => {
|
|
243
|
+
const price = prices.get(token.netuid);
|
|
244
|
+
const rates = price ? getDTaoTokenRates(token, tokenRates, price, changes?.get(token.netuid)) : null;
|
|
245
|
+
return [token.id, rates ?? previousRates[token.id]];
|
|
246
|
+
}).filter(([, rates]) => !!rates));
|
|
107
247
|
};
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/TalismanTokenRatesDatabase.ts
|
|
250
|
+
const tryToDeleteOldTokenRatesDb = () => {
|
|
251
|
+
try {
|
|
252
|
+
indexedDB.deleteDatabase("TalismanTokenRates");
|
|
253
|
+
} catch {}
|
|
254
|
+
};
|
|
255
|
+
//#endregion
|
|
256
|
+
//#region src/TokenRates.ts
|
|
257
|
+
var TokenRatesError = class extends Error {
|
|
258
|
+
response;
|
|
259
|
+
constructor(message, response) {
|
|
260
|
+
super(message);
|
|
261
|
+
this.response = response;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
const ALL_CURRENCY_IDS = Object.keys(SUPPORTED_CURRENCIES);
|
|
265
|
+
const DEFAULT_COINSAPI_CONFIG = { apiUrl: "https://coins.talisman.xyz" };
|
|
108
266
|
async function fetchTokenRates(tokens, currencyIds = ALL_CURRENCY_IDS, config = DEFAULT_COINSAPI_CONFIG) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const ratesList = Object.fromEntries(
|
|
170
|
-
Object.entries(tokens).map(([tokenId, token]) => [
|
|
171
|
-
tokenId,
|
|
172
|
-
token.coingeckoId ? tokenRates[token.coingeckoId] ?? null : null
|
|
173
|
-
])
|
|
174
|
-
);
|
|
175
|
-
return ratesList;
|
|
267
|
+
const coingeckoIdToTokenIds = Object.values(tokens).flatMap((token) => {
|
|
268
|
+
if (token.type === "evm-uniswapv2") {
|
|
269
|
+
if (token.platform !== "ethereum") return [];
|
|
270
|
+
const getToken = (evmNetworkId, tokenAddress, coingeckoId) => ({
|
|
271
|
+
id: (0, _talismn_chaindata_provider.evmErc20TokenId)(evmNetworkId, tokenAddress),
|
|
272
|
+
coingeckoId
|
|
273
|
+
});
|
|
274
|
+
const token0 = token.coingeckoId0 ? [getToken(token.networkId, token.tokenAddress0, token.coingeckoId0)] : [];
|
|
275
|
+
const token1 = token.coingeckoId1 ? [getToken(token.networkId, token.tokenAddress1, token.coingeckoId1)] : [];
|
|
276
|
+
return [...token0, ...token1];
|
|
277
|
+
}
|
|
278
|
+
if (!token.coingeckoId) return [];
|
|
279
|
+
return [{
|
|
280
|
+
id: token.id,
|
|
281
|
+
coingeckoId: token.coingeckoId
|
|
282
|
+
}];
|
|
283
|
+
}).reduce((coingeckoIdToTokenIds, { id, coingeckoId }) => {
|
|
284
|
+
if (!coingeckoIdToTokenIds[coingeckoId]) coingeckoIdToTokenIds[coingeckoId] = [];
|
|
285
|
+
coingeckoIdToTokenIds[coingeckoId].push(id);
|
|
286
|
+
return coingeckoIdToTokenIds;
|
|
287
|
+
}, {});
|
|
288
|
+
const coingeckoIds = Object.keys(coingeckoIdToTokenIds).sort();
|
|
289
|
+
if (coingeckoIds.length < 1) return {};
|
|
290
|
+
const hasVsTao = currencyIds.includes("tao");
|
|
291
|
+
const [effectiveCoingeckoIds, effectiveCurrencyIds] = hasVsTao ? [[...new Set(coingeckoIds).add("bittensor")], [...new Set(currencyIds.filter((c) => c !== "tao")).add("usd")]] : [coingeckoIds, currencyIds];
|
|
292
|
+
const rawTokenRates = await (await fetch(`${config.apiUrl}/token-rates`, {
|
|
293
|
+
method: "POST",
|
|
294
|
+
body: JSON.stringify({
|
|
295
|
+
coingeckoIds: effectiveCoingeckoIds,
|
|
296
|
+
currencyIds: effectiveCurrencyIds
|
|
297
|
+
})
|
|
298
|
+
})).json();
|
|
299
|
+
if (hasVsTao) {
|
|
300
|
+
const effectiveTaoIndex = effectiveCoingeckoIds.indexOf("bittensor");
|
|
301
|
+
const effectiveUsdIndex = effectiveCurrencyIds.indexOf("usd");
|
|
302
|
+
const taoUsdRate = rawTokenRates[effectiveTaoIndex]?.[effectiveUsdIndex]?.[0];
|
|
303
|
+
const taoUsdChange24h = rawTokenRates[effectiveTaoIndex]?.[effectiveUsdIndex]?.[2];
|
|
304
|
+
const taoIndex = currencyIds.indexOf("tao");
|
|
305
|
+
rawTokenRates.forEach((rates, i) => {
|
|
306
|
+
if (i === effectiveTaoIndex) {
|
|
307
|
+
rates?.splice(taoIndex, 0, [
|
|
308
|
+
1,
|
|
309
|
+
null,
|
|
310
|
+
null
|
|
311
|
+
]);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const tokenUsdRate = rates?.[effectiveUsdIndex]?.[0];
|
|
315
|
+
const tokenTaoRate = typeof tokenUsdRate === "number" && typeof taoUsdRate === "number" && taoUsdRate !== 0 ? tokenUsdRate / taoUsdRate : null;
|
|
316
|
+
const tokenUsdChange24h = rates?.[effectiveUsdIndex]?.[2];
|
|
317
|
+
const tokenTaoChange24h = typeof taoUsdChange24h === "number" && typeof tokenUsdChange24h === "number" ? (1 + tokenUsdChange24h) / (1 + taoUsdChange24h) - 1 : null;
|
|
318
|
+
rates?.splice(taoIndex, 0, [
|
|
319
|
+
tokenTaoRate,
|
|
320
|
+
null,
|
|
321
|
+
tokenTaoChange24h
|
|
322
|
+
]);
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
const tokenRates = parseTokenRatesFromApi(rawTokenRates, coingeckoIds, currencyIds);
|
|
326
|
+
return Object.fromEntries(Object.entries(tokens).map(([tokenId, token]) => [tokenId, token.coingeckoId ? tokenRates[token.coingeckoId] ?? null : null]));
|
|
176
327
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
)
|
|
192
|
-
];
|
|
193
|
-
})
|
|
194
|
-
);
|
|
328
|
+
const parseTokenRatesFromApi = (rawTokenRates, coingeckoIds, currencyIds) => {
|
|
329
|
+
return Object.fromEntries(coingeckoIds.map((coingeckoId, idx) => {
|
|
330
|
+
const rates = rawTokenRates[idx];
|
|
331
|
+
if (!rates) return [coingeckoId, null];
|
|
332
|
+
return [coingeckoId, Object.fromEntries(currencyIds.map((currencyId, idx) => {
|
|
333
|
+
if (!rates[idx]) return [currencyId, null];
|
|
334
|
+
const [price, marketCap, change24h] = rates[idx];
|
|
335
|
+
return [currencyId, {
|
|
336
|
+
price,
|
|
337
|
+
marketCap,
|
|
338
|
+
change24h
|
|
339
|
+
}];
|
|
340
|
+
}))];
|
|
341
|
+
}));
|
|
195
342
|
};
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
343
|
+
//#endregion
|
|
344
|
+
exports.ALL_CURRENCY_IDS = ALL_CURRENCY_IDS;
|
|
345
|
+
exports.DEFAULT_COINSAPI_CONFIG = DEFAULT_COINSAPI_CONFIG;
|
|
346
|
+
exports.SUPPORTED_CURRENCIES = SUPPORTED_CURRENCIES;
|
|
347
|
+
exports.TokenRatesError = TokenRatesError;
|
|
348
|
+
exports.fetchDTaoTokenRates = fetchDTaoTokenRates;
|
|
349
|
+
exports.fetchTokenRates = fetchTokenRates;
|
|
350
|
+
exports.getDTaoTokenRates = getDTaoTokenRates;
|
|
351
|
+
exports.newTokenRates = newTokenRates;
|
|
352
|
+
exports.tryToDeleteOldTokenRatesDb = tryToDeleteOldTokenRatesDb;
|
|
353
|
+
|
|
206
354
|
//# sourceMappingURL=index.js.map
|