()
| 351 | if (!effectiveProxy) { setPositions([]); return; } |
| 352 | let cancelled = false; |
| 353 | const fetchPositions = async () => { |
| 354 | try { |
| 355 | const res = await fetch( |
| 356 | `https://data-api.polymarket.com/positions?user=${encodeURIComponent(effectiveProxy)}&sortBy=CURRENT&limit=50`, |
| 357 | { signal: AbortSignal.timeout(10_000) } |
| 358 | ); |
| 359 | if (!res.ok || cancelled) return; |
| 360 | const data = await res.json(); |
| 361 | const arr = Array.isArray(data) ? data : data.positions || data.data || []; |
| 362 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 363 | const items: PositionItem[] = arr.filter((p: any) => { |
| 364 | const size = parseFloat(String(p.size || p.shares || 0)); |
| 365 | if (size < 0.01) return false; |
| 366 | // Filter out closed/redeemed/resolved positions |
| 367 | const closed = p.closed || p.resolved || p.redeemed || p.mergeable; |
| 368 | if (closed) return false; |
| 369 | // Filter out positions with curPrice at 0 or 1 (settled) |
| 370 | const cur = parseFloat(String(p.curPrice || p.currentPrice || -1)); |
| 371 | if (cur <= 0.001 || cur >= 0.999) return false; |
| 372 | return true; |
| 373 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 374 | }).map((p: any) => { |
| 375 | const size = parseFloat(String(p.size || p.shares || 0)); |
| 376 | const avgPrice = parseFloat(String(p.avgPrice || p.price || 0)); |
| 377 | const curPrice = parseFloat(String(p.curPrice || p.currentPrice || 0)); |
| 378 | return { |
| 379 | conditionId: String(p.conditionId || p.market || ""), |
| 380 | title: String(p.title || p.question || p.marketTitle || ""), |
| 381 | outcome: String(p.outcome || ""), |
| 382 | size, |
| 383 | avgPrice, |
| 384 | currentPrice: curPrice, |
| 385 | cashPnl: (curPrice - avgPrice) * size, |
| 386 | image: p.image || p.icon || p.marketImage || null, |
| 387 | }; |
| 388 | }); |
| 389 | if (!cancelled) setPositions(items); |
| 390 | } catch { /* ignore */ } |
| 391 | }; |
| 392 | fetchPositions(); |
| 393 | const iv = setInterval(fetchPositions, 30_000); |
| 394 | let posTimer: ReturnType<typeof setTimeout> | null = null; |
no outgoing calls
no test coverage detected