xcaDocs
Guías

Escanear un token y esperar

Inicia un escaneo, consulta con moderación y obtén el reporte terminado.

El flujo más común: obtienes una dirección de contrato de algún lado y necesitas su Holder Score antes de actuar. Inicia un escaneo y luego consulta el reporte con una espera cada vez mayor hasta que esté listo.

  • POST /scans responde de inmediato; el escaneo se ejecuta en segundo plano.
  • Aumenta la espera entre consultas y respeta retryAfter ante un 429.
  • Detente en DONE o ERROR, o cuando se cumpla tu propio tiempo límite.

Código#

const BASE = "https://app.xca.fun/api/v1";
const headers = {
  Authorization: `Bearer ${process.env.XCA_API_KEY}`,
  "Content-Type": "application/json",
};
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function scanAndWait(address, { timeoutMs = 180_000 } = {}) {
  const start = await fetch(`${BASE}/scans`, {
    method: "POST",
    headers,
    body: JSON.stringify({ chain: "solana", address }),
  });
  if (!start.ok) throw new Error((await start.json()).error.message);

  const deadline = Date.now() + timeoutMs;
  let delay = 2000;
  while (Date.now() < deadline) {
    const res = await fetch(`${BASE}/tokens/solana/${address}`, { headers });
    if (res.status === 429) {
      const { error } = await res.json();
      await sleep((error.retryAfter ?? 5) * 1000);
      continue;
    }
    const report = await res.json();
    if (report.status === "DONE") return report;
    if (report.status === "ERROR") throw new Error(report.errorMessage ?? "Scan failed");
    console.log(`${report.step ?? "queued"} ${report.progress}%`);
    await sleep(delay);
    delay = Math.min(delay * 1.5, 8000);
  }
  throw new Error("Timed out waiting for the scan");
}

const report = await scanAndWait("DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263");
console.log(report.symbol, report.holderScore, report.riskLevel);