Connector Open-Source Code

Browse connector files locally. Exchange API keys stay on your device.

ui/diagnostics.php

<?php
// /opt/nuxvision_connector/ui/diagnostics.php
declare(strict_types=1);

require_once __DIR__ . '/common.php';

function diag_bool_icon(bool $ok): string {
    return $ok
        ? '<span class="text-success"><i class="bi bi-check-circle-fill me-1"></i>OK</span>'
        : '<span class="text-danger"><i class="bi bi-x-circle-fill me-1"></i>FAIL</span>';
}

function diag_card(string $title, bool $ok, string $bodyHtml): void {
    ?>
    <div class="nv-card p-4 mb-3">
      <div class="d-flex align-items-center justify-content-between mb-2">
        <div class="h5 fw-bold m-0"><?=h($title)?></div>
        <div><?=diag_bool_icon($ok)?></div>
      </div>
      <div class="nv-muted2 small"><?= $bodyHtml ?></div>
    </div>
    <?php
}

function http_probe(string $url, int $timeout = 6): array {
    [$code, $err, $body, $json] = curl_json($url, [], $timeout);
    $ok = ($err === '' && $code >= 200 && $code < 400);
    return [
        'ok'=>$ok,
        'http'=>$code,
        'err'=>$err,
        'raw'=>is_string($body)?substr($body,0,200):null,
        'json'=>$json
    ];
}

/**
 * Normalize a base url:
 * - if already ends with /api/v<number>, keep it
 * - otherwise append /api/v1
 */
function nv_normalize_base(string $base): string {
    $base = rtrim(trim($base), '/');
    if ($base === '') return '';
    if (preg_match('~/api/v\d+$~', $base)) return $base;
    return $base . '/api/v1';
}

function nv_call_get(string $nvBase, string $nvKey, string $path, array $query, int $timeout): array {
    $nvBase = nv_normalize_base($nvBase);
    $url = $nvBase . '/' . ltrim($path, '/');
    if ($query) $url .= '?' . http_build_query($query);

    [$code, $err, $body, $json] = curl_json($url, nv_auth_headers($nvKey), $timeout);

    $ok = ($err === '' && $code >= 200 && $code < 400 && is_array($json));
    return [
        'ok' => $ok,
        'http' => $code,
        'err' => $err,
        'raw' => is_string($body) ? substr($body, 0, 200) : null,
        'json' => $json,
        'url' => $url,
    ];
}

/* -------------------- Choose instance_id -------------------- */
$instanceId = to_int($_GET['instance_id'] ?? 0, 0);
if ($instanceId <= 0) {
    $sid = nv_instance_id_from_session();
    if ($sid > 0) $instanceId = $sid;
}

/* -------------------- Load config (prefer local instance config) -------------------- */
$wiz = wiz_get();

$nv_base = '';
$nv_key  = '';
$nv_to   = 6;
$ex_name = 'bitkub';
$ex_key  = '';
$ex_sec  = '';

$cfgPath = '';
if ($instanceId > 0) {
    $cfgPath = nv_instance_config_path($instanceId);
    if (is_file($cfgPath)) {
        $cfg = @require $cfgPath;
        if (is_array($cfg)) {
            $nv_base = trim((string)($cfg['nuxvision']['base_url'] ?? ''));
            $nv_key  = trim((string)($cfg['nuxvision']['api_key'] ?? ''));
            $nv_to   = to_int($cfg['nuxvision']['timeout'] ?? 6, 6);
            $ex_name = (string)($cfg['exchange']['name'] ?? $ex_name);
            $ex_key  = trim((string)($cfg['exchange']['api_key'] ?? ''));
            $ex_sec  = trim((string)($cfg['exchange']['api_secret'] ?? ''));
        }
    }
}

/* fallback to wizard session if missing */
if ($nv_base === '') $nv_base = trim((string)v($wiz, 'nuxvision.base_url', ''));
if ($nv_key === '')  $nv_key  = trim((string)v($wiz, 'nuxvision.api_key', ''));
$tmpInst = to_int(v($wiz, 'nuxvision.instance_id', 0), 0);
if ($instanceId <= 0 && $tmpInst > 0) $instanceId = $tmpInst;
$nv_to = to_int($nv_to, 6);
if ($nv_to < 2 || $nv_to > 30) $nv_to = 6;

if ($ex_name === '' || $ex_name === '0') $ex_name = (string)v($wiz, 'exchange.name', $ex_name);
if ($ex_key === '') $ex_key = trim((string)v($wiz, 'exchange.api_key', ''));
if ($ex_sec === '') $ex_sec = trim((string)v($wiz, 'exchange.api_secret', ''));

render_header('NuxVision Connector', 'Diagnostics', false);
render_flash();
?>

<div class="row g-3">
  <div class="col-lg-8">
    <div class="nv-card p-4 mb-3">
      <div class="h4 fw-bold mb-1">Diagnostics</div>
      <div class="nv-muted mb-2">Quick checks for connectivity and runtime configuration.</div>
      <div class="smallhint">
        Tip: if something fails, check DNS, firewall, or server time (TLS can fail when clock is wrong).
      </div>
    </div>

<?php
// 1) Internet probe
$internet = http_probe('https://www.google.com/generate_204', 6);
$internetOk = !empty($internet['ok']);

diag_card(
    'Internet connectivity',
    $internetOk,
    'HTTP: <span class="mono">'.h((string)$internet['http']).'</span>'
    .($internet['err'] ? ' • Error: <span class="mono">'.h((string)$internet['err']).'</span>' : '')
);

// 2) NuxVision probe (heartbeat + instance_settings)
$nvOk = false;
$nvBody = '';

if ($nv_base === '' || !is_valid_url($nv_base)) {
    $nvBody = 'Invalid base URL: <span class="mono">'.h($nv_base ?: '—').'</span>';
} elseif ($nv_key === '') {
    $nvBody = 'Missing API key (from local instance config or wizard session).';
} elseif ($instanceId <= 0) {
    $nvBody = 'Missing instance_id (add <span class="mono">?instance_id=1</span> or select an instance in UI).';
} else {
    $hb = nv_call_get($nv_base, $nv_key, 'heartbeat.php', ['instance_id' => $instanceId], $nv_to);
    $hbOk = !empty($hb['ok']) && !empty($hb['json']) && (!empty($hb['json']['ok']) || (($hb['json']['status'] ?? '') === 'ok'));

    $nvBody .= 'Base: <span class="mono">'.h(nv_normalize_base($nv_base)).'</span>';
    $nvBody .= '<br>Heartbeat URL: <span class="mono">'.h((string)$hb['url']).'</span>';
    $nvBody .= '<br>Heartbeat: '.($hbOk ? '<span class="text-success">OK</span>' : '<span class="text-danger">FAIL</span>')
             .' • HTTP <span class="mono">'.h((string)($hb['http'] ?? 0)).'</span>';

    if (!$hbOk) {
        if (!empty($hb['err'])) $nvBody .= '<br>Error: <span class="mono">'.h((string)$hb['err']).'</span>';
        if (!empty($hb['raw'])) $nvBody .= '<br>Raw: <span class="mono">'.h((string)$hb['raw']).'</span>';
    }

    // settings endpoint = validates “config fetched from NuxVision”
    $st = nv_call_get($nv_base, $nv_key, 'instance_settings.php', ['instance_id' => $instanceId], $nv_to);
    $stOk = !empty($st['ok']) && !empty($st['json']) && !empty($st['json']['ok']) && is_array($st['json']['settings'] ?? null);

    $nvBody .= '<br><br>Settings URL: <span class="mono">'.h((string)$st['url']).'</span>';
    $nvBody .= '<br>Instance settings: '.($stOk ? '<span class="text-success">OK</span>' : '<span class="text-danger">FAIL</span>')
             .' • HTTP <span class="mono">'.h((string)($st['http'] ?? 0)).'</span>';

    if ($stOk) {
        $count = count((array)($st['json']['settings'] ?? []));
        $nvBody .= ' • keys=<span class="mono">'.h((string)$count).'</span>';
        $nvOk = true; // we consider NV OK when settings works
    } else {
        if (!empty($st['err'])) $nvBody .= '<br>Error: <span class="mono">'.h((string)$st['err']).'</span>';
        if (!empty($st['raw'])) $nvBody .= '<br>Raw: <span class="mono">'.h((string)$st['raw']).'</span>';
        $nvOk = false;
    }
}

diag_card('NuxVision API', $nvOk, $nvBody);

// 3) Exchange probe (public only)
$exOk = false;
$exBody = 'Exchange: <span class="mono">'.h($ex_name ?: '—').'</span>';

if (strtolower($ex_name) !== 'bitkub') {
    $exBody .= '<br>Public probe not implemented for this exchange.';
} else {
    $pub = http_probe('https://api.bitkub.com/api/v3/servertime', 6);
    $pubOk = !empty($pub['ok']);
    $exBody .= '<br>Public servertime: '.($pubOk ? '<span class="text-success">OK</span>' : '<span class="text-danger">FAIL</span>')
             .' • HTTP <span class="mono">'.h((string)$pub['http']).'</span>';

    if ($ex_key === '' || $ex_sec === '') {
        $exBody .= '<br>Private test skipped: missing API key/secret (local config or wizard session).';
    } else {
        $exBody .= '<br>Private test: skipped in UI (runner validates during runtime).';
    }

    $exOk = $pubOk;
}

diag_card('Exchange API', $exOk, $exBody);
?>

    <div class="d-flex gap-2 mt-2">
      <a class="btn btn-soft" href="./index.php"><i class="bi bi-house me-1"></i>Home</a>
      <?php if ($instanceId > 0): ?>
        <a class="btn btn-soft" href="./diagnostics.php?instance_id=<?=h((string)$instanceId)?>">
          <i class="bi bi-arrow-clockwise me-1"></i>Refresh
        </a>
      <?php endif; ?>
    </div>
  </div>

  <div class="col-lg-4">
    <div class="nv-card p-4">
      <div class="h5 fw-bold mb-2">Current config</div>
      <div class="smallhint mb-2">Prefer local instance config; fallback to wizard session.</div>

      <div class="smallhint mb-2">
        Instance ID<br>
        <span class="mono"><?=h((string)$instanceId ?: '—')?></span>
      </div>

      <div class="smallhint mb-2">
        Config file<br>
        <span class="mono"><?=h($cfgPath ?: '—')?></span>
      </div>

      <div class="smallhint mb-2">
        NuxVision base URL<br>
        <span class="mono"><?=h($nv_base ?: '—')?></span>
      </div>

      <div class="smallhint mb-2">
        Normalized base<br>
        <span class="mono"><?=h($nv_base ? nv_normalize_base($nv_base) : '—')?></span>
      </div>

      <div class="smallhint mb-2">
        Exchange<br>
        <span class="mono"><?=h($ex_name ?: '—')?></span>
      </div>
    </div>
  </div>
</div>

<?php
render_footer();