import { resolveShineServerByServerLogin } from './shine-server-resolver.js'; import { SOLANA_ENDPOINT_DEFAULT } from '../solana-programs.js'; function normalizeUrl(value) { return String(value || '').trim(); } function normalizeShineWsUrl(rawUrl) { const value = normalizeUrl(rawUrl); if (!value) return ''; if (value.startsWith('ws://') || value.startsWith('wss://')) { try { const parsed = new URL(value); if (!parsed.pathname || parsed.pathname === '/') parsed.pathname = '/ws'; return parsed.toString(); } catch { return value; } } if (value.startsWith('http://') || value.startsWith('https://')) { try { const parsed = new URL(value); parsed.protocol = parsed.protocol === 'https:' ? 'wss:' : 'ws:'; if (!parsed.pathname || parsed.pathname === '/') parsed.pathname = '/ws'; return parsed.toString(); } catch { return `${value.replace(/^http/, 'ws').replace(/\/$/, '')}/ws`; } } return value; } async function checkSolanaRpc(url) { const endpoint = normalizeUrl(url); if (!endpoint) return false; try { const resp = await fetch(endpoint, { method: 'POST', cache: 'no-store', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'getVersion', }), }); if (!resp.ok) return false; const json = await resp.json(); return Boolean(json?.result?.['solana-core'] || json?.result); } catch { return false; } } async function checkArweave(url) { const base = normalizeUrl(url).replace(/\/+$/, ''); if (!base) return false; try { const resp = await fetch(`${base}/info`, { method: 'GET', cache: 'no-store' }); if (!resp.ok) return false; const json = await resp.json(); return Boolean(json?.network); } catch { return false; } } function checkShineWs(url, timeoutMs = 7000) { const wsUrl = normalizeShineWsUrl(url); if (!wsUrl) return Promise.resolve(false); return new Promise((resolve) => { let done = false; const finish = (ok) => { if (done) return; done = true; window.clearTimeout(timer); try { ws.close(); } catch {} resolve(Boolean(ok)); }; const timer = window.setTimeout(() => finish(false), timeoutMs); let ws; try { ws = new WebSocket(wsUrl); } catch { finish(false); return; } ws.addEventListener('open', () => { try { ws.send(JSON.stringify({ op: 'Ping', requestId: `check-${Date.now()}`, payload: { ts: Date.now() }, })); } catch { finish(false); } }, { once: true }); ws.addEventListener('message', () => finish(true), { once: true }); ws.addEventListener('error', () => finish(false), { once: true }); ws.addEventListener('close', () => finish(false), { once: true }); }); } export async function resolveAndCheckShineServerLogin(serverLogin, solanaEndpoint) { const resolved = await resolveShineServerByServerLogin({ serverLogin, solanaEndpoint, }); const available = await checkShineWs(resolved.wsUrl); return { status: available ? 'available' : 'unavailable', serverLogin: resolved.serverLogin, serverAddress: resolved.serverAddress, httpBase: resolved.httpBase, wsUrl: resolved.wsUrl, }; } export async function checkServerAvailabilityByKey(key, url) { if (key === 'solanaServer') { return (await checkSolanaRpc(url)) ? 'available' : 'unavailable'; } if (key === 'shineServerLogin') { return (await resolveAndCheckShineServerLogin(url, SOLANA_ENDPOINT_DEFAULT)).status; } if (key === 'shineServer') { return (await checkShineWs(url)) ? 'available' : 'unavailable'; } if (key === 'arweaveServer') { return (await checkArweave(url)) ? 'available' : 'unavailable'; } return 'unavailable'; }