← Back
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...