mirror of
https://github.com/theodore-song/polymarket-analyst.git
synced 2026-07-27 16:07:46 +00:00
Scaffold live money backend readiness
This commit is contained in:
+95
@@ -0,0 +1,95 @@
|
||||
const REQUIRED_ENV = [
|
||||
["KYC_PROVIDER", "KYC / eligibility provider"],
|
||||
["PAYMENTS_PROVIDER", "Deposit and withdrawal provider"],
|
||||
["WALLET_PROVIDER", "Wallet or deposit-wallet provider"],
|
||||
["POLYMARKET_CLOB_API_KEY", "Polymarket CLOB API key"],
|
||||
["POLYMARKET_CLOB_SECRET", "Polymarket CLOB API secret"],
|
||||
["POLYMARKET_CLOB_PASSPHRASE", "Polymarket CLOB passphrase"],
|
||||
["AUDIT_LOG_STORE", "Durable audit log store"],
|
||||
];
|
||||
|
||||
function providerStatus() {
|
||||
return REQUIRED_ENV.map(([key, label]) => ({
|
||||
key,
|
||||
label,
|
||||
configured: Boolean(process.env[key]),
|
||||
}));
|
||||
}
|
||||
|
||||
function liveTradingReady() {
|
||||
return providerStatus().every((x) => x.configured) && process.env.LIVE_TRADING_ENABLED === "true";
|
||||
}
|
||||
|
||||
function baseStatus() {
|
||||
const providers = providerStatus();
|
||||
return {
|
||||
ok: true,
|
||||
live_trading_enabled: liveTradingReady(),
|
||||
locked_reason: liveTradingReady()
|
||||
? null
|
||||
: "Live trading is locked until KYC, payments, wallet signing, CLOB credentials, audit storage, and LIVE_TRADING_ENABLED=true are configured.",
|
||||
providers,
|
||||
next_required: providers.filter((x) => !x.configured).map((x) => x.label),
|
||||
};
|
||||
}
|
||||
|
||||
function validateIntent(intent) {
|
||||
const missing = [];
|
||||
["user_id", "wallet_address", "agent_id", "market_id", "side", "max_amount"].forEach((key) => {
|
||||
if (!intent || intent[key] === undefined || intent[key] === null || intent[key] === "") missing.push(key);
|
||||
});
|
||||
if (intent && !["YES", "NO"].includes(String(intent.side).toUpperCase())) missing.push("side must be YES or NO");
|
||||
if (intent && Number(intent.max_amount) <= 0) missing.push("max_amount must be positive");
|
||||
return missing;
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
|
||||
if (req.method === "GET") {
|
||||
return res.status(200).json(baseStatus());
|
||||
}
|
||||
|
||||
if (req.method === "POST") {
|
||||
const body = typeof req.body === "string" ? JSON.parse(req.body || "{}") : (req.body || {});
|
||||
const intent = body.intent || body;
|
||||
const errors = validateIntent(intent);
|
||||
if (errors.length) {
|
||||
return res.status(400).json({ ok: false, error: "Invalid order intent", details: errors });
|
||||
}
|
||||
|
||||
const status = baseStatus();
|
||||
const auditEvent = {
|
||||
at: new Date().toISOString(),
|
||||
type: "ORDER_INTENT_DRY_RUN",
|
||||
user_id: String(intent.user_id),
|
||||
wallet_address: String(intent.wallet_address),
|
||||
agent_id: String(intent.agent_id),
|
||||
market_id: String(intent.market_id),
|
||||
side: String(intent.side).toUpperCase(),
|
||||
max_amount: Number(intent.max_amount),
|
||||
execution_mode: intent.execution_mode || "manual_approval",
|
||||
};
|
||||
|
||||
if (!status.live_trading_enabled) {
|
||||
return res.status(423).json({
|
||||
ok: false,
|
||||
dry_run: true,
|
||||
error: status.locked_reason,
|
||||
audit_event: auditEvent,
|
||||
status,
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(501).json({
|
||||
ok: false,
|
||||
dry_run: true,
|
||||
error: "Live trading credentials are configured, but signed order placement is intentionally not implemented yet.",
|
||||
audit_event: auditEvent,
|
||||
status,
|
||||
});
|
||||
}
|
||||
|
||||
res.setHeader("Allow", "GET, POST");
|
||||
return res.status(405).json({ ok: false, error: "Method not allowed" });
|
||||
}
|
||||
Reference in New Issue
Block a user