Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
026b9b5
copy-trade app: scaffold + Liquid Glass UI + leader discovery + copy …
Kaleb-Rupe Jun 12, 2026
f6f118f
copy-trade: plain-language console, deposit/withdraw flow, leaderboar…
Kaleb-Rupe Jun 12, 2026
853f5e9
copy-trade: robust money inputs + honest skip messages
Kaleb-Rupe Jun 12, 2026
2da22a8
copy-trade: persistent session + global running/close-all + multi-filter
Kaleb-Rupe Jun 12, 2026
68e878a
copy-trade: combinable metric filters + big red Stop all on the hero
Kaleb-Rupe Jun 12, 2026
c0641a7
predict: Updown — glass price-call rounds on Flash V2 (5m/15m/1h time…
Kaleb-Rupe Jun 12, 2026
4a401b2
predict v2 phase 1: prediction-market odds engine + spec
Kaleb-Rupe Jun 15, 2026
ba98a0f
predict v2 phase 2/3: market-state hook + Discover grid + market card
Kaleb-Rupe Jun 15, 2026
ba1c06d
predict v2 phase 4: market detail (strike ladder + buckets) + buy ticket
Kaleb-Rupe Jun 15, 2026
a6af920
predict v2 phase 5: real bet execution (wallet/session/signer wired)
Kaleb-Rupe Jun 15, 2026
7d6a104
predict v2 phase 5b: portfolio of open bets (read-only) + card polish
Kaleb-Rupe Jun 15, 2026
80a2db5
predict v2: float the card odds (each market gets its own cents)
Kaleb-Rupe Jun 15, 2026
45f4803
predict v2.1: lock the spread-aware Path A redesign (corrected constr…
Kaleb-Rupe Jun 15, 2026
06d7390
predict v2.1: spread-aware engine + live-spread wiring + slippage (fi…
Kaleb-Rupe Jun 15, 2026
f67e884
predict v2.1: double-spread engine correction + two-step reconcile (f…
Kaleb-Rupe Jun 15, 2026
cd68467
predict v2.1: gates, real enable error, funds + double-submit guards …
Kaleb-Rupe Jun 15, 2026
819b82e
predict v2.1: remove degenerate buckets, honest reach semantics in en…
Kaleb-Rupe Jun 15, 2026
6838be1
predict v2.1: settlement engine + expiry + bets view + disclosure (fi…
Kaleb-Rupe Jun 15, 2026
6a648b2
predict v2.1: remediate adversarial-review findings (C1,C2,H1,H2,H4 +…
Kaleb-Rupe Jun 15, 2026
55197e5
predict v2.1: fix lost-result regression from the remediation (verifi…
Kaleb-Rupe Jun 15, 2026
55d3b3f
predict v2.1: F7 cross-app guard + spec review-outcome record
Kaleb-Rupe Jun 15, 2026
2ef139d
predict: make markets THE app at /, any-wallet connect, standalone fu…
Kaleb-Rupe Jun 15, 2026
bac1057
predict: wallet connect matches the other apps (tap-trade pattern)
Kaleb-Rupe Jun 15, 2026
3e042e1
predict: add session authority guard (exact tap-trade parity, securit…
Kaleb-Rupe Jun 15, 2026
834dd5b
predict: fix 'Enable one-tap' getting stuck — refresh owner snapshot …
Kaleb-Rupe Jun 15, 2026
c526f7d
predict: stake input — drop the $25 hardcode, add max button + min hint
Kaleb-Rupe Jun 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 54 additions & 10 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 22 additions & 5 deletions examples/copy-trade/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# copy-trade — LEADER is required; everything else optional (dry-run default)
LEADER= # wallet pubkey to mirror (any owner with live V2 positions)
MAX_FOLLOW_USD=100 # hard cap per mirrored trade
# RATIO=0.1 # override collateral-ratio sizing with a fixed ratio
# FOLLOWER_KEYPAIR= # + run with `-- --execute` to sign for real (MAINNET wallet!)
# copy-trade — copy to .env.local and fill in ONE thing: your RPC key.
# cp .env.example .env.local
#
# Flash Trade V2 runs on Solana MAINNET (real funds — start small). You connect a
# wallet and Enable One-Click Trading; mirrors sign with a session key, no popups.

NEXT_PUBLIC_FLASH_NETWORK=mainnet

# ── RPC ───────────────────────────────────────────────────────────────────────
# Base-chain RPC (setup / deposit / withdraw) — browser-direct to a CORS-friendly
# RPC. A FREE key from helius.dev / triton.one / quicknode.com works. This URL
# ships in the browser bundle, so use a DOMAIN-RESTRICTED key for deploys.
NEXT_PUBLIC_BASE_RPC=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY_HERE
# Ephemeral Rollup RPC (trading + the live leader stream) — serves CORS, direct.
NEXT_PUBLIC_ER_RPC=https://flash.magicblock.xyz

# The leaderboard is fetched server-side from the public fstats V2 stats API via
# /api/leaders (it has no CORS). No key needed. Override only if it ever moves:
# FSTATS_BASE=https://fstats.io/v2/api/v1

# Override the hosted Flash V2 API (rarely needed).
# NEXT_PUBLIC_FLASH_API_BASE=https://flashapi.trade/v2
39 changes: 39 additions & 0 deletions examples/copy-trade/app/api/leaders/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// ─────────────────────────────────────────────────────────────────────────────
// app/api/leaders/route.ts — same-origin read-only proxy for the PUBLIC fstats
// V2/ER leaderboard. WHY IT EXISTS: fstats serves leader rankings (win rate,
// PnL) for the MagicBlock ER but does NOT send CORS headers, so a browser can't
// fetch it directly. This route fetches it server-side and hands the JSON back.
// It carries NO keys and reaches NO RPC — it only relays public stats. (Live
// LEADER POSITIONS come straight from flashapi.trade over the owner WS, which
// DOES serve CORS — see lib/copy-engine.ts; this is discovery only.)
// ─────────────────────────────────────────────────────────────────────────────

export const runtime = "nodejs";

const FSTATS = "https://fstats.io/v2/api/v1";

export async function GET(): Promise<Response> {
try {
const [lbRes, openRes] = await Promise.all([
fetch(`${FSTATS}/leaderboards/pnl`, { cache: "no-store" }),
fetch(`${FSTATS}/positions/open`, { cache: "no-store" }),
]);
if (!lbRes.ok) throw new Error(`fstats leaderboard ${lbRes.status}`);
const lb = (await lbRes.json()) as { leaderboard?: unknown[] };
// positions/open is best-effort — it only enriches rows with "live now" counts
let openByOwner: Record<string, number> = {};
if (openRes.ok) {
const open = (await openRes.json()) as { positions?: Array<{ owner: string }> };
openByOwner = (open.positions ?? []).reduce<Record<string, number>>((acc, p) => {
acc[p.owner] = (acc[p.owner] ?? 0) + 1;
return acc;
}, {});
}
return Response.json(
{ leaders: lb.leaderboard ?? [], openByOwner },
{ headers: { "Cache-Control": "public, max-age=10" } },
);
} catch (e) {
return Response.json({ error: (e as Error).message }, { status: 502 });
}
}
Loading