{"version":3,"file":"manage-orders.mjs","names":[],"sources":["../../../src/tools/manage-orders.ts"],"sourcesContent":["/**\n * Manage Orders Tool — conditional order engine via ClawnchOrders\n *\n * Supports 7 order types: limit_buy, limit_sell, stop_loss, take_profit,\n * dca, trailing_stop, twap. Includes order chaining, risk management,\n * and circuit breaker protection.\n *\n * Orders are stored via a StateStore adapter. In OpenClaw, this uses\n * the agent's persistent state directory.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { Type } from '@sinclair/typebox';\nimport { stringEnum, jsonResult, errorResult, readStringParam, readNumberParam } from '../lib/tool-helpers.js';\nimport { getPrice } from '../services/price-service.js';\n\nconst ACTIONS = [\n  'create', 'list', 'cancel', 'cancel_tag', 'check',\n  'executed', 'failed', 'pause', 'resume',\n  'risk', 'reset_circuit_breaker', 'cleanup',\n] as const;\n\nconst ORDER_TYPES = [\n  'limit_buy', 'limit_sell', 'stop_loss', 'take_profit',\n  'dca', 'trailing_stop', 'twap',\n] as const;\n\nconst ManageOrdersSchema = Type.Object({\n  action: stringEnum(ACTIONS, {\n    description:\n      'create: new order. list: show all orders. cancel/cancel_tag: cancel by ID/tag. ' +\n      'check: check triggers against price. executed/failed: mark order result. ' +\n      'pause/resume: toggle order. risk: show risk status. cleanup: remove completed.',\n  }),\n  type: Type.Optional(stringEnum(ORDER_TYPES, {\n    description: 'Order type for create action',\n  })),\n  token: Type.Optional(Type.String({\n    description: 'Token address (defaults to agent\\'s token if available)',\n  })),\n  trigger_price: Type.Optional(Type.String({\n    description: 'Trigger price in ETH (e.g. \"0.001\")',\n  })),\n  side: Type.Optional(Type.String({\n    description: '\"buy\" or \"sell\" (auto-inferred from order type if omitted)',\n  })),\n  amount_pct: Type.Optional(Type.Number({\n    description: 'Percentage of holdings to trade (1-100)',\n  })),\n  amount_raw: Type.Optional(Type.String({\n    description: 'Absolute amount to trade',\n  })),\n  slippage_bps: Type.Optional(Type.Number({\n    description: 'Slippage tolerance in basis points (default: 200 = 2%)',\n  })),\n  order_id: Type.Optional(Type.String({\n    description: 'Order ID for cancel/executed/failed/pause/resume',\n  })),\n  tag: Type.Optional(Type.String({\n    description: 'Tag for grouping orders / bulk cancel',\n  })),\n  current_price: Type.Optional(Type.String({\n    description: 'Current price in ETH for \"check\" action (auto-fetched from DexScreener if omitted)',\n  })),\n  execution_result: Type.Optional(Type.String({\n    description: 'Execution result string for \"executed\" action',\n  })),\n  description: Type.Optional(Type.String({\n    description: 'Human-readable order description',\n  })),\n  // DCA params\n  dca_interval_hours: Type.Optional(Type.Number({ description: 'Hours between DCA buys' })),\n  dca_max_buys: Type.Optional(Type.Number({ description: 'Maximum DCA iterations' })),\n  // Trailing stop params\n  trailing_pct: Type.Optional(Type.Number({ description: 'Trailing stop: % drop from peak to trigger' })),\n  floor_price: Type.Optional(Type.String({ description: 'Trailing stop: absolute floor price in ETH' })),\n  // TWAP params\n  twap_chunks: Type.Optional(Type.Number({ description: 'TWAP: number of chunks' })),\n  twap_window_hours: Type.Optional(Type.Number({ description: 'TWAP: time window in hours' })),\n  twap_max_price: Type.Optional(Type.String({ description: 'TWAP: max price ceiling in ETH' })),\n  twap_min_price: Type.Optional(Type.String({ description: 'TWAP: min price floor in ETH' })),\n  // Chaining params\n  chain_type: Type.Optional(Type.String({ description: 'Follow-up order type after this one executes' })),\n  chain_trigger_price: Type.Optional(Type.String({ description: 'Follow-up trigger price' })),\n  chain_side: Type.Optional(Type.String({ description: 'Follow-up side: buy or sell' })),\n  chain_amount_pct: Type.Optional(Type.Number({ description: 'Follow-up amount %' })),\n});\n\n// In-memory storage with file-based persistence on shutdown/startup\nlet _orders: any[] = [];\nlet _riskConfig: any = null;\nlet _ordersInstance: any = null;\n\nfunction getOrdersInstance(): any {\n  if (_ordersInstance) return _ordersInstance;\n\n  // Lazy import to avoid hard dep at load time\n  const storage = {\n    getOrders: () => _orders,\n    saveOrders: (orders: any[]) => { _orders = orders; },\n  };\n  const riskStorage = {\n    getRiskConfig: () => _riskConfig,\n    saveRiskConfig: (config: any) => { _riskConfig = config; },\n  };\n\n  // We'll initialize synchronously since ClawnchOrders doesn't need async\n  return null; // will be created on first call\n}\n\nasync function ensureOrders(): Promise<any> {\n  if (_ordersInstance) return _ordersInstance;\n  const { ClawnchOrders } = await import('@clawnch/clawncher-sdk');\n  const storage = {\n    getOrders: () => _orders,\n    saveOrders: (orders: any[]) => { _orders = orders; },\n  };\n  const riskStorage = {\n    getRiskConfig: () => _riskConfig,\n    saveRiskConfig: (config: any) => { _riskConfig = config; },\n  };\n  _ordersInstance = new ClawnchOrders(storage, riskStorage);\n  return _ordersInstance;\n}\n\nexport function createManageOrdersTool() {\n  return {\n    name: 'manage_orders',\n    label: 'Manage Orders',\n    ownerOnly: true,\n    description:\n      'Create and manage conditional orders: limit buy/sell, stop-loss, take-profit, ' +\n      'DCA, trailing stop, TWAP. Supports order chaining (e.g., buy then set stop-loss). ' +\n      'Includes risk management with position sizing, drawdown circuit breaker, and rate limiting.',\n    parameters: ManageOrdersSchema,\n    execute: async (_toolCallId: string, args: unknown) => {\n      const p = args as Record<string, unknown>;\n      const action = readStringParam(p, 'action', { required: true })!;\n\n      try {\n        const orders = await ensureOrders();\n\n        switch (action) {\n          case 'create': {\n            const orderType = readStringParam(p, 'type', { required: true })!;\n            const token = readStringParam(p, 'token') || '0x0000000000000000000000000000000000000000';\n            const triggerPrice = parseFloat(readStringParam(p, 'trigger_price', { required: true })!);\n\n            // Auto-infer side from order type\n            let side = readStringParam(p, 'side');\n            if (!side) {\n              if (orderType.includes('buy') || orderType === 'dca') side = 'buy';\n              else if (orderType.includes('sell') || orderType === 'stop_loss' || orderType === 'take_profit') side = 'sell';\n              else side = 'buy';\n            }\n\n            const orderAction: any = {\n              side,\n              amountPct: readNumberParam(p, 'amount_pct'),\n              amountRaw: readStringParam(p, 'amount_raw'),\n              slippageBps: readNumberParam(p, 'slippage_bps') ?? 200,\n            };\n\n            const createParams: any = {\n              type: orderType,\n              token,\n              triggerPriceEth: triggerPrice,\n              action: orderAction,\n              description: readStringParam(p, 'description'),\n              tag: readStringParam(p, 'tag'),\n            };\n\n            // DCA config\n            const dcaInterval = readNumberParam(p, 'dca_interval_hours');\n            if (dcaInterval) {\n              createParams.dca = {\n                intervalMs: dcaInterval * 3600 * 1000,\n                amountEthPerBuy: triggerPrice, // simplified\n                maxBuys: readNumberParam(p, 'dca_max_buys') ?? null,\n              };\n            }\n\n            // Trailing stop config\n            const trailingPct = readNumberParam(p, 'trailing_pct');\n            if (trailingPct) {\n              createParams.trailing = {\n                pct: trailingPct,\n                floorPriceEth: readStringParam(p, 'floor_price')\n                  ? parseFloat(readStringParam(p, 'floor_price')!)\n                  : undefined,\n              };\n            }\n\n            // TWAP config\n            const twapChunks = readNumberParam(p, 'twap_chunks');\n            if (twapChunks) {\n              const windowHours = readNumberParam(p, 'twap_window_hours') ?? 4;\n              createParams.twap = {\n                totalChunks: twapChunks,\n                windowMs: windowHours * 3600 * 1000,\n                chunkIntervalMs: (windowHours * 3600 * 1000) / twapChunks,\n                maxPriceEth: readStringParam(p, 'twap_max_price')\n                  ? parseFloat(readStringParam(p, 'twap_max_price')!)\n                  : undefined,\n                minPriceEth: readStringParam(p, 'twap_min_price')\n                  ? parseFloat(readStringParam(p, 'twap_min_price')!)\n                  : undefined,\n              };\n            }\n\n            // Chaining\n            const chainType = readStringParam(p, 'chain_type');\n            if (chainType) {\n              createParams.chain = [{\n                type: chainType,\n                triggerPriceEth: readStringParam(p, 'chain_trigger_price')\n                  ? parseFloat(readStringParam(p, 'chain_trigger_price')!)\n                  : triggerPrice,\n                action: {\n                  side: readStringParam(p, 'chain_side') || (chainType.includes('sell') ? 'sell' : 'buy'),\n                  amountPct: readNumberParam(p, 'chain_amount_pct') ?? 100,\n                },\n              }];\n            }\n\n            const order = orders.create(createParams);\n            return jsonResult({\n              status: 'created',\n              order: {\n                id: order.id,\n                type: order.type,\n                token: order.token,\n                triggerPrice: order.condition.triggerPriceEth,\n                side: order.action.side,\n                status: order.status,\n                tag: order.tag,\n                description: order.description,\n                hasChain: !!order.chain?.length,\n              },\n            });\n          }\n\n          case 'list': {\n            const allOrders = orders.list();\n            const riskSummary = orders.getRiskSummary();\n            return jsonResult({\n              orders: allOrders.map((o: any) => ({\n                id: o.id,\n                type: o.type,\n                status: o.status,\n                token: o.token,\n                triggerPrice: o.condition.triggerPriceEth,\n                side: o.action.side,\n                tag: o.tag,\n                description: o.description,\n                createdAt: o.createdAt,\n                executedAt: o.executedAt,\n              })),\n              count: allOrders.length,\n              riskSummary,\n            });\n          }\n\n          case 'cancel': {\n            const orderId = readStringParam(p, 'order_id', { required: true })!;\n            const success = orders.cancel(orderId);\n            return jsonResult({ status: success ? 'cancelled' : 'not_found', orderId });\n          }\n\n          case 'cancel_tag': {\n            const tag = readStringParam(p, 'tag', { required: true })!;\n            const count = orders.cancelByTag(tag);\n            return jsonResult({ status: 'cancelled', tag, count });\n          }\n\n          case 'check': {\n            let price: number;\n            let priceSource: string;\n            const manualPrice = readStringParam(p, 'current_price');\n\n            if (manualPrice) {\n              price = parseFloat(manualPrice);\n              priceSource = 'manual';\n            } else {\n              // Auto-fetch price from DexScreener via the price service.\n              // Use the token from the first active order, or require a token param.\n              const activeOrders = orders.list().filter(\n                (o: any) => o.status === 'active' || o.status === 'pending',\n              );\n              const token = readStringParam(p, 'token') || activeOrders[0]?.token;\n\n              if (!token || token === '0x0000000000000000000000000000000000000000') {\n                return errorResult(\n                  'No price provided and no token to look up. ' +\n                  'Pass current_price or token parameter, or create an order with a real token address first.'\n                );\n              }\n\n              try {\n                const priceResult = await getPrice(token);\n                price = priceResult.priceEth;\n                priceSource = `auto:${priceResult.source}:${priceResult.symbol}`;\n\n                if (price === 0) {\n                  return errorResult(\n                    `Could not fetch price for token ${token}. Pass current_price manually.`\n                  );\n                }\n              } catch (err) {\n                return errorResult(\n                  `Price fetch failed: ${err instanceof Error ? err.message : String(err)}. ` +\n                  `Pass current_price manually.`\n                );\n              }\n            }\n\n            const triggered = orders.checkTriggers(price);\n            return jsonResult({\n              currentPrice: price,\n              priceSource,\n              triggered: triggered.map((o: any) => ({\n                id: o.id,\n                type: o.type,\n                token: o.token,\n                triggerPrice: o.condition.triggerPriceEth,\n                side: o.action.side,\n                note: 'Use defi_swap tool to execute this order, then call manage_orders with action \"executed\".',\n              })),\n              count: triggered.length,\n              hint: triggered.length > 0\n                ? 'Orders triggered! Execute them with defi_swap, then mark as executed.'\n                : 'No orders triggered at this price.',\n            });\n          }\n\n          case 'executed': {\n            const orderId = readStringParam(p, 'order_id', { required: true })!;\n            const result = readStringParam(p, 'execution_result') || 'executed';\n            const chained = orders.markExecuted(orderId, result);\n            return jsonResult({\n              status: 'executed',\n              orderId,\n              chainedOrders: chained.map((o: any) => ({\n                id: o.id,\n                type: o.type,\n                triggerPrice: o.condition.triggerPriceEth,\n              })),\n            });\n          }\n\n          case 'failed': {\n            const orderId = readStringParam(p, 'order_id', { required: true })!;\n            orders.markPending(orderId);\n            orders.recordFailure();\n            return jsonResult({ status: 'reverted_to_pending', orderId, note: 'Failure cooldown activated.' });\n          }\n\n          case 'pause': {\n            const orderId = readStringParam(p, 'order_id', { required: true })!;\n            const success = orders.pause(orderId);\n            return jsonResult({ status: success ? 'paused' : 'not_found', orderId });\n          }\n\n          case 'resume': {\n            const orderId = readStringParam(p, 'order_id', { required: true })!;\n            const success = orders.resume(orderId);\n            return jsonResult({ status: success ? 'resumed' : 'not_found', orderId });\n          }\n\n          case 'risk': {\n            const summary = orders.getRiskSummary();\n            const config = orders.getRiskConfig();\n            return jsonResult({ summary, config });\n          }\n\n          case 'reset_circuit_breaker': {\n            orders.resetCircuitBreaker();\n            return jsonResult({ status: 'circuit_breaker_reset' });\n          }\n\n          case 'cleanup': {\n            const removed = orders.cleanup();\n            return jsonResult({ status: 'cleanup_complete', removedCount: removed });\n          }\n\n          default:\n            return errorResult(`Unknown orders action: ${action}`);\n        }\n      } catch (err) {\n        return errorResult(`Orders error: ${err instanceof Error ? err.message : String(err)}`);\n      }\n    },\n  };\n}\n\n// ── Persistence ──────────────────────────────────────────────────────────\n\nfunction getOrdersStateDir(): string {\n  return process.env.OPENCLAWNCH_TX_DIR\n    ? join(process.env.OPENCLAWNCH_TX_DIR, '..', 'orders')\n    : join(process.env.HOME ?? '/tmp', '.openclawnch', 'orders');\n}\n\nfunction getOrdersStatePath(): string {\n  return join(getOrdersStateDir(), 'orders.json');\n}\n\nfunction getRiskStatePath(): string {\n  return join(getOrdersStateDir(), 'risk-config.json');\n}\n\n/** Persist orders and risk config to disk. Called on graceful shutdown. */\nexport function persistOrders(): void {\n  if (_orders.length === 0 && !_riskConfig) return;\n\n  const dir = getOrdersStateDir();\n  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\n  if (_orders.length > 0) {\n    writeFileSync(getOrdersStatePath(), JSON.stringify(_orders, null, 2), 'utf8');\n  }\n  if (_riskConfig) {\n    writeFileSync(getRiskStatePath(), JSON.stringify(_riskConfig, null, 2), 'utf8');\n  }\n}\n\n/** Restore orders and risk config from disk. Called on startup. */\nexport function restoreOrders(): void {\n  try {\n    const ordersPath = getOrdersStatePath();\n    if (existsSync(ordersPath)) {\n      _orders = JSON.parse(readFileSync(ordersPath, 'utf8'));\n    }\n  } catch { /* corrupt file — start fresh */ }\n\n  try {\n    const riskPath = getRiskStatePath();\n    if (existsSync(riskPath)) {\n      _riskConfig = JSON.parse(readFileSync(riskPath, 'utf8'));\n    }\n  } catch { /* corrupt file — start fresh */ }\n\n  // Reset the instance so next ensureOrders() call picks up restored data\n  _ordersInstance = null;\n}\n"],"mappings":"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"}