MCPcopy Create free account
hub / github.com/AmazingAng/PolyWorld / PortfolioPanel

Function PortfolioPanel

src/components/PortfolioPanel.tsx:50–289  ·  view source on GitHub ↗
({ markets, onSelectMarket }: PortfolioPanelProps)

Source from the content-addressed store, hash-verified

48}
49
50export default function PortfolioPanel({ markets, onSelectMarket }: PortfolioPanelProps) {
51 const { t } = useI18n();
52 const connectedAddress = useWalletStore((s) => s.address);
53 // Start with "" on both server and client to avoid hydration mismatch,
54 // then load from localStorage + connected wallet in a single effect.
55 const [savedWallet, setSavedWalletState] = useState<string>("");
56 const [inputValue, setInputValue] = useState("");
57
58 useEffect(() => {
59 const stored = readSavedWallet();
60 if (stored) {
61 // Respect manually saved wallet — don't overwrite with connected address
62 setSavedWalletState(stored);
63 } else if (connectedAddress) {
64 // No saved wallet yet: use connected address as default (don't persist yet)
65 setSavedWalletState(connectedAddress);
66 }
67 // eslint-disable-next-line react-hooks/exhaustive-deps
68 }, []); // run once on mount
69
70 // Do NOT auto-sync on wallet connect — user may be tracking a different wallet
71 const [positions, setPositions] = useState<TraderPosition[]>([]);
72 const [totalValue, setTotalValue] = useState(0);
73 const [loading, setLoading] = useState(false);
74 const [error, setError] = useState<string | null>(null);
75 const [showClosed, setShowClosed] = useState(false);
76 const cancelRef = useRef(false);
77
78 // Match positions to markets by conditionId → marketId, or by title fallback
79 const enriched = useMemo<PositionWithMarket[]>(() => {
80 return positions.map((p) => {
81 // Try matching via conditionId against sub-market IDs first
82 let market = markets.find((m) =>
83 m.markets.some((sm) => sm.id === p.conditionId)
84 );
85 // Fallback: match by title substring
86 if (!market && p.title) {
87 const titleLower = p.title.toLowerCase();
88 market = markets.find((m) => m.title.toLowerCase() === titleLower);
89 if (!market) {
90 market = markets.find((m) =>
91 m.title.toLowerCase().includes(titleLower.slice(0, 30)) ||
92 titleLower.includes(m.title.toLowerCase().slice(0, 30))
93 );
94 }
95 }
96 return { position: p, market };
97 });
98 }, [positions, markets]);
99
100 const openPositions = useMemo(() => enriched.filter((e) => !e.position.redeemed), [enriched]);
101 const closedPositions = useMemo(() => enriched.filter((e) => e.position.redeemed), [enriched]);
102 const totalPnl = useMemo(
103 () => openPositions.reduce((s, e) => s + e.position.cashPnl, 0),
104 [openPositions]
105 );
106
107 const load = useCallback(async (wallet: string) => {

Callers

nothing calls this directly

Calls 8

useI18nFunction · 0.90
fetchTraderPositionsFunction · 0.90
fetchTraderValueFunction · 0.90
formatVolumeFunction · 0.90
readSavedWalletFunction · 0.85
loadFunction · 0.85
saveWalletFunction · 0.85
handleSubmitFunction · 0.85

Tested by

no test coverage detected