import { useEffect, useState } from 'react';
import QRCode from 'qrcode';
import { readDepositBalances, USDC_NATIVE_ADDRESS } from '../utils/dwApprovals';
import { useT } from '../i18n/LanguageContext';
/**
* Self-serve crypto deposit screen (Friend-beta Block B / B1).
* Shows the user's deposit-wallet address + QR, a hard network/token warning, and polls
* the DW's balances to reflect deposit state: waiting → detected (USDC, converting) → ready
* (pUSD). The actual USDC→pUSD conversion is done server-side by the watcher (B2).
*/
export default function DepositPanel({ dwAddress }: { dwAddress: string }) {
const { t } = useT();
const [copied, setCopied] = useState(false);
const [qr, setQr] = useState('');
const [bal, setBal] = useState<{ incoming: bigint; pusd: bigint } | null>(null);
useEffect(() => {
let alive = true;
QRCode.toDataURL(dwAddress, { margin: 1, width: 180 }).then((u) => { if (alive) setQr(u); }).catch(() => {});
return () => { alive = false; };
}, [dwAddress]);
useEffect(() => {
if (!dwAddress) return;
let alive = true;
const load = () => readDepositBalances(dwAddress).then((b) => { if (alive) setBal({ incoming: b.incoming, pusd: b.pusd }); }).catch(() => {});
load();
const id = setInterval(load, 20000);
return () => { alive = false; clearInterval(id); };
}, [dwAddress]);
const copyAddr = async () => {
try { await navigator.clipboard.writeText(dwAddress); setCopied(true); setTimeout(() => setCopied(false), 1500); } catch { /* ignore */ }
};
const fmt = (raw: bigint) => (Number(raw) / 1e6).toFixed(2);
const status = !bal
? t('dep.statusWaiting')
: bal.incoming > 0n
? t('dep.statusDetected').replace('${amount}', `$${fmt(bal.incoming)}`)
: bal.pusd > 0n
? t('dep.statusReady').replace('${amount}', fmt(bal.pusd))
: t('dep.statusWaiting');
return (
<div className="acct-deposit" style={{ marginTop: 12 }}>
<div className="acct-sub" style={{ fontWeight: 600 }}>{t('dep.title')}</div>
<div style={{ border: '1px solid #f59e0b', background: 'rgba(245,158,11,0.10)', borderRadius: 8, padding: '8px 10px', margin: '8px 0' }}>
<div style={{ fontWeight: 600, color: '#b45309', fontSize: 13 }}>{t('dep.warnTitle')}</div>
<div className="acct-sub" style={{ marginTop: 2 }}>{t('dep.warnBody')}</div>
</div>
<div className="acct-sub">{t('dep.instr')}</div>
{qr && <img src={qr} alt="deposit address QR" width={180} height={180} style={{ display: 'block', margin: '8px auto', borderRadius: 6 }} />}
<div className="acct-dep-addr" style={{ wordBreak: 'break-all', fontFamily: 'monospace', fontSize: 12, margin: '6px 0' }}>{dwAddress}</div>
<button className="acct-btn" onClick={copyAddr}>{copied ? t('dep.copied') : t('dep.copy')}</button>
<div className="acct-sub" style={{ marginTop: 8, opacity: 0.75, fontSize: 11 }}>{t('dep.token')}:</div>
<div style={{ wordBreak: 'break-all', fontFamily: 'monospace', fontSize: 11, opacity: 0.75 }}>{USDC_NATIVE_ADDRESS}</div>
<div className="acct-sub" style={{ marginTop: 8, fontWeight: 600 }}>{status}</div>
<div className="acct-sub" style={{ marginTop: 4, opacity: 0.8 }}>{t('dep.note')}</div>
</div>
);
}
📜 Git History
6c47fa4chore: local Polikopi project home + Phase 1 redesign artifacts12 days ago
Show last diff
Loading...