// screens-setup.jsx — API setup + Extension install + Subscription
// ── API SETUP ─────────────────────────────────────────────────
const COM_CURRENCIES = ["USDT", "BTC", "ETH", "LTC", "SOL", "DOGE", "TRX", "XRP", "BNB"];
const COM_REGIONS = [
{ value: "norway", label: "Norway · no.decodo.com (recommended)" },
{ value: "malta", label: "Malta · mt.decodo.com" },
{ value: "japan", label: "Japan · jp.decodo.com" },
];
const ApiSetup = ({ goto, path, setApiState, apiState }) => {
// Step 0 = platform picker, Step 1 = key entry
const [step, setStep] = React.useState(0);
const [platforms, setPlatforms] = React.useState(apiState?.platforms || "both");
const [comKey, setComKey] = React.useState(apiState?.comKey || "");
const [comClaims, setComClaims] = React.useState(apiState?.comClaims || [{ id: 1, currency: "USDT" }]);
const [comRegion, setComRegion] = React.useState(apiState?.comRegion || "norway");
const [usKey, setUsKey] = React.useState(apiState?.usKey || "");
// Stake.us is forced to sweeps + Texas
const usCurrency = "Sweeps";
const usRegion = "texas";
const [testing, setTesting] = React.useState(false);
const [log, setLog] = React.useState([]);
const [done, setDone] = React.useState(false);
const [saving, setSaving] = React.useState(false);
const [saveError, setSaveError] = React.useState("");
const addComClaim = () => {
if (comClaims.length >= 6) return;
const used = new Set(comClaims.map(c => c.currency));
const next = COM_CURRENCIES.find(c => !used.has(c)) || COM_CURRENCIES[0];
setComClaims([...comClaims, { id: Date.now(), currency: next }]);
};
const removeComClaim = (id) => setComClaims(comClaims.filter(c => c.id !== id));
const updateComClaim = (id, currency) => setComClaims(comClaims.map(c => c.id === id ? { ...c, currency } : c));
const runTest = async () => {
setTesting(true);
setLog([]);
setDone(false);
const token = localStorage.getItem("cc_token");
if (!token) { setTesting(false); return; }
const platform = wantUs ? "stake_us" : "stake_com";
const apiKey = wantUs ? usKey : comKey;
try {
const r = await fetch("/api/keys/test", {
method: "POST",
headers: { "content-type": "application/json", "Authorization": `Bearer ${token}` },
body: JSON.stringify({ platform, api_key: apiKey }),
});
const d = await r.json();
const lines = d.log || [];
let t = 0;
lines.forEach((l, i) => {
t += 300;
setTimeout(() => {
setLog((prev) => [...prev, { text: l.text, ok: l.ok }]);
if (i === lines.length - 1) { setDone(!!d.success); setTesting(false); }
}, t);
});
if (!lines.length) { setDone(false); setTesting(false); }
} catch {
setLog([{ text: "Network error — could not reach server", ok: "err" }]);
setTesting(false);
}
};
const wantCom = platforms === "com" || platforms === "both";
const wantUs = platforms === "us" || platforms === "both";
const canProceed = (wantCom ? comKey.trim().length > 0 : true) &&
(wantUs ? usKey.trim().length > 0 : true) &&
(wantCom || wantUs);
const proceed = async () => {
setSaveError("");
const token = localStorage.getItem("cc_token");
if (!token) { goto("signup"); return; }
const comEntries = wantCom && comKey
? comClaims.map(c => ({ api_key: comKey, currency: c.currency.toLowerCase() }))
: [];
const usEntries = wantUs && usKey ? [{ api_key: usKey, currency: "sweeps" }] : [];
setSaving(true);
try {
// Save keys
const r = await fetch("/api/keys", {
method: "POST",
headers: { "content-type": "application/json", "Authorization": `Bearer ${token}` },
body: JSON.stringify({ stake_com: comEntries, stake_us: usEntries }),
});
const d = await r.json();
if (d.error) { setSaveError(d.error); setSaving(false); return; }
// Save proxy region preference
if (wantCom) {
await fetch("/api/me/proxy-region", {
method: "POST",
headers: { "content-type": "application/json", "Authorization": `Bearer ${token}` },
body: JSON.stringify({ com_region: comRegion }),
}).catch(() => {});
}
setApiState({ platforms, comKey, comClaims, comRegion, usKey, usCurrency, usRegion, tested: done });
goto("dashboard");
} catch {
setSaveError("Network error — try again");
setSaving(false);
}
};
const comCurrencyOptions = (currentId) => {
const taken = new Set(comClaims.filter(c => c.id !== currentId).map(c => c.currency));
return COM_CURRENCIES.map(c => ({ value: c, label: taken.has(c) ? `${c} · already added` : c, disabled: taken.has(c) }));
};
return (
{path === "hybrid" ? "API · then extension" : "API setup"}
step 3a · cloud setup
Paste your Stake API keys
On Stake → Settings → API → Generate key.
We encrypt keys at rest with Fernet.
Test claim
{done ? "verified · 218ms" : testing ? "running…" : "ready"}
{log.length === 0 && (
Click "Fire test claim" to verify your keys, proxy, and Turnstile pool with a synthetic code.
)}
{log.map((l, i) => (
{`[${String(i+1).padStart(2,"0")}]`}
{l.text}
))}
{done && (
✓ Pipeline working. You're good to go.
)}
{testing ? <>◐ Testing…> : done ? <>Re-run > : <>Fire test claim >}
{saveError && (
{saveError}
)}
goto("subscription")}> Back
{saving
? <>◐ Saving…>
: path === "hybrid" ? "Next · install extension" : "Continue · pick a plan"}
{!saving && }
);
};
// ── EXTENSION INSTALL ─────────────────────────────────────────
const ExtInstall = ({ goto, path, setExtState, extState }) => {
const [browser, setBrowser] = React.useState(extState?.browser || "chrome");
const [stage, setStage] = React.useState(extState?.installed ? 3 : 0); // 0 pick, 1 installing, 2 linking, 3 done
const [progress, setProgress] = React.useState(0);
const [linked, setLinked] = React.useState(extState?.linked || { stake_com: false, stake_us: false, shuffle: false, thrill: false });
React.useEffect(() => {
if (stage !== 1) return;
setProgress(0);
const tick = setInterval(() => {
setProgress((p) => {
if (p >= 100) { clearInterval(tick); setStage(2); return 100; }
return p + 5;
});
}, 90);
return () => clearInterval(tick);
}, [stage]);
const allLinked = Object.values(linked).every(Boolean);
const linkAll = () => {
const keys = Object.keys(linked);
keys.forEach((k, i) => setTimeout(() => setLinked((prev) => ({ ...prev, [k]: true })), 400 * (i + 1)));
setTimeout(() => setStage(3), 400 * keys.length + 400);
};
const proceed = () => {
setExtState({ browser, installed: stage >= 2, linked });
goto("subscription");
};
return (
{path === "hybrid" ? "extension · then plan" : "extension setup"}
step 3b · local setup
Install the extension
Pick your browser. Pin the icon. Log into Stake / Shuffle / Thrill in a normal tab — we'll link them in one click.
{/* Browser picker */}
① Browser
{browser ? `${browser} selected` : "pick one"}
{[
{ id: "chrome", label: "Chrome" },
{ id: "brave", label: "Brave" },
{ id: "firefox", label: "Firefox" },
{ id: "safari", label: "Safari" },
].map(b => (
setBrowser(b.id)}
className={"path-card " + (browser === b.id ? "selected" : "")}
style={{ padding: 12, textAlign: "center", cursor: "pointer" }}>
{b.label}
))}
{/* Install */}
② Install & pin
= 2 ? "ok" : ""} dot={stage >= 2}>{stage >= 2 ? "installed" : stage === 1 ? "installing" : "ready"}
{stage === 0 && (
setStage(1)}>
Add Stake Sauce to {browser}
)}
{stage === 1 && (
◐
Downloading & verifying signature…
{progress}%
Don't see the icon? Browser menu → puzzle → pin Stake Sauce.
)}
{stage >= 2 && (
Installed in {browser} · pinned to toolbar
Auth token already provisioned — your account & the extension are paired.
)}
{/* Link */}
③ Link platforms
{Object.values(linked).filter(Boolean).length} of 4
{stage < 2 && Finish install first.
}
{stage >= 2 && (
{[
{ id: "stake_com" },
{ id: "stake_us" },
{ id: "shuffle" },
{ id: "thrill" },
].map((p) => (
{linked[p.id]
?
linked · session ok
:
setLinked((prev) => ({ ...prev, [p.id]: true }))}>Link}
))}
{allLinked ? "All platforms linked ✓" : "Link all (demo)"}
)}
{/* Right side: live extension popup mock */}
SS
Stake Sauce
v1.4.0
= 2 ? "ok" : ""} dot={stage >= 2}>{stage >= 2 ? "connected · SSE" : "not yet installed"}
{stage >= 2 ? "live · 0s" : "—"}
{[
{ id: "stake_com" },
{ id: "stake_us" },
{ id: "shuffle" },
{ id: "thrill" },
].map((p) => (
{linked[p.id]
?
linked
:
—}
))}
Last claim: {allLinked ? "shuf · AB12CD · 1.4s · ✓" : "—"}
↑ this is your browser popup, mirrored.
goto(path === "hybrid" ? "api-setup" : "onboarding")}> Back
Continue · pick a plan
);
};
// ── SUBSCRIPTION ──────────────────────────────────────────────
const MAX_SLOTS = 4;
const Subscription = ({ goto, path, plan, setPlan }) => {
const [billing, setBilling] = React.useState("monthly");
const [chosen, setChosen] = React.useState(plan || "house_cut");
const [slotCount, setSlots] = React.useState(1);
const [promoCode, setPromoCode] = React.useState("");
const [promoInfo, setPromoInfo] = React.useState(null);
const [promoErr, setPromoErr] = React.useState("");
const [checking, setChecking] = React.useState(false);
const [checkingOut, setCheckingOut] = React.useState(false);
const [payError, setPayError] = React.useState("");
// Three paid tiers — every plan covers both Stake.com and Stake.us, ships
// with reloads + daily dollar, and grants the (forthcoming) Shuffle/Thrill
// extension. What separates them is which code tiers BoostMonitor will route
// to the user: regular only / + highroller / + Saturday stream.
const PLANS = [
{
id: "house_cut", name: "The House Cut", tag: "Regular codes",
price: { monthly: 10, yearly: 96 },
blurb: "Regular bonus drops on both Stake.com and Stake.us — daily dollar and reloads on us.",
features: [
"Regular bonus codes (both platforms)",
"Reloads + Stake.us daily dollar — bundled",
"Pre-solved captchas, residential proxy",
"Extension access (Shuffle + Thrill — coming soon)",
],
},
{
id: "prime_cut", name: "The Prime Cut", tag: "+ Highroller",
price: { monthly: 15, yearly: 144 },
blurb: "Regular + highroller codes, both platforms. The pour-over of bonus claiming.",
features: [
"Everything in House Cut",
"Highroller codes (both platforms)",
"Same bundled reloads + daily dollar",
"Telegram alerts on every claim",
],
featured: true,
},
{
id: "grand_feast", name: "The Grand Feast", tag: "Every code",
price: { monthly: 30, yearly: 288 },
blurb: "The whole spread — regular, highroller, and Saturday stream codes for both platforms.",
features: [
"Everything in Prime Cut",
"Saturday stream codes (both platforms)",
"First in line on every drop tier",
"Priority support",
],
},
];
const chosenPlan = PLANS.find(p => p.id === chosen);
const basePrice = billing === "monthly"
? (chosenPlan?.price.monthly ?? 0)
: (chosenPlan?.price.yearly ?? 0);
// Price scales linearly with slot count. 1 slot = 1 API key bound to one
// platform; buying a 2nd slot lets the user run both Stake.com and Stake.us
// in parallel under the same tier.
const total = basePrice * slotCount;
const checkPromo = async () => {
if (!promoCode.trim()) return;
setPromoErr(""); setChecking(true); setPromoInfo(null);
const token = localStorage.getItem("cc_token");
try {
const r = await fetch("/api/promo/check", {
method: "POST",
headers: { "content-type": "application/json", "Authorization": `Bearer ${token}` },
body: JSON.stringify({ code: promoCode.trim() }),
});
const d = await r.json();
if (d.error) { setPromoErr(d.error); } else { setPromoInfo(d); }
} catch (_) { setPromoErr("Network error"); }
setChecking(false);
};
const checkout = async () => {
setPayError("");
const token = localStorage.getItem("cc_token");
if (!token) { goto("signup"); return; }
setCheckingOut(true);
try {
const r = await fetch("/api/payments/create", {
method: "POST",
headers: { "content-type": "application/json", "Authorization": `Bearer ${token}` },
body: JSON.stringify({
plan: chosen,
addons: { reload: addonReload, extra_seat: addonSeat },
promo_code: promoCode.trim() || undefined,
}),
});
const d = await r.json();
if (d.error) { setPayError(d.error); setCheckingOut(false); return; }
if (d.dev_mode || !d.invoice_url) {
setPlan(chosen);
goto("api-setup");
} else {
window.location.href = d.invoice_url;
}
} catch {
setPayError("Network error — try again");
setCheckingOut(false);
}
};
const pill = (label) => (
{label}
);
return (
cancel anytime
step 3 · pick your cut
What'll it be?
Choose your platform. Add extras below. Yearly saves ~20%.
{/* Billing toggle */}
{["monthly", "yearly"].map(b => (
))}
{/* Plan cards */}
{PLANS.map(p => (
setChosen(p.id)}
style={{ minHeight: 300, position: "relative", cursor: "pointer" }}>
{p.featured &&
best value}
{p.name}
{pill(p.tag)}
{p.blurb}
${billing === "monthly" ? p.price.monthly : p.price.yearly}
/{billing === "monthly" ? "mo" : "yr"}
{p.features.map((f, i) => (
-
{f}
))}
{chosen === p.id && }
{chosen === p.id ? "selected" : "tap to select"}
))}
{/* Add-ons */}
secret seasonings
{!hasApi && — requires a Stake.com or Stake.us plan}
{ADDONS.map(a => {
const active = addonStates[a.id];
const disabled = a.requiresApi && !hasApi;
return (
!disabled && addonSetters[a.id](!active)}
style={{
border: `2px solid ${active ? "var(--accent)" : "var(--border-2)"}`,
borderRadius: "var(--radius-sm)",
padding: "14px 18px",
minWidth: 200, flex: 1, maxWidth: 320,
cursor: disabled ? "not-allowed" : "pointer",
opacity: disabled ? 0.4 : 1,
background: active ? "rgba(0,230,77,.07)" : "var(--surf)",
transition: "border-color .15s, background .15s",
}}>
{a.icon}
{a.name}
+${billing === "monthly" ? a.price.monthly : a.price.yearly}
/{billing === "monthly" ? "mo" : "yr"}
{a.blurb}
{active && }
{active ? "added" : "tap to add"}
);
})}
{/* Order summary */}
{chosenPlan?.name}
${basePrice}/{billing === "monthly" ? "mo" : "yr"}
{addonReload && (
+ Reload Claimer
+${ADDONS[0].price[billing]}/{billing === "monthly" ? "mo" : "yr"}
)}
{addonSeat && (
+ Extra API Slot
+${ADDONS[1].price[billing]}/{billing === "monthly" ? "mo" : "yr"}
)}
{promoInfo && (
✓ {promoInfo.code}
−{promoInfo.description}
)}
Total
${total}/{billing === "monthly" ? "mo" : "yr"}
{/* Promo code */}
{ setPromoCode(e.target.value.toUpperCase()); setPromoInfo(null); setPromoErr(""); }}
placeholder="Promo code (optional)"
style={{ flex: 1, padding: "8px 12px", fontSize: 13, background: "var(--surf-2)", color: "var(--text)", border: "1px solid var(--border-2)", borderRadius: "var(--radius-sm)", textTransform: "uppercase", letterSpacing: ".06em", outline: "none" }} />
{checking ? "…" : "Apply"}
{promoErr &&
{promoErr}
}
{payError &&
{payError}
}
goto("onboarding")}> Back
{checkingOut
? <>◐ Starting…>
: <>Subscribe · ${total}/{billing === "monthly" ? "mo" : "yr"} >}
);
};
Object.assign(window, { ApiSetup, ExtInstall, Subscription });