← back to Ken
kalshi-dash/src/setup/steps/TestConnection.jsx
92 lines
import React, { useState, useEffect } from 'react';
import { post } from '../../api';
export default function TestConnection({ data, update, next, back }) {
const [exchangeTest, setExchangeTest] = useState(null);
const [authTest, setAuthTest] = useState(null);
const [exLoading, setExLoading] = useState(true);
const [authLoading, setAuthLoading] = useState(false);
useEffect(() => { runExchangeTest(); }, []);
async function runExchangeTest() {
setExLoading(true);
try {
const r = await post('/kalshi', { action: 'test_connection' });
setExchangeTest(r);
if (r.success && data.keys && !data.skippedConnect) runAuthTest();
} catch { setExchangeTest({ error: true }); }
setExLoading(false);
}
async function runAuthTest() {
setAuthLoading(true);
try {
const r = await post('/kalshi', { action: 'get_balance' });
setAuthTest(r);
if (r.success) update({ connectionOk: true });
} catch { setAuthTest({ error: true }); }
setAuthLoading(false);
}
const skipped = data.skippedConnect;
const TestCard = ({ title, loading, result, skippedMsg }) => (
<div className="card">
<div className="flex items-center gap-2 mb-3">
{skippedMsg ? (
<div className="w-5 h-5 rounded-full bg-yellow-500 flex items-center justify-center"><span className="text-white text-xs font-bold">—</span></div>
) : loading ? (
<div className="animate-spin w-5 h-5 border-2 border-amber-500 border-t-transparent rounded-full" />
) : result?.success ? (
<div className="w-5 h-5 rounded-full bg-green-500 flex items-center justify-center">
<svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" strokeWidth="3" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" /></svg>
</div>
) : result?.error ? (
<div className="w-5 h-5 rounded-full bg-red-500 flex items-center justify-center">
<svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" strokeWidth="3" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" /></svg>
</div>
) : <div className="w-5 h-5 rounded-full bg-gray-600" />}
<h3 className="font-semibold text-sm">{title}</h3>
</div>
{skippedMsg ? (
<p className="text-xs text-yellow-400">{skippedMsg}</p>
) : result?.success ? (
<div className="space-y-1 text-xs text-gray-400">
{result.exchange_status && <p>Exchange: <span className="text-green-400 font-mono">{result.exchange_status}</span></p>}
{result.balance !== undefined && <p>Balance: <span className="text-green-400 font-mono">${(result.balance / 100).toFixed(2)}</span></p>}
{result.env && <p>Env: <span className="text-amber-400 font-mono">{result.env.toUpperCase()}</span></p>}
</div>
) : result?.error ? (
<p className="text-xs text-red-400">{typeof result.error === 'string' ? result.error : 'Connection failed'}</p>
) : null}
</div>
);
return (
<div className="space-y-6">
<div className="text-center">
<h2 className="text-2xl font-bold mb-2">Let's See If This Thing Works</h2>
<p className="text-gray-400 text-sm">I'm checking your wiring. Hold your horses.</p>
</div>
<div className="grid grid-cols-2 gap-4">
<TestCard title="Is Ken Even Open?" loading={exLoading} result={exchangeTest} />
<TestCard title="Do They Know Who You Are?" loading={authLoading} result={authTest}
skippedMsg={skipped ? 'You skipped this — playing pretend, remember?' : (!data.keys ? 'No keys, no entry. What did you expect?' : null)} />
</div>
{!exLoading && !authLoading && (
<div className="flex justify-center">
<button onClick={runExchangeTest} className="text-xs text-gray-500 hover:text-gray-300">Try again, maybe this time it'll listen</button>
</div>
)}
<div className="flex items-center justify-between">
<button onClick={back} className="text-sm text-gray-500 hover:text-gray-300">Back</button>
<button onClick={next} className="btn btn-p">Continue</button>
</div>
</div>
);
}