Add live money configuration setup
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
# Cloud state
|
||||
BLOB_READ_WRITE_TOKEN=
|
||||
PMA_STATE_PATH=shared/state.json
|
||||
|
||||
# Live-money feature gate
|
||||
# Keep false until legal/compliance approval, provider credentials, wallet signing,
|
||||
# payment rails, and audit logging are production-ready.
|
||||
LIVE_TRADING_ENABLED=false
|
||||
|
||||
# Eligibility / compliance provider
|
||||
KYC_PROVIDER=
|
||||
KYC_API_KEY=
|
||||
KYC_WEBHOOK_SECRET=
|
||||
RESTRICTED_JURISDICTIONS=US,CA-NY,CA-ON
|
||||
|
||||
# Wallet / deposit-wallet provider
|
||||
WALLET_PROVIDER=
|
||||
WALLET_PROJECT_ID=
|
||||
WALLET_API_KEY=
|
||||
DEPOSIT_WALLET_ADDRESS=
|
||||
POLYMARKET_SIGNATURE_TYPE=3
|
||||
|
||||
# Payments / deposits / withdrawals
|
||||
PAYMENTS_PROVIDER=
|
||||
PAYMENTS_API_KEY=
|
||||
PAYMENTS_WEBHOOK_SECRET=
|
||||
SETTLEMENT_ASSET=pUSD
|
||||
SETTLEMENT_CHAIN=polygon
|
||||
|
||||
# Polymarket CLOB credentials
|
||||
POLYMARKET_CLOB_HOST=https://clob.polymarket.com
|
||||
POLYMARKET_CHAIN_ID=137
|
||||
POLYMARKET_CLOB_API_KEY=
|
||||
POLYMARKET_CLOB_SECRET=
|
||||
POLYMARKET_CLOB_PASSPHRASE=
|
||||
|
||||
# Audit / monitoring
|
||||
AUDIT_LOG_STORE=
|
||||
ADMIN_ALERT_EMAIL=
|
||||
RISK_ADMIN_WALLET=
|
||||
@@ -3,3 +3,4 @@ node_modules/
|
||||
.vercel
|
||||
.claude/
|
||||
.env*
|
||||
!.env.example
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
# 📊 Polymarket Analyst — standalone website
|
||||
# Polymarket Analyst
|
||||
|
||||
A **single-file website**. Everything (fetching live Polymarket data, the
|
||||
analysis engine, and the ten AI paper-trading agents) runs in your browser. The
|
||||
paper portfolio is saved in your browser's local storage. No server, no keys.
|
||||
A Vercel-hosted Polymarket agent arena with shared paper-trading state, agent
|
||||
return charts, paper accounts, market browsing, and live-money readiness rails.
|
||||
|
||||
## Just look at it now
|
||||
Double-click **`index.html`** — it opens in your browser and works immediately.
|
||||
On first open it fetches live markets, generates today's suggestions, and the
|
||||
agents run a seven-day backtest, then begin live tracking. It auto-refreshes
|
||||
once per day; the **Run cycle** button forces a refresh anytime.
|
||||
|
||||
Open the deployed site:
|
||||
|
||||
https://polymarket-site-eta.vercel.app
|
||||
|
||||
The site fetches live Polymarket markets, generates agent suggestions, lets you
|
||||
run hourly paper cycles, and syncs the shared arena state through the Vercel API
|
||||
when `BLOB_READ_WRITE_TOKEN` is configured.
|
||||
|
||||
## Put it online (free) so you can reach it from any device
|
||||
|
||||
@@ -28,8 +31,20 @@ Pick one — all give you a public URL:
|
||||
1. <https://vercel.com> → Add New → Project → import this GitHub repo under the
|
||||
`theodore_song` Vercel account (or use the `vercel` CLI in this folder) → Deploy.
|
||||
|
||||
## Configuration
|
||||
|
||||
Use `.env.example` as the setup template.
|
||||
|
||||
- `BLOB_READ_WRITE_TOKEN` enables cross-device shared state.
|
||||
- `/api/live` reports whether KYC, payments, wallet/deposit-wallet, Polymarket
|
||||
CLOB, audit, and monitoring providers are configured.
|
||||
- `LIVE_TRADING_ENABLED` should stay `false` until legal review, provider setup,
|
||||
wallet signing, reconciliation, and dry-run testing are complete.
|
||||
- See `REAL_MONEY_ROADMAP.md` for the launch requirements before any real funds
|
||||
or live order execution are enabled.
|
||||
|
||||
## Notes
|
||||
- Paper trading only — no real money, nothing places real orders.
|
||||
- Paper trading only right now — no real money, nothing places real orders.
|
||||
- The analysis is a transparent heuristic, **not financial advice**.
|
||||
- Because the portfolio lives in your browser, each browser/device keeps its
|
||||
own portfolio. Clearing site data resets it (so does the **Reset** button).
|
||||
- The shared arena uses cloud state when configured. Individual paper accounts
|
||||
still use local browser storage unless a backend account database is added.
|
||||
|
||||
+53
-1
@@ -4,6 +4,17 @@ This app is currently paper trading only. The Live Money tab and `/api/live`
|
||||
endpoint are readiness scaffolding: they make the required product and backend
|
||||
interfaces visible without moving funds or placing orders.
|
||||
|
||||
## What is configured now
|
||||
|
||||
- `.env.example` lists the environment variables the production app needs.
|
||||
- `/api/live` reports which live-money providers are configured or missing.
|
||||
- `/api/live` accepts order intents only as dry-runs and returns an audit event.
|
||||
- The Live Money tab shows launch checks, wallet/deposit settings, agent risk
|
||||
limits, a dry-run order console, and an audit preview.
|
||||
|
||||
The app still refuses to place live orders. That is intentional until the legal,
|
||||
provider, wallet-signing, reconciliation, and monitoring steps below are done.
|
||||
|
||||
## Required before live deposits or trading
|
||||
|
||||
1. Legal and eligibility
|
||||
@@ -42,15 +53,56 @@ interfaces visible without moving funds or placing orders.
|
||||
|
||||
## Environment variables expected by `/api/live`
|
||||
|
||||
Copy `.env.example` into your local environment for development, then add the
|
||||
same variables in Vercel Project Settings -> Environment Variables for
|
||||
production.
|
||||
|
||||
- `KYC_PROVIDER`
|
||||
- `KYC_API_KEY`
|
||||
- `KYC_WEBHOOK_SECRET`
|
||||
- `PAYMENTS_PROVIDER`
|
||||
- `PAYMENTS_API_KEY`
|
||||
- `PAYMENTS_WEBHOOK_SECRET`
|
||||
- `WALLET_PROVIDER`
|
||||
- `WALLET_PROJECT_ID`
|
||||
- `WALLET_API_KEY`
|
||||
- `DEPOSIT_WALLET_ADDRESS`
|
||||
- `POLYMARKET_SIGNATURE_TYPE=3`
|
||||
- `POLYMARKET_CHAIN_ID=137`
|
||||
- `SETTLEMENT_ASSET=pUSD`
|
||||
- `SETTLEMENT_CHAIN=polygon`
|
||||
- `POLYMARKET_CLOB_API_KEY`
|
||||
- `POLYMARKET_CLOB_SECRET`
|
||||
- `POLYMARKET_CLOB_PASSPHRASE`
|
||||
- `AUDIT_LOG_STORE`
|
||||
- `LIVE_TRADING_ENABLED=true`
|
||||
- `ADMIN_ALERT_EMAIL`
|
||||
- `LIVE_TRADING_ENABLED=true` only after final approval and end-to-end testing
|
||||
|
||||
Even when all variables are present, live order placement remains intentionally
|
||||
unimplemented until wallet signing, compliance approval, and safe order routing
|
||||
are completed.
|
||||
|
||||
## Polymarket integration notes
|
||||
|
||||
Polymarket's public docs describe trading as non-custodial. Orders are signed
|
||||
and matched through the CLOB, and new API users generally use the deposit-wallet
|
||||
flow with signature type `3`.
|
||||
|
||||
Useful official docs:
|
||||
|
||||
- Trading overview: https://docs.polymarket.com/trading/overview
|
||||
- Trading quickstart: https://docs.polymarket.com/trading/quickstart
|
||||
- Deposit wallets: https://docs.polymarket.com/trading/deposit-wallets
|
||||
|
||||
## Final setup checklist
|
||||
|
||||
1. Choose and contract the KYC / eligibility provider.
|
||||
2. Choose the deposit and withdrawal provider.
|
||||
3. Choose the wallet or embedded-wallet provider and create a deposit wallet.
|
||||
4. Derive or create Polymarket CLOB credentials for the approved signing flow.
|
||||
5. Create durable append-only audit storage.
|
||||
6. Add all environment variables in Vercel.
|
||||
7. Run dry-runs against `/api/live` and verify audit events.
|
||||
8. Complete legal review, terms, restricted jurisdiction rules, and support
|
||||
procedures.
|
||||
9. Only then set `LIVE_TRADING_ENABLED=true`.
|
||||
|
||||
+34
-3
@@ -1,11 +1,22 @@
|
||||
const REQUIRED_ENV = [
|
||||
["KYC_PROVIDER", "KYC / eligibility provider"],
|
||||
["KYC_API_KEY", "KYC provider API key"],
|
||||
["KYC_WEBHOOK_SECRET", "KYC webhook secret"],
|
||||
["PAYMENTS_PROVIDER", "Deposit and withdrawal provider"],
|
||||
["PAYMENTS_API_KEY", "Payments provider API key"],
|
||||
["PAYMENTS_WEBHOOK_SECRET", "Payments webhook secret"],
|
||||
["WALLET_PROVIDER", "Wallet or deposit-wallet provider"],
|
||||
["WALLET_PROJECT_ID", "Wallet provider project ID"],
|
||||
["WALLET_API_KEY", "Wallet provider API key"],
|
||||
["DEPOSIT_WALLET_ADDRESS", "Polymarket deposit-wallet address"],
|
||||
["POLYMARKET_SIGNATURE_TYPE", "Polymarket signature type"],
|
||||
["POLYMARKET_CLOB_API_KEY", "Polymarket CLOB API key"],
|
||||
["POLYMARKET_CLOB_SECRET", "Polymarket CLOB API secret"],
|
||||
["POLYMARKET_CLOB_PASSPHRASE", "Polymarket CLOB passphrase"],
|
||||
["SETTLEMENT_ASSET", "Settlement asset"],
|
||||
["SETTLEMENT_CHAIN", "Settlement chain"],
|
||||
["AUDIT_LOG_STORE", "Durable audit log store"],
|
||||
["ADMIN_ALERT_EMAIL", "Admin alert destination"],
|
||||
];
|
||||
|
||||
function providerStatus() {
|
||||
@@ -13,23 +24,43 @@ function providerStatus() {
|
||||
key,
|
||||
label,
|
||||
configured: Boolean(process.env[key]),
|
||||
expected: key === "POLYMARKET_SIGNATURE_TYPE" ? "3 for new deposit-wallet API users" : undefined,
|
||||
}));
|
||||
}
|
||||
|
||||
function liveTradingReady() {
|
||||
return providerStatus().every((x) => x.configured) && process.env.LIVE_TRADING_ENABLED === "true";
|
||||
const requiredConfigured = providerStatus().every((x) => x.configured);
|
||||
const liveFlagEnabled = process.env.LIVE_TRADING_ENABLED === "true";
|
||||
const signatureTypeOk = String(process.env.POLYMARKET_SIGNATURE_TYPE || "") === "3";
|
||||
const chainOk = String(process.env.POLYMARKET_CHAIN_ID || "137") === "137";
|
||||
return requiredConfigured && liveFlagEnabled && signatureTypeOk && chainOk;
|
||||
}
|
||||
|
||||
function baseStatus() {
|
||||
const providers = providerStatus();
|
||||
const liveFlagEnabled = process.env.LIVE_TRADING_ENABLED === "true";
|
||||
const signatureTypeOk = String(process.env.POLYMARKET_SIGNATURE_TYPE || "") === "3";
|
||||
const chainOk = String(process.env.POLYMARKET_CHAIN_ID || "137") === "137";
|
||||
const missing = providers.filter((x) => !x.configured).map((x) => x.label);
|
||||
if (!liveFlagEnabled) missing.push("LIVE_TRADING_ENABLED=true after final approval");
|
||||
if (!signatureTypeOk) missing.push("POLYMARKET_SIGNATURE_TYPE=3 for deposit-wallet users");
|
||||
if (!chainOk) missing.push("POLYMARKET_CHAIN_ID=137");
|
||||
return {
|
||||
ok: true,
|
||||
live_trading_enabled: liveTradingReady(),
|
||||
live_flag_enabled: liveFlagEnabled,
|
||||
signature_type_ok: signatureTypeOk,
|
||||
chain_ok: chainOk,
|
||||
locked_reason: liveTradingReady()
|
||||
? null
|
||||
: "Live trading is locked until KYC, payments, wallet signing, CLOB credentials, audit storage, and LIVE_TRADING_ENABLED=true are configured.",
|
||||
: "Live trading is locked until eligibility, payments, wallet/deposit-wallet signing, Polymarket CLOB credentials, audit storage, monitoring, and LIVE_TRADING_ENABLED=true are configured.",
|
||||
providers,
|
||||
next_required: providers.filter((x) => !x.configured).map((x) => x.label),
|
||||
next_required: missing,
|
||||
docs: {
|
||||
polymarket_overview: "https://docs.polymarket.com/trading/overview",
|
||||
polymarket_quickstart: "https://docs.polymarket.com/trading/quickstart",
|
||||
deposit_wallets: "https://docs.polymarket.com/trading/deposit-wallets",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -2259,8 +2259,9 @@ function renderLiveBackendStatus(){
|
||||
const root=$("liveBackendStatus");if(!root)return;
|
||||
const s=LIVE_BACKEND_STATUS;
|
||||
if(!s){root.innerHTML="Checking backend readiness...";return;}
|
||||
const providers=(s.providers||[]).map(p=>`<div class="leader-row"><span>${esc(p.label)}</span><b class="${p.configured?"pos-val":"neg-val"}">${p.configured?"configured":"missing"}</b></div>`).join("");
|
||||
root.innerHTML=`<b>${s.live_trading_enabled?"Live trading unlocked":"Live trading locked"}</b><div class="small muted" style="margin:6px 0">${esc(s.locked_reason||"All required backend providers are configured.")}</div>${providers}`;
|
||||
const providers=(s.providers||[]).map(p=>`<div class="leader-row"><span>${esc(p.label)}${p.expected?`<div class="small muted">${esc(p.expected)}</div>`:""}</span><b class="${p.configured?"pos-val":"neg-val"}">${p.configured?"configured":"missing"}</b></div>`).join("");
|
||||
const next=(s.next_required||[]).slice(0,8).map(x=>`<li>${esc(x)}</li>`).join("");
|
||||
root.innerHTML=`<b>${s.live_trading_enabled?"Live trading unlocked":"Live trading locked"}</b><div class="small muted" style="margin:6px 0">${esc(s.locked_reason||"All required backend providers are configured.")}</div>${providers}${next?`<div class="locked-panel" style="margin-top:10px"><b>Next setup items</b><ul>${next}</ul></div>`:""}<div class="small muted" style="margin-top:8px">Live execution stays disabled until every provider is configured and final approval flips LIVE_TRADING_ENABLED=true.</div>`;
|
||||
}
|
||||
async function dryRunLiveOrderIntent(){
|
||||
const s=loadLiveState();
|
||||
|
||||
Reference in New Issue
Block a user