|
import * as web3 from "npm:@solana/web3.js"; |
|
|
|
const MAINNET = "https://api.mainnet-beta.solana.com"; |
|
const CSV_FILE_NAME = "rpc-nodes.csv"; |
|
|
|
const connection = new web3.Connection(MAINNET); |
|
const cluster_nodes = await connection.getClusterNodes(); |
|
const nodes_with_rpc = cluster_nodes.filter((node) => !!node.rpc); |
|
nodes_with_rpc.push({ rpc: MAINNET } as web3.ContactInfo); |
|
|
|
console.log("> Found", nodes_with_rpc.length, "nodes with RPC"); |
|
|
|
const data: Array<[string, number]> = []; |
|
|
|
function withTimeout<T>(promise: Promise<T>, timeout = 30_000): Promise<T> { |
|
return new Promise((resolve, reject) => { |
|
const timer = setTimeout(() => { |
|
reject(new Error("сonnection timeout exceeded")); |
|
}, timeout); |
|
|
|
promise.then(resolve, reject).finally(() => clearTimeout(timer)); |
|
}); |
|
} |
|
|
|
await Promise.all( |
|
nodes_with_rpc.map(async (node, i) => { |
|
try { |
|
console.log(`> Connecting to node ${i + 1}/${nodes_with_rpc.length}`); |
|
|
|
const rpc_url = node.rpc?.startsWith("http") |
|
? node.rpc |
|
: `http://${node.rpc}`; |
|
|
|
const rpc_connection = new web3.Connection(rpc_url); |
|
const first_available_block = await withTimeout( |
|
rpc_connection.getFirstAvailableBlock() |
|
); |
|
|
|
data.push([rpc_url, first_available_block]); |
|
} catch (e) { |
|
console.error("> Error:", node.rpc, '|', (e as Error).message); |
|
} |
|
}) |
|
); |
|
|
|
console.log("> Active nodes with RPC:", data.length); |
|
|
|
const CSV_HEADERS = ["rpc_url", "first_available_block"]; |
|
const CSV_DATA = [ |
|
CSV_HEADERS.join(","), |
|
...data |
|
.sort((a, b) => Number(a[1]) - Number(b[1])) |
|
.map((row) => row.join(",")), |
|
]; |
|
|
|
Deno.writeTextFile(CSV_FILE_NAME, CSV_DATA.join("\n")); |
|
console.log(`> Saved to ${CSV_FILE_NAME}`); |