import { useState, useEffect } from 'react';
import { usePrivy } from '@privy-io/react-auth';
import PrivyAccount from '../components/PrivyAccount';
import { readPusdBalance } from '../utils/dwApprovals';
import { useT } from '../i18n/LanguageContext';
import '../redesign/editorial.css';
/**
* Dedicated wallet page (funding view): a balance summary + deposit / withdraw / wallet setup,
* reached from the header balance chip. Trading positions & P&L stay on the Portfolio page.
* Wraps the existing PrivyAccount block (deposit/withdraw/approvals/delegate) unchanged.
*/
export default function WalletPage() {
const { t } = useT();
const { authenticated, getAccessToken } = usePrivy();
const [cashRaw, setCash] = useState<number | null>(null);
const [posRaw, setPosValue] = useState<number | null>(null);
// Derived: null when logged out (no synchronous reset inside the effect).
const cash = authenticated ? cashRaw : null;
const posValue = authenticated ? posRaw : null;
// Available = free pUSD cash; In positions = live mark-to-market of open copies (Data API).
useEffect(() => {
if (!authenticated) return;
let alive = true;
const load = async () => {
try {
const token = await getAccessToken();
if (!token) return;
const r = await fetch('/api/copy/wallet', { headers: { authorization: `Bearer ${token}` } });
const dw = (await r.json())?.data?.depositWallet;
if (!dw) { if (alive) { setCash(null); setPosValue(null); } return; }
const bal = await readPusdBalance(dw);
if (alive) setCash(Number(bal) / 1e6);
try {
const v = await fetch(`https://data-api.polymarket.com/value?user=${dw}`);
const d = await v.json();
const val = Array.isArray(d) ? Number(d[0]?.value) : Number(d?.value);
if (alive) setPosValue(Number.isFinite(val) ? val : 0);
} catch { if (alive) setPosValue(0); }
} catch { /* leave last-known */ }
};
load();
const id = setInterval(load, 30000);
return () => { alive = false; clearInterval(id); };
}, [authenticated, getAccessToken]);
const fmt = (n: number | null) => n == null ? '—' : `$${n.toFixed(2)}`;
const total = cash != null && posValue != null ? cash + posValue : null;
return (
<div className="more-page pk-more pk-wallet">
<h2 className="more-title">{t('nav.wallet')}</h2>
{authenticated && (cash != null || posValue != null) && (
<div className="wallet-summary" style={{ display: 'flex', gap: 8, margin: '0 0 14px' }}>
{[
{ k: 'wallet.available', v: fmt(cash), strong: true },
{ k: 'wallet.inPositions', v: fmt(posValue) },
{ k: 'wallet.total', v: fmt(total) },
].map(({ k, v, strong }) => (
<div key={k} style={{ flex: 1, background: 'var(--bg-card)', border: '1px solid var(--border)', borderRadius: 10, padding: '10px 8px', textAlign: 'center' }}>
<div style={{ fontSize: 11, opacity: 0.7, marginBottom: 4 }}>{t(k)}</div>
<div style={{ fontSize: strong ? 18 : 16, fontWeight: 700 }}>{v}</div>
</div>
))}
</div>
)}
<PrivyAccount />
</div>
);
}
📜 Git History
9dfe057feat(poli): editorial Wallet/MarketDetail/Copy-subs + serif-var fix (chunk 8)10 days ago
6c47fa4chore: local Polikopi project home + Phase 1 redesign artifacts12 days ago
Show last diff
Loading...