-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
125 lines (111 loc) · 3.62 KB
/
index.js
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
const axios = require("axios");
const https = require("https");
const fs = require("fs");
const CancelToken = axios.CancelToken;
async function getRpcLatency(url) {
const start = Date.now();
try {
const source = CancelToken.source();
setTimeout(() => {
source.cancel(`Request to ${url} timed out`);
}, 10000); // 10 seconds timeout
await axios.post(
url,
{},
{
timeout: 3000,
httpsAgent: new https.Agent({ keepAlive: true }),
cancelToken: source.token,
}
);
const latency = Date.now() - start;
return { url, latency };
} catch (error) {
if (axios.isCancel(error)) {
console.log("Request canceled:", error.message);
}
// console.error({ error });
return { url, latency: Infinity };
}
}
async function processBatch(rpcs) {
const results = [];
for (const rpc of rpcs) {
const result = await getRpcLatency(rpc);
results.push(result);
}
const filtered = results.filter((result) => result.latency !== Infinity);
const sorted = filtered.sort((a, b) => a.latency - b.latency);
return sorted.map((result) => result.url);
}
async function sortAndFilterRpcs(rpcs) {
const batchSize = 5;
const batches = [];
for (let i = 0; i < rpcs.length; i += batchSize) {
batches.push(rpcs.slice(i, i + batchSize));
}
const sortedRpcs = [];
for (const batch of batches) {
const sortedBatch = await processBatch(batch);
sortedRpcs.push(...sortedBatch);
}
return sortedRpcs;
}
async function processRpcs() {
try {
const response = await axios.get(
"https://raw.githubusercontent.com/DefiLlama/chainlist/main/constants/extraRpcs.js"
);
const regex = /export const extraRpcs = ({[\s\S]*?});\s*$/gm;
const matches = regex.exec(response.data);
const extractedRpcsString = matches[0];
const cleanedString = extractedRpcsString
.replace("export const extraRpcs = ", "")
.replace(/^[ \t]*.*tracking.*\n/gm, "")
.replaceAll("${INFURA_API_KEY}", "");
let rpcObject = {};
eval(`rpcObject = ${cleanedString}`);
const finalSortedRpcs = {};
const networkIds = Object.keys(rpcObject);
for (let i = 0; i < networkIds.length; i++) {
const networkId = networkIds[i];
const rpcs = rpcObject[networkId].rpcs.map((rpc) =>
typeof rpc === "object" ? rpc.url : rpc
);
console.log("Processing RPCs for network:", networkId);
const sortedRpcList = await sortAndFilterRpcs(rpcs);
// console.log({ sortedRpcList, rpcs });
finalSortedRpcs[networkId] = sortedRpcList;
}
try {
// overrides rpc
const overrides = fs.readFileSync("overrides.json", "utf8");
const overridesObject = JSON.parse(overrides);
const networkIdsOverrides = Object.keys(overridesObject);
for (let i = 0; i < networkIdsOverrides.length; i++) {
const networkId = networkIdsOverrides[i];
const rpcs = overridesObject[networkId];
console.log("Processing RPCs for network:", networkId);
finalSortedRpcs[networkId] = [
...rpcs,
...(finalSortedRpcs[networkId] || []),
];
}
} catch (error) {
console.error("Failed to load overrides.json file");
}
const jsonString = JSON.stringify(finalSortedRpcs, null, 2);
fs.writeFile("export.json", jsonString, "utf8", (error) => {
if (error) {
console.error("Failed to write file:", error);
} else {
console.log("Data written to export.json");
}
});
} catch (error) {
console.error(error);
throw new Error("Failed to process RPCs");
}
}
// Call the function to start processing
processRpcs();