repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | function parseCsv(value) { |
| #2 | if (!value) { |
| #3 | return []; |
| #4 | } |
| #5 | return value |
| #6 | .split(",") |
| #7 | .map((item) => item.trim()) |
| #8 | .filter(Boolean); |
| #9 | } |
| #10 | function normalizeSymbols(symbols) { |
| #11 | return symbols.map((symbol) => symbol.toUpperCase()); |
| #12 | } |
| #13 | export function loadPerpsRuntimeConfig(env = process.env) { |
| #14 | return { |
| #15 | rpcUrl: env.SOLANA_RPC_URL ?? "https://api.mainnet-beta.solana.com", |
| #16 | apiUrl: env.CLAWD_PERPS_API_URL ?? "https://perp-api.phoenix.trade", |
| #17 | heliusApiKey: env.HELIUS_API_KEY || undefined, |
| #18 | wallet: env.CLAWD_PERPS_WALLET || undefined, |
| #19 | traderPdaIndex: Number(env.CLAWD_PERPS_TRADER_PDA_INDEX ?? 0), |
| #20 | traderSubaccountIndex: Number(env.CLAWD_PERPS_TRADER_SUBACCOUNT_INDEX ?? 0), |
| #21 | liveTrading: env.LIVE_TRADING === "true", |
| #22 | operatorConfirmed: env.OPERATOR_CONFIRMED === "true", |
| #23 | simOnly: env.PERPS_SIM_ONLY !== "false", |
| #24 | telegramBotToken: env.TELEGRAM_BOT_TOKEN || undefined, |
| #25 | telegramAllowedChats: parseCsv(env.TELEGRAM_ALLOWED_CHATS), |
| #26 | risk: { |
| #27 | allowedSymbols: normalizeSymbols(parseCsv(env.PERPS_ALLOWED_SYMBOLS ?? "SOL,ETH,BTC")), |
| #28 | maxNotionalUsd: Number(env.PERPS_MAX_NOTIONAL_USD ?? 250), |
| #29 | maxLeverage: Number(env.PERPS_MAX_LEVERAGE ?? 3), |
| #30 | maxSpreadBps: Number(env.PERPS_MAX_SPREAD_BPS ?? 40), |
| #31 | requireWallet: env.PERPS_REQUIRE_WALLET !== "false", |
| #32 | }, |
| #33 | }; |
| #34 | } |
| #35 | export function resolveTradingMode(config) { |
| #36 | if (config.liveTrading && config.operatorConfirmed && !config.simOnly) { |
| #37 | return "live"; |
| #38 | } |
| #39 | if (!config.simOnly) { |
| #40 | return "paper"; |
| #41 | } |
| #42 | return "observe"; |
| #43 | } |
| #44 | export function buildPreflightReport(config, request) { |
| #45 | const blocking = []; |
| #46 | const warnings = []; |
| #47 | const mode = resolveTradingMode(config); |
| #48 | const symbol = request.symbol.trim().toUpperCase(); |
| #49 | if (!config.rpcUrl) { |
| #50 | blocking.push("Missing SOLANA_RPC_URL."); |
| #51 | } |
| #52 | if (config.risk.requireWallet && !config.wallet) { |
| #53 | blocking.push("Missing CLAWD_PERPS_WALLET."); |
| #54 | } |
| #55 | if (!config.risk.allowedSymbols.includes(symbol)) { |
| #56 | blocking.push(`Symbol ${symbol} is outside PERPS_ALLOWED_SYMBOLS.`); |
| #57 | } |
| #58 | if (request.notionalUsd <= 0) { |
| #59 | blocking.push("Notional must be positive."); |
| #60 | } |
| #61 | if (request.notionalUsd > config.risk.maxNotionalUsd) { |
| #62 | blocking.push(`Notional ${request.notionalUsd} exceeds PERPS_MAX_NOTIONAL_USD=${config.risk.maxNotionalUsd}.`); |
| #63 | } |
| #64 | if (request.leverage !== undefined && request.leverage > config.risk.maxLeverage) { |
| #65 | blocking.push(`Leverage ${request.leverage} exceeds PERPS_MAX_LEVERAGE=${config.risk.maxLeverage}.`); |
| #66 | } |
| #67 | if (request.expectedSpreadBps !== undefined && |
| #68 | request.expectedSpreadBps > config.risk.maxSpreadBps) { |
| #69 | blocking.push(`Spread ${request.expectedSpreadBps}bps exceeds PERPS_MAX_SPREAD_BPS=${config.risk.maxSpreadBps}.`); |
| #70 | } |
| #71 | if (request.execution === "rise-live" || request.execution === "vulcan-live") { |
| #72 | if (mode !== "live") { |
| #73 | blocking.push("Live execution disabled. Require LIVE_TRADING=true, OPERATOR_CONFIRMED=true, and PERPS_SIM_ONLY=false."); |
| #74 | } |
| #75 | warnings.push("Live execution path must still simulate and sign outside this adapter."); |
| #76 | } |
| #77 | if (mode !== "live") { |
| #78 | warnings.push(`Runtime mode is ${mode}; execution should remain observe/paper.`); |
| #79 | } |
| #80 | return { |
| #81 | ok: blocking.length === 0, |
| #82 | mode, |
| #83 | blocking, |
| #84 | warnings, |
| #85 | }; |
| #86 | } |
| #87 | export function assertLiveTradingAllowed(config, request) { |
| #88 | const report = buildPreflightReport(config, { |
| #89 | ...request, |
| #90 | execution: "rise-live", |
| #91 | }); |
| #92 | if (!report.ok) { |
| #93 | throw new Error(report.blocking.join(" ")); |
| #94 | } |
| #95 | return report; |
| #96 | } |
| #97 | //# sourceMappingURL=config.js.map |