-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.js
More file actions
executable file
·84 lines (67 loc) · 2.52 KB
/
main.js
File metadata and controls
executable file
·84 lines (67 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
const tallyTvl = require('./utils/tallyTvl');
const main = (req, client, fetchCoinGeckoPrices, fetchCachedToken) => {
return new Promise(async (resolve, reject) => {
try {
const tokenVolumesRaw = req.body.tokenVolumes;
const network = req.body.network;
var key, keys = Object.keys(tokenVolumesRaw);
var n = keys.length;
var tokenVolumes = {};
const tokenDecimals = {}
while (n--) {
key = keys[n];
tokenVolumes[key.toLocaleLowerCase()] = tokenVolumesRaw[key].volume;
tokenDecimals[key.toLocaleLowerCase()] = tokenVolumesRaw[key].decimals;
}
if (Object.keys(tokenVolumes).length == 0) {
return reject({ error: 'missing tokens' });
}
const tokenAddresses = Object.keys(tokenVolumes);
if (!Array.isArray(tokenAddresses) || tokenAddresses.length === 0) {
return reject({ error: 'token must not be empty' });
}
// Fetch any token price you can from cache
let remainingTokens = [];
let cachedTokenPrices = {};
await Promise.all(
tokenAddresses.map(async (tokenAddress) => {
const price = await fetchCachedToken(client, tokenAddress);
// price will be null if there's an error or cache miss
if (price != null) {
cachedTokenPrices[tokenAddress] = {};
// For later merging with fetched token prices, we must reflect CoinGeckos return object
cachedTokenPrices[tokenAddress]['usd'] = price;
} else {
remainingTokens.push(tokenAddress);
}
})
);
// For the remaining tokens which were not in cache, fetch them all with a single call
const fetchedTokenPrices = await fetchCoinGeckoPrices(
client,
remainingTokens,
network
);
// Merge the cached and fetched token prices into a single object
const tokenPriceMap = Object.assign(cachedTokenPrices, fetchedTokenPrices);
// Now multiply each token's USD value by the volume of that token
let usdValuePerCoin = {};
let individualTokenPrices = {};
for (const [key, value] of Object.entries(tokenPriceMap)) {
let decimals = tokenDecimals[key];
const multiplier = tokenVolumes[key] / Math.pow(10, decimals);
usdValuePerCoin[key] = value.usd * multiplier;
individualTokenPrices[key] = Math.round(parseFloat(value.usd) * 100) / 100;
}
// Prepare the result object for return
let result = {};
result['tokenPrices'] = individualTokenPrices;
result['tokens'] = usdValuePerCoin;
result['total'] = tallyTvl(usdValuePerCoin);
return resolve(result);
} catch (error) {
return reject(error);
}
});
};
module.exports = main;