fix: wallet x-ray RPC failover with 5 endpoints (Alchemy, PublicNode, Ankr, Solana, Helius)
This commit is contained in:
parent
660bb842ec
commit
f484cf94b1
1 changed files with 28 additions and 12 deletions
|
|
@ -6,8 +6,13 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// ── Config ──
|
// ── Config ──
|
||||||
const RPC = 'https://api.mainnet-beta.solana.com';
|
const RPC_ENDPOINTS = [
|
||||||
const RPC_BACKUP = 'https://rpc.ankr.com/solana';
|
'https://solana-mainnet.g.alchemy.com/v2/demo',
|
||||||
|
'https://solana.publicnode.com',
|
||||||
|
'https://rpc.ankr.com/solana',
|
||||||
|
'https://api.mainnet-beta.solana.com',
|
||||||
|
'https://mainnet.helius-rpc.com/?api-key=1d8740dc-e5f4-421c-b823-e1bad1889eff'
|
||||||
|
];
|
||||||
const JUP_PRICE = 'https://price.jup.ag/v6/price';
|
const JUP_PRICE = 'https://price.jup.ag/v6/price';
|
||||||
const JUP_TOKEN_LIST = 'https://token.jup.ag/all';
|
const JUP_TOKEN_LIST = 'https://token.jup.ag/all';
|
||||||
const SOLSCAN_TX = 'https://solscan.io/tx/';
|
const SOLSCAN_TX = 'https://solscan.io/tx/';
|
||||||
|
|
@ -30,7 +35,8 @@
|
||||||
// ── State ──
|
// ── State ──
|
||||||
let tokenListCache = null;
|
let tokenListCache = null;
|
||||||
let tokenMapCache = null; // mint → {name, symbol, logoURI, decimals}
|
let tokenMapCache = null; // mint → {name, symbol, logoURI, decimals}
|
||||||
let activeRpc = RPC;
|
let activeRpc = RPC_ENDPOINTS[0];
|
||||||
|
let rpcIndex = 0;
|
||||||
let scanning = false;
|
let scanning = false;
|
||||||
|
|
||||||
// ── Helpers ──
|
// ── Helpers ──
|
||||||
|
|
@ -104,34 +110,44 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── RPC Call ──
|
// ── RPC Call ──
|
||||||
async function rpc(method, params, retries = 2) {
|
async function rpc(method, params, retries = 4) {
|
||||||
|
let lastError;
|
||||||
for (let i = 0; i <= retries; i++) {
|
for (let i = 0; i <= retries; i++) {
|
||||||
|
const url = RPC_ENDPOINTS[(rpcIndex + i) % RPC_ENDPOINTS.length];
|
||||||
try {
|
try {
|
||||||
const url = i === 0 ? activeRpc : RPC_BACKUP;
|
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params })
|
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params })
|
||||||
});
|
});
|
||||||
if (res.status === 429) {
|
if (res.status === 429 || res.status === 403) {
|
||||||
await sleep(1000 * (i + 1));
|
lastError = new Error('Rate limited (HTTP ' + res.status + ')');
|
||||||
|
await sleep(800 * (i + 1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!res.ok) {
|
||||||
|
lastError = new Error('HTTP ' + res.status);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (json.error) {
|
if (json.error) {
|
||||||
if (json.error.code === -32429 || json.error.message?.includes('rate')) {
|
if (json.error.code === -32429 || (json.error.message && json.error.message.includes('rate'))) {
|
||||||
await sleep(1000 * (i + 1));
|
lastError = new Error(json.error.message);
|
||||||
|
await sleep(800 * (i + 1));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
throw new Error(json.error.message || 'RPC error');
|
throw new Error(json.error.message || 'RPC error');
|
||||||
}
|
}
|
||||||
|
// Success — remember this working RPC
|
||||||
|
rpcIndex = (rpcIndex + i) % RPC_ENDPOINTS.length;
|
||||||
|
activeRpc = RPC_ENDPOINTS[rpcIndex];
|
||||||
return json.result;
|
return json.result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (i === retries) throw e;
|
lastError = e;
|
||||||
activeRpc = RPC_BACKUP;
|
if (i < retries) await sleep(500);
|
||||||
await sleep(500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw lastError || new Error('All RPC endpoints failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
|
function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue