@continuumdao/continuum-node-sdk 1.3.30 → 1.3.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/dist/agent-host-catalog.json +7 -0
  2. package/dist/core/chart/analysis/analysis-agent-view.d.ts.map +1 -1
  3. package/dist/core/chart/analysis/analysis-agent-view.js +48 -7
  4. package/dist/core/chart/analysis/analysis-agent-view.js.map +1 -1
  5. package/dist/core/chart/analysis/analysis-catalog.d.ts +19 -13
  6. package/dist/core/chart/analysis/analysis-catalog.d.ts.map +1 -1
  7. package/dist/core/chart/analysis/analysis-catalog.js +132 -106
  8. package/dist/core/chart/analysis/analysis-catalog.js.map +1 -1
  9. package/dist/core/chart/analysis/elliott-wave-drawings-tools.d.ts +31 -0
  10. package/dist/core/chart/analysis/elliott-wave-drawings-tools.d.ts.map +1 -0
  11. package/dist/core/chart/analysis/elliott-wave-drawings-tools.js +301 -0
  12. package/dist/core/chart/analysis/elliott-wave-drawings-tools.js.map +1 -0
  13. package/dist/core/chart/analysis/elliott-waves-analyze-tools.d.ts +161 -0
  14. package/dist/core/chart/analysis/elliott-waves-analyze-tools.d.ts.map +1 -0
  15. package/dist/core/chart/analysis/elliott-waves-analyze-tools.js +139 -0
  16. package/dist/core/chart/analysis/elliott-waves-analyze-tools.js.map +1 -0
  17. package/dist/core/chart/analysis/trade-setups/build-trade-uniswap-limit.d.ts +10 -0
  18. package/dist/core/chart/analysis/trade-setups/build-trade-uniswap-limit.d.ts.map +1 -0
  19. package/dist/core/chart/analysis/trade-setups/build-trade-uniswap-limit.js +123 -0
  20. package/dist/core/chart/analysis/trade-setups/build-trade-uniswap-limit.js.map +1 -0
  21. package/dist/core/chart/analysis/trade-setups/build-trade.d.ts +29 -1
  22. package/dist/core/chart/analysis/trade-setups/build-trade.d.ts.map +1 -1
  23. package/dist/core/chart/analysis/trade-setups/build-trade.js +267 -8
  24. package/dist/core/chart/analysis/trade-setups/build-trade.js.map +1 -1
  25. package/dist/core/chart/analysis/trade-setups/elliott-waves-trade-setup.d.ts +50 -0
  26. package/dist/core/chart/analysis/trade-setups/elliott-waves-trade-setup.d.ts.map +1 -0
  27. package/dist/core/chart/analysis/trade-setups/elliott-waves-trade-setup.js +116 -0
  28. package/dist/core/chart/analysis/trade-setups/elliott-waves-trade-setup.js.map +1 -0
  29. package/dist/core/chart/analysis/trade-setups/shared.d.ts +1 -1
  30. package/dist/core/chart/analysis/trade-setups/shared.d.ts.map +1 -1
  31. package/dist/core/chart/analysis/trade-setups/shared.js +2 -0
  32. package/dist/core/chart/analysis/trade-setups/shared.js.map +1 -1
  33. package/dist/core/chart/analysis/trade-setups/trade-desk-defaults.d.ts +13 -1
  34. package/dist/core/chart/analysis/trade-setups/trade-desk-defaults.d.ts.map +1 -1
  35. package/dist/core/chart/analysis/trade-setups/trade-desk-defaults.js +11 -0
  36. package/dist/core/chart/analysis/trade-setups/trade-desk-defaults.js.map +1 -1
  37. package/dist/core/chart/analysis/trade-setups/trade-idea-list.d.ts +2 -0
  38. package/dist/core/chart/analysis/trade-setups/trade-idea-list.d.ts.map +1 -1
  39. package/dist/core/chart/analysis/trade-setups/trade-idea-list.js +38 -3
  40. package/dist/core/chart/analysis/trade-setups/trade-idea-list.js.map +1 -1
  41. package/dist/core/chart/analysis/trade-setups/trade-idea.d.ts +4 -0
  42. package/dist/core/chart/analysis/trade-setups/trade-idea.d.ts.map +1 -1
  43. package/dist/core/chart/analysis/trade-setups/trade-idea.js +4 -0
  44. package/dist/core/chart/analysis/trade-setups/trade-idea.js.map +1 -1
  45. package/dist/core/chart/analysis/trade-setups/trade-purpose-format.d.ts +2 -0
  46. package/dist/core/chart/analysis/trade-setups/trade-purpose-format.d.ts.map +1 -1
  47. package/dist/core/chart/analysis/trade-setups/trade-purpose-format.js +6 -0
  48. package/dist/core/chart/analysis/trade-setups/trade-purpose-format.js.map +1 -1
  49. package/dist/core/chart/analysis/trade-setups/trade-setup-selection.d.ts +8 -1
  50. package/dist/core/chart/analysis/trade-setups/trade-setup-selection.d.ts.map +1 -1
  51. package/dist/core/chart/analysis/trade-setups/trade-setup-selection.js +13 -0
  52. package/dist/core/chart/analysis/trade-setups/trade-setup-selection.js.map +1 -1
  53. package/dist/core/chart/analysis/trade-setups/trend-structure-trade-setup.d.ts +20 -0
  54. package/dist/core/chart/analysis/trade-setups/trend-structure-trade-setup.d.ts.map +1 -1
  55. package/dist/core/chart/analysis/trade-setups/trend-structure-trade-setup.js +54 -0
  56. package/dist/core/chart/analysis/trade-setups/trend-structure-trade-setup.js.map +1 -1
  57. package/dist/core/chart/analysis/trade-setups/uniswap-tpsl-monitor.d.ts +41 -0
  58. package/dist/core/chart/analysis/trade-setups/uniswap-tpsl-monitor.d.ts.map +1 -0
  59. package/dist/core/chart/analysis/trade-setups/uniswap-tpsl-monitor.js +80 -0
  60. package/dist/core/chart/analysis/trade-setups/uniswap-tpsl-monitor.js.map +1 -0
  61. package/dist/core/chart/fetch-agent-view.d.ts +17 -0
  62. package/dist/core/chart/fetch-agent-view.d.ts.map +1 -0
  63. package/dist/core/chart/fetch-agent-view.js +39 -0
  64. package/dist/core/chart/fetch-agent-view.js.map +1 -0
  65. package/dist/core/chart/live/binding-extract.d.ts.map +1 -1
  66. package/dist/core/chart/live/binding-extract.js +34 -2
  67. package/dist/core/chart/live/binding-extract.js.map +1 -1
  68. package/dist/core/chart/live/fetch-tick.d.ts.map +1 -1
  69. package/dist/core/chart/live/fetch-tick.js +25 -1
  70. package/dist/core/chart/live/fetch-tick.js.map +1 -1
  71. package/dist/core/chart/live/index.d.ts +1 -1
  72. package/dist/core/chart/live/index.d.ts.map +1 -1
  73. package/dist/core/chart/live/index.js +1 -1
  74. package/dist/core/chart/live/index.js.map +1 -1
  75. package/dist/core/chart/live/schemas.d.ts +1 -0
  76. package/dist/core/chart/live/schemas.d.ts.map +1 -1
  77. package/dist/core/chart/live/schemas.js +1 -0
  78. package/dist/core/chart/live/schemas.js.map +1 -1
  79. package/dist/core/chart/overlay-schemas.d.ts +241 -0
  80. package/dist/core/chart/overlay-schemas.d.ts.map +1 -1
  81. package/dist/core/chart/overlay-schemas.js +63 -0
  82. package/dist/core/chart/overlay-schemas.js.map +1 -1
  83. package/dist/core/chart/overlays.d.ts.map +1 -1
  84. package/dist/core/chart/overlays.js +72 -1
  85. package/dist/core/chart/overlays.js.map +1 -1
  86. package/dist/core/chart/prepare-from-rows.d.ts +60 -0
  87. package/dist/core/chart/prepare-from-rows.d.ts.map +1 -1
  88. package/dist/core/chart/schemas.d.ts +240 -0
  89. package/dist/core/chart/schemas.d.ts.map +1 -1
  90. package/dist/core/coinmarketcap/schemas.d.ts +2 -2
  91. package/dist/core/elliott-waves/analyze.d.ts +38 -0
  92. package/dist/core/elliott-waves/analyze.d.ts.map +1 -0
  93. package/dist/core/elliott-waves/analyze.js +276 -0
  94. package/dist/core/elliott-waves/analyze.js.map +1 -0
  95. package/dist/core/elliott-waves/constants.d.ts +24 -0
  96. package/dist/core/elliott-waves/constants.d.ts.map +1 -0
  97. package/dist/core/elliott-waves/constants.js +24 -0
  98. package/dist/core/elliott-waves/constants.js.map +1 -0
  99. package/dist/core/elliott-waves/data-requirements.d.ts +22 -0
  100. package/dist/core/elliott-waves/data-requirements.d.ts.map +1 -0
  101. package/dist/core/elliott-waves/data-requirements.js +105 -0
  102. package/dist/core/elliott-waves/data-requirements.js.map +1 -0
  103. package/dist/core/elliott-waves/fibonacci-projector.d.ts +7 -0
  104. package/dist/core/elliott-waves/fibonacci-projector.d.ts.map +1 -0
  105. package/dist/core/elliott-waves/fibonacci-projector.js +20 -0
  106. package/dist/core/elliott-waves/fibonacci-projector.js.map +1 -0
  107. package/dist/core/elliott-waves/impulse-detector.d.ts +11 -0
  108. package/dist/core/elliott-waves/impulse-detector.d.ts.map +1 -0
  109. package/dist/core/elliott-waves/impulse-detector.js +294 -0
  110. package/dist/core/elliott-waves/impulse-detector.js.map +1 -0
  111. package/dist/core/elliott-waves/index.d.ts +10 -0
  112. package/dist/core/elliott-waves/index.d.ts.map +1 -0
  113. package/dist/core/elliott-waves/index.js +10 -0
  114. package/dist/core/elliott-waves/index.js.map +1 -0
  115. package/dist/core/elliott-waves/pivot-scanner.d.ts +40 -0
  116. package/dist/core/elliott-waves/pivot-scanner.d.ts.map +1 -0
  117. package/dist/core/elliott-waves/pivot-scanner.js +121 -0
  118. package/dist/core/elliott-waves/pivot-scanner.js.map +1 -0
  119. package/dist/core/elliott-waves/projection-builder.d.ts +32 -0
  120. package/dist/core/elliott-waves/projection-builder.d.ts.map +1 -0
  121. package/dist/core/elliott-waves/projection-builder.js +153 -0
  122. package/dist/core/elliott-waves/projection-builder.js.map +1 -0
  123. package/dist/core/elliott-waves/types.d.ts +117 -0
  124. package/dist/core/elliott-waves/types.d.ts.map +1 -0
  125. package/dist/core/elliott-waves/types.js +6 -0
  126. package/dist/core/elliott-waves/types.js.map +1 -0
  127. package/dist/core/elliott-waves/wave-labeler.d.ts +34 -0
  128. package/dist/core/elliott-waves/wave-labeler.d.ts.map +1 -0
  129. package/dist/core/elliott-waves/wave-labeler.js +95 -0
  130. package/dist/core/elliott-waves/wave-labeler.js.map +1 -0
  131. package/dist/core/elliott-waves/wave-math.d.ts +10 -0
  132. package/dist/core/elliott-waves/wave-math.d.ts.map +1 -0
  133. package/dist/core/elliott-waves/wave-math.js +61 -0
  134. package/dist/core/elliott-waves/wave-math.js.map +1 -0
  135. package/dist/core/mpc/broadcast-sign-result.d.ts +1 -0
  136. package/dist/core/mpc/broadcast-sign-result.d.ts.map +1 -1
  137. package/dist/core/mpc/broadcast-sign-result.js +129 -0
  138. package/dist/core/mpc/broadcast-sign-result.js.map +1 -1
  139. package/dist/core/mpc/deliver-arcus-exchange.d.ts +17 -0
  140. package/dist/core/mpc/deliver-arcus-exchange.d.ts.map +1 -0
  141. package/dist/core/mpc/deliver-arcus-exchange.js +380 -0
  142. package/dist/core/mpc/deliver-arcus-exchange.js.map +1 -0
  143. package/dist/core/mpc/deliver-hyperliquid-exchange.d.ts +13 -0
  144. package/dist/core/mpc/deliver-hyperliquid-exchange.d.ts.map +1 -0
  145. package/dist/core/mpc/deliver-hyperliquid-exchange.js +93 -0
  146. package/dist/core/mpc/deliver-hyperliquid-exchange.js.map +1 -0
  147. package/dist/core/mpc/deliver-personal-sign.d.ts +13 -0
  148. package/dist/core/mpc/deliver-personal-sign.d.ts.map +1 -0
  149. package/dist/core/mpc/deliver-personal-sign.js +17 -0
  150. package/dist/core/mpc/deliver-personal-sign.js.map +1 -0
  151. package/dist/core/mpc/deliver-uniswapx-limit-order.d.ts +6 -0
  152. package/dist/core/mpc/deliver-uniswapx-limit-order.d.ts.map +1 -0
  153. package/dist/core/mpc/deliver-uniswapx-limit-order.js +59 -0
  154. package/dist/core/mpc/deliver-uniswapx-limit-order.js.map +1 -0
  155. package/dist/core/mpc/eip712-sign-request.d.ts +8 -0
  156. package/dist/core/mpc/eip712-sign-request.d.ts.map +1 -0
  157. package/dist/core/mpc/eip712-sign-request.js +65 -0
  158. package/dist/core/mpc/eip712-sign-request.js.map +1 -0
  159. package/dist/core/mpc/trigger-sign-result.d.ts.map +1 -1
  160. package/dist/core/mpc/trigger-sign-result.js +15 -1
  161. package/dist/core/mpc/trigger-sign-result.js.map +1 -1
  162. package/dist/mcp/agent-host-catalog.d.ts +1 -1
  163. package/dist/mcp/agent-host-catalog.d.ts.map +1 -1
  164. package/dist/mcp/agent-host-catalog.js +2 -1
  165. package/dist/mcp/agent-host-catalog.js.map +1 -1
  166. package/dist/mcp/chart.d.ts.map +1 -1
  167. package/dist/mcp/chart.js +33 -4
  168. package/dist/mcp/chart.js.map +1 -1
  169. package/dist/mcp/deferred/tool-group-map.d.ts.map +1 -1
  170. package/dist/mcp/deferred/tool-group-map.js +7 -0
  171. package/dist/mcp/deferred/tool-group-map.js.map +1 -1
  172. package/dist/mcp/defi/bitquery-api-key.d.ts +16 -0
  173. package/dist/mcp/defi/bitquery-api-key.d.ts.map +1 -0
  174. package/dist/mcp/defi/bitquery-api-key.js +86 -0
  175. package/dist/mcp/defi/bitquery-api-key.js.map +1 -0
  176. package/dist/mcp/defi/catalog-adapter.d.ts +3 -2
  177. package/dist/mcp/defi/catalog-adapter.d.ts.map +1 -1
  178. package/dist/mcp/defi/catalog-adapter.js +7 -2
  179. package/dist/mcp/defi/catalog-adapter.js.map +1 -1
  180. package/dist/mcp/defi/defi-protocol-fetch-meta.d.ts.map +1 -1
  181. package/dist/mcp/defi/defi-protocol-fetch-meta.js +8 -4
  182. package/dist/mcp/defi/defi-protocol-fetch-meta.js.map +1 -1
  183. package/dist/mcp/defi/eip712-multisign.d.ts +26 -0
  184. package/dist/mcp/defi/eip712-multisign.d.ts.map +1 -0
  185. package/dist/mcp/defi/eip712-multisign.js +74 -0
  186. package/dist/mcp/defi/eip712-multisign.js.map +1 -0
  187. package/dist/mcp/defi/handler.d.ts.map +1 -1
  188. package/dist/mcp/defi/handler.js +46 -29
  189. package/dist/mcp/defi/handler.js.map +1 -1
  190. package/dist/mcp/defi/ohlcv-chart-workflow.d.ts +4 -2
  191. package/dist/mcp/defi/ohlcv-chart-workflow.d.ts.map +1 -1
  192. package/dist/mcp/defi/ohlcv-chart-workflow.js +20 -8
  193. package/dist/mcp/defi/ohlcv-chart-workflow.js.map +1 -1
  194. package/dist/mcp/defi/register-protocol-tools.d.ts.map +1 -1
  195. package/dist/mcp/defi/register-protocol-tools.js +36 -5
  196. package/dist/mcp/defi/register-protocol-tools.js.map +1 -1
  197. package/dist/mcp/defi/tool-schemas.d.ts +1 -3
  198. package/dist/mcp/defi/tool-schemas.d.ts.map +1 -1
  199. package/dist/mcp/defi/uniswap-api-key.d.ts.map +1 -1
  200. package/dist/mcp/defi/uniswap-api-key.js +3 -0
  201. package/dist/mcp/defi/uniswap-api-key.js.map +1 -1
  202. package/dist/mcp/defi/uniswap-limit-order-input.d.ts +10 -0
  203. package/dist/mcp/defi/uniswap-limit-order-input.d.ts.map +1 -0
  204. package/dist/mcp/defi/uniswap-limit-order-input.js +39 -0
  205. package/dist/mcp/defi/uniswap-limit-order-input.js.map +1 -0
  206. package/dist/mcp/defi/uniswap-quote-input.d.ts.map +1 -1
  207. package/dist/mcp/defi/uniswap-quote-input.js +45 -26
  208. package/dist/mcp/defi/uniswap-quote-input.js.map +1 -1
  209. package/dist/mcp/defi/uniswap-v4-ohlcv-chains.d.ts +2 -2
  210. package/dist/mcp/defi/uniswap-v4-ohlcv-chains.js +3 -3
  211. package/dist/mcp/defi/uniswap-v4-ohlcv-chains.js.map +1 -1
  212. package/dist/mcp/ohlcv-session-wrapper.d.ts.map +1 -1
  213. package/dist/mcp/ohlcv-session-wrapper.js +56 -2
  214. package/dist/mcp/ohlcv-session-wrapper.js.map +1 -1
  215. package/dist/mcp/resources/agent-cron-jobs.md +22 -1
  216. package/dist/mcp/resources/chart-analysis.md +37 -3
  217. package/dist/mcp/resources/chart.md +5 -2
  218. package/dist/mcp/resources/uniswap-tpsl-monitor-cron.example.md +27 -0
  219. package/dist/mcp/trade-tools.d.ts.map +1 -1
  220. package/dist/mcp/trade-tools.js +192 -4
  221. package/dist/mcp/trade-tools.js.map +1 -1
  222. package/package.json +2 -2
@@ -0,0 +1,123 @@
1
+ import { getMcpToolDefinitions } from '@continuumdao/ctm-mpc-defi/agent';
2
+ import { resolveTokenFromRegistry } from '../../../registry/tokens.js';
3
+ import { executeDefiMcpTool } from '../../../../mcp/defi/handler.js';
4
+ import { formatHumanPrice, validateBuildTradePrices } from './build-trade.js';
5
+ const UNISWAP_LIMIT_QUOTE_TOOL = 'ctm_uniswap_v4_limit_order_quote';
6
+ const UNISWAP_BUILD_LIMIT_TOOL = 'ctm_uniswap_v4_build_limit_order_multisign';
7
+ const DEFAULT_COLLATERAL_SYMBOL = 'USDC';
8
+ const MAINNET_CHAIN_ID = 1;
9
+ const DEFAULT_ORDER_TTL_SEC = 7 * 24 * 60 * 60;
10
+ function findDefiTool(toolName) {
11
+ return getMcpToolDefinitions().find(tool => tool.name === toolName) ?? null;
12
+ }
13
+ function humanToBaseUnits(human, decimals) {
14
+ const trimmed = human.trim();
15
+ if (!trimmed || !/^\d+(\.\d+)?$/.test(trimmed)) {
16
+ return null;
17
+ }
18
+ const [whole, frac = ''] = trimmed.split('.');
19
+ const fracPadded = (frac + '0'.repeat(decimals)).slice(0, decimals);
20
+ const combined = `${whole}${fracPadded}`.replace(/^0+/, '') || '0';
21
+ try {
22
+ return BigInt(combined).toString();
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ function limitPriceFromEntry(entry) {
29
+ return formatHumanPrice(entry);
30
+ }
31
+ export async function buildUniswapLimitOrderFromTradeIdea(config, defiContext, idea, input) {
32
+ const chainId = input.chainId || MAINNET_CHAIN_ID;
33
+ if (chainId !== MAINNET_CHAIN_ID) {
34
+ return {
35
+ ok: false,
36
+ reason: `UniswapX limit orders require Ethereum mainnet (chainId ${MAINNET_CHAIN_ID}). Got ${chainId}.`,
37
+ };
38
+ }
39
+ if (idea.side !== 'long' && idea.side !== 'short') {
40
+ return { ok: false, reason: 'Trade idea side must be long or short for Uniswap limit orders.' };
41
+ }
42
+ const validated = validateBuildTradePrices(idea, input);
43
+ if (!validated.ok) {
44
+ return validated;
45
+ }
46
+ const symbol = idea.symbol?.trim().toUpperCase();
47
+ if (!symbol) {
48
+ return { ok: false, reason: 'Trade idea is missing symbol for Uniswap mapping.' };
49
+ }
50
+ const sizeUsd = input.sizeUsdHuman?.trim();
51
+ if (!sizeUsd) {
52
+ return { ok: false, reason: 'sizeUsdHuman is required for Uniswap limit orders.' };
53
+ }
54
+ const tokenOut = await resolveTokenFromRegistry(config, {
55
+ chainId,
56
+ tokenSymbol: idea.side === 'long' ? symbol : DEFAULT_COLLATERAL_SYMBOL,
57
+ });
58
+ if (!tokenOut.ok) {
59
+ return tokenOut;
60
+ }
61
+ const tokenIn = await resolveTokenFromRegistry(config, {
62
+ chainId,
63
+ tokenSymbol: idea.side === 'long' ? DEFAULT_COLLATERAL_SYMBOL : symbol,
64
+ });
65
+ if (!tokenIn.ok) {
66
+ return tokenIn;
67
+ }
68
+ const inDecimals = idea.side === 'long' ? 6 : 18;
69
+ const amountBase = humanToBaseUnits(sizeUsd, inDecimals);
70
+ if (!amountBase) {
71
+ return { ok: false, reason: `Invalid sizeUsdHuman ${sizeUsd} for Uniswap limit quote.` };
72
+ }
73
+ const quoteTool = findDefiTool(UNISWAP_LIMIT_QUOTE_TOOL);
74
+ const buildTool = findDefiTool(UNISWAP_BUILD_LIMIT_TOOL);
75
+ if (!quoteTool || !buildTool) {
76
+ return { ok: false, reason: 'Uniswap V4 limit order MCP tools are not registered.' };
77
+ }
78
+ const tokenInAddr = tokenIn.data.contractAddress === '0x0' ? '0x0000000000000000000000000000000000000000' : tokenIn.data.contractAddress;
79
+ const tokenOutAddr = tokenOut.data.contractAddress === '0x0' ? '0x0000000000000000000000000000000000000000' : tokenOut.data.contractAddress;
80
+ const orderDeadline = input.expiryDate != null && input.expiryDate > 0
81
+ ? Math.floor(input.expiryDate)
82
+ : Math.floor(Date.now() / 1000) + DEFAULT_ORDER_TTL_SEC;
83
+ const quoteResult = await executeDefiMcpTool(config, defiContext, quoteTool, {
84
+ type: 'EXACT_INPUT',
85
+ amount: amountBase,
86
+ limitPrice: limitPriceFromEntry(validated.data.entry),
87
+ tokenIn: tokenInAddr,
88
+ tokenOut: tokenOutAddr,
89
+ chainId,
90
+ orderDeadline,
91
+ keyGenId: input.keyGenId,
92
+ });
93
+ if (quoteResult.isError) {
94
+ const text = quoteResult.content?.[0]?.type === 'text' ? quoteResult.content[0].text : 'Uniswap limit quote failed.';
95
+ return { ok: false, reason: text };
96
+ }
97
+ const fullLimitQuote = quoteResult.structuredContent && typeof quoteResult.structuredContent === 'object'
98
+ ? quoteResult.structuredContent
99
+ : null;
100
+ if (!fullLimitQuote) {
101
+ return { ok: false, reason: 'Uniswap limit quote returned no structured content.' };
102
+ }
103
+ const buildResult = await executeDefiMcpTool(config, defiContext, buildTool, {
104
+ keyGenId: input.keyGenId,
105
+ chainId,
106
+ purposeText: input.purposeText,
107
+ fullLimitQuote,
108
+ ...(input.expiryDate != null && input.expiryDate > 0 ? { expiryDate: Math.floor(input.expiryDate) } : {}),
109
+ });
110
+ if (buildResult.isError) {
111
+ const text = buildResult.content?.[0]?.type === 'text' ? buildResult.content[0].text : 'Uniswap build_limit_order failed.';
112
+ return { ok: false, reason: text };
113
+ }
114
+ const structured = buildResult.structuredContent && typeof buildResult.structuredContent === 'object'
115
+ ? buildResult.structuredContent
116
+ : {};
117
+ const requestId = String(structured.requestId ?? '').trim();
118
+ if (!requestId) {
119
+ return { ok: false, reason: 'Uniswap build_limit_order did not return requestId.' };
120
+ }
121
+ return { ok: true, data: { requestId, mappedTool: UNISWAP_BUILD_LIMIT_TOOL } };
122
+ }
123
+ //# sourceMappingURL=build-trade-uniswap-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-trade-uniswap-limit.js","sourceRoot":"","sources":["../../../../../src/core/chart/analysis/trade-setups/build-trade-uniswap-limit.ts"],"names":[],"mappings":"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"}
@@ -3,16 +3,31 @@ import type { SdkResult } from '../../../result.js';
3
3
  import type { DefiProtocolContext } from '../../../../mcp/defi/context.js';
4
4
  import type { EntryOffsetMode, EntryProximityMode } from './pattern-limit-entry.js';
5
5
  import type { TradeIdea } from './trade-idea.js';
6
- export type BuildTradeProtocolId = 'hyperliquid' | 'gmx' | 'uniswap';
6
+ import { type HyperliquidTpslExecMode } from './trade-desk-defaults.js';
7
+ export type BuildTradeProtocolId = 'hyperliquid' | 'arcus' | 'gmx' | 'uniswap';
8
+ /** Trend structure take-profit base before desk targetOffsetPct (default: impulse-leg measured move). */
9
+ export type TakeProfitSource = 'swing' | 'impulse_leg';
10
+ export declare const DEFAULT_TREND_TAKE_PROFIT_SOURCE: TakeProfitSource;
7
11
  export type BuildTradeFromTradeIdeaInput = {
8
12
  tradeIdea: TradeIdea;
9
13
  protocolId: BuildTradeProtocolId;
10
14
  keyGenId: string;
15
+ /** Arcus paired ed25519 KeyGen id (same GroupId as secp256k1 keyGenId). */
16
+ ed25519KeyGenId?: string;
11
17
  chainId: number;
12
18
  purposeText: string;
13
19
  useCustomGas?: boolean;
20
+ /** Uniswap mainnet: market spot swap (default) or UniswapX limit order. */
21
+ orderKind?: 'market' | 'limit';
22
+ /** When true, include TP/SL monitor cron registration hints in output (Uniswap). */
23
+ enableTpslMonitor?: boolean;
14
24
  entryOffsetPct?: number;
15
25
  invalidationOffsetPct?: number;
26
+ targetOffsetPct?: number;
27
+ targetOffsetMode?: EntryProximityMode;
28
+ /** Trend structure only: impulse-leg measured move (default) or recent swing target. */
29
+ takeProfitSource?: TakeProfitSource;
30
+ tpslExecMode?: HyperliquidTpslExecMode;
16
31
  entryProximityPct?: number;
17
32
  entryProximityMode?: EntryProximityMode;
18
33
  szHuman?: string;
@@ -34,15 +49,28 @@ export type BuildTradeFromTradeIdeaOutput = {
34
49
  protocolId: BuildTradeProtocolId;
35
50
  entryPriceHuman: string;
36
51
  invalidationPriceHuman?: string;
52
+ takeProfitPriceHuman?: string;
53
+ stopLossPriceHuman?: string;
37
54
  side: TradeIdea['side'];
55
+ /** Set when enableTpslMonitor registered a cron job after build. */
56
+ tpslMonitorCron?: {
57
+ name: string;
58
+ jobId: string;
59
+ };
60
+ /** When enableTpslMonitor was requested but cron could not be created. */
61
+ tpslMonitorWarning?: string;
38
62
  };
39
63
  export declare function applyEntryOffset(price: number, side: TradeIdea['side'], offsetPct: number | undefined, mode: EntryOffsetMode): number;
40
64
  export declare function applyInvalidationOffset(price: number, side: TradeIdea['side'], offsetPct?: number): number;
41
65
  export declare function formatHumanPrice(price: number): string;
66
+ export declare function applyTargetOffset(price: number, side: TradeIdea['side'], offsetPct?: number, mode?: EntryProximityMode, atr?: number | null): number;
42
67
  export declare function validateBuildTradePrices(idea: TradeIdea, input: BuildTradeFromTradeIdeaInput): SdkResult<{
43
68
  entry: number;
44
69
  invalidation?: number;
70
+ target?: number;
45
71
  }>;
72
+ export declare function mapTradeIdeaToArcusPerpPlaceOrderInput(idea: TradeIdea, input: BuildTradeFromTradeIdeaInput): SdkResult<Record<string, unknown>>;
73
+ export declare function mapTradeIdeaToArcusSpotRfqInput(idea: TradeIdea, input: BuildTradeFromTradeIdeaInput): SdkResult<Record<string, unknown>>;
46
74
  export declare function mapTradeIdeaToHyperliquidLimitInput(idea: TradeIdea, input: BuildTradeFromTradeIdeaInput): SdkResult<Record<string, unknown>>;
47
75
  export declare function mapTradeIdeaToGmxIncreaseInput(idea: TradeIdea, input: BuildTradeFromTradeIdeaInput): SdkResult<Record<string, unknown>>;
48
76
  export declare function buildTradeFromTradeIdea(config: NodeSdkConfig, defiContext: DefiProtocolContext, input: BuildTradeFromTradeIdeaInput): Promise<SdkResult<BuildTradeFromTradeIdeaOutput>>;
@@ -1 +1 @@
1
- {"version":3,"file":"build-trade.d.ts","sourceRoot":"","sources":["../../../../../src/core/chart/analysis/trade-setups/build-trade.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-trade.d.ts","sourceRoot":"","sources":["../../../../../src/core/chart/analysis/trade-setups/build-trade.ts"],"names":[],"mappings":"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"}
@@ -2,13 +2,19 @@ import { getMcpToolDefinitions } from '@continuumdao/ctm-mpc-defi/agent';
2
2
  import { executeDefiMcpTool } from '../../../../mcp/defi/handler.js';
3
3
  import { tradeIdeaWithFibSideOverride } from './trade-idea.js';
4
4
  import { buildUniswapSpotSwapFromTradeIdea } from './build-trade-uniswap.js';
5
+ import { buildUniswapLimitOrderFromTradeIdea } from './build-trade-uniswap-limit.js';
5
6
  import { passesEntryProximityGate } from './trade-entry-gates.js';
7
+ import { hyperliquidTradeDeskDefaults, } from './trade-desk-defaults.js';
8
+ export const DEFAULT_TREND_TAKE_PROFIT_SOURCE = 'impulse_leg';
6
9
  const DEFAULT_CHAIN_BY_PROTOCOL = {
7
10
  hyperliquid: 999,
11
+ arcus: 4663,
8
12
  gmx: 42161,
9
13
  uniswap: 42161,
10
14
  };
11
15
  const HYPERLIQUID_LIMIT_TOOL = 'ctm_hyperliquid_build_limit_order_multisign';
16
+ const ARCUS_PERP_PLACE_TOOL = 'ctm_arcus_build_place_order_multisign';
17
+ const ARCUS_SPOT_RFQ_TOOL = 'ctm_arcus_spot_build_rfq_multisign';
12
18
  const GMX_INCREASE_TOOL = 'ctm_gmx_build_increase_multisign';
13
19
  function proximityFromSetup(idea) {
14
20
  const setup = idea.analysisSetup.setup;
@@ -47,6 +53,21 @@ function entryOffsetModeFromIdea(idea) {
47
53
  }
48
54
  return 'bounce';
49
55
  }
56
+ function takeProfitBasePrice(idea, input) {
57
+ const source = input.takeProfitSource ?? DEFAULT_TREND_TAKE_PROFIT_SOURCE;
58
+ if (idea.analysisSetup.kind === 'trend_structure') {
59
+ if (source === 'impulse_leg') {
60
+ const mm = idea.analysisSetup.setup.measuredMove;
61
+ if (mm != null && Number.isFinite(mm.targetPrice)) {
62
+ return mm.targetPrice;
63
+ }
64
+ }
65
+ if (source === 'swing') {
66
+ return idea.target?.price;
67
+ }
68
+ }
69
+ return idea.target?.price;
70
+ }
50
71
  export function applyEntryOffset(price, side, offsetPct, mode) {
51
72
  if (offsetPct == null || !Number.isFinite(offsetPct) || offsetPct === 0) {
52
73
  return price;
@@ -92,16 +113,68 @@ export function formatHumanPrice(price) {
92
113
  }
93
114
  return price.toFixed(6);
94
115
  }
116
+ function atrAtLastBarFromTradeIdea(idea) {
117
+ const setup = idea.analysisSetup.setup;
118
+ if ('atrAtLastBar' in setup) {
119
+ const v = setup.atrAtLastBar;
120
+ if (v != null && Number.isFinite(v) && v > 0) {
121
+ return v;
122
+ }
123
+ }
124
+ if ('atr' in setup) {
125
+ const v = setup.atr;
126
+ if (v != null && Number.isFinite(v) && v > 0) {
127
+ return v;
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ export function applyTargetOffset(price, side, offsetPct, mode = 'price', atr) {
133
+ if (offsetPct == null || !Number.isFinite(offsetPct) || offsetPct === 0) {
134
+ return price;
135
+ }
136
+ const isShort = side === 'short';
137
+ const isLong = side === 'long';
138
+ if (mode === 'atr' && atr != null && Number.isFinite(atr) && atr > 0) {
139
+ const delta = (atr * offsetPct) / 100;
140
+ if (isLong) {
141
+ return price - delta;
142
+ }
143
+ if (isShort) {
144
+ return price + delta;
145
+ }
146
+ return price;
147
+ }
148
+ const factor = offsetPct / 100;
149
+ if (isLong) {
150
+ return price * (1 - factor);
151
+ }
152
+ if (isShort) {
153
+ return price * (1 + factor);
154
+ }
155
+ return price;
156
+ }
95
157
  function resolveEffectivePrices(idea, input) {
96
158
  if (!idea.entry) {
97
159
  return null;
98
160
  }
161
+ const hlDesk = hyperliquidTradeDeskDefaults();
99
162
  const mode = entryOffsetModeFromIdea(idea);
100
163
  const entry = applyEntryOffset(idea.entry.price, idea.side, input.entryOffsetPct, mode);
101
164
  const invalidation = idea.invalidation != null
102
165
  ? applyInvalidationOffset(idea.invalidation.price, idea.side, input.invalidationOffsetPct)
103
166
  : undefined;
104
- return { entry, invalidation };
167
+ const targetBase = takeProfitBasePrice(idea, input);
168
+ const target = targetBase != null
169
+ ? (() => {
170
+ const offsetPct = input.targetOffsetPct ?? hlDesk.targetOffsetPct;
171
+ const mode = input.targetOffsetMode ?? hlDesk.targetOffsetMode;
172
+ const atr = mode === 'atr' ? atrAtLastBarFromTradeIdea(idea) : null;
173
+ const effectiveMode = mode === 'atr' && atr == null ? 'price' : mode;
174
+ return applyTargetOffset(targetBase, idea.side, offsetPct, effectiveMode, atr);
175
+ })()
176
+ : undefined;
177
+ return { entry, invalidation, target };
105
178
  }
106
179
  export function validateBuildTradePrices(idea, input) {
107
180
  if (idea.side !== 'long' && idea.side !== 'short') {
@@ -114,7 +187,7 @@ export function validateBuildTradePrices(idea, input) {
114
187
  if (!resolved) {
115
188
  return { ok: false, reason: 'Trade idea has no entry level — cannot build limit order.' };
116
189
  }
117
- const { entry, invalidation } = resolved;
190
+ const { entry, invalidation, target } = resolved;
118
191
  const lastClose = idea.lastClose;
119
192
  const mode = entryOffsetModeFromIdea(idea);
120
193
  if (mode !== 'retest') {
@@ -145,6 +218,30 @@ export function validateBuildTradePrices(idea, input) {
145
218
  };
146
219
  }
147
220
  }
221
+ if (target != null) {
222
+ if (idea.side === 'long' && target <= entry) {
223
+ return {
224
+ ok: false,
225
+ reason: 'Adjusted take-profit must sit above adjusted entry for long setups.',
226
+ };
227
+ }
228
+ if (idea.side === 'short' && target >= entry) {
229
+ return {
230
+ ok: false,
231
+ reason: 'Adjusted take-profit must sit below adjusted entry for short setups.',
232
+ };
233
+ }
234
+ }
235
+ if (input.protocolId === 'hyperliquid' && (target != null || invalidation != null)) {
236
+ if (invalidation != null && target != null) {
237
+ if (idea.side === 'long' && !(invalidation < entry && entry < target)) {
238
+ return { ok: false, reason: 'Long bracket requires SL < entry < TP after desk offsets.' };
239
+ }
240
+ if (idea.side === 'short' && !(target < entry && entry < invalidation)) {
241
+ return { ok: false, reason: 'Short bracket requires TP < entry < SL after desk offsets.' };
242
+ }
243
+ }
244
+ }
148
245
  if (input.protocolId === 'uniswap' &&
149
246
  !passesEntryProximityGate({
150
247
  lastClose,
@@ -155,7 +252,7 @@ export function validateBuildTradePrices(idea, input) {
155
252
  })) {
156
253
  return { ok: false, reason: 'Uniswap swap requires price within entry proximity of the idea entry.' };
157
254
  }
158
- return { ok: true, data: { entry, invalidation } };
255
+ return { ok: true, data: { entry, invalidation, target } };
159
256
  }
160
257
  function resolveGmxSymbol(idea) {
161
258
  const symbol = idea.symbol?.trim();
@@ -171,6 +268,106 @@ function resolveCoinSymbol(idea) {
171
268
  function findDefiTool(toolName) {
172
269
  return getMcpToolDefinitions().find(tool => tool.name === toolName) ?? null;
173
270
  }
271
+ function resolveArcusMarket(idea) {
272
+ const symbol = idea.symbol?.trim();
273
+ if (!symbol)
274
+ return null;
275
+ if (symbol.includes('-'))
276
+ return symbol.toUpperCase();
277
+ return `${symbol.toUpperCase()}-USD`;
278
+ }
279
+ function resolveArcusSpotTicker(idea) {
280
+ const symbol = idea.symbol?.trim();
281
+ if (!symbol)
282
+ return null;
283
+ return symbol.split('-')[0].toUpperCase();
284
+ }
285
+ function arcusKeyGenFields(input) {
286
+ const secp256k1KeyGenId = input.keyGenId.trim();
287
+ const ed25519KeyGenId = input.ed25519KeyGenId?.trim() ?? '';
288
+ if (!secp256k1KeyGenId) {
289
+ return { ok: false, reason: 'keyGenId (secp256k1) is required for Arcus trades.' };
290
+ }
291
+ if (!ed25519KeyGenId) {
292
+ return {
293
+ ok: false,
294
+ reason: 'ed25519KeyGenId is required for Arcus trades (paired KeyGen, same GroupId).',
295
+ };
296
+ }
297
+ return { ok: true, data: { secp256k1KeyGenId, ed25519KeyGenId } };
298
+ }
299
+ export function mapTradeIdeaToArcusPerpPlaceOrderInput(idea, input) {
300
+ if (idea.side !== 'long' && idea.side !== 'short') {
301
+ return { ok: false, reason: 'Trade idea side must be long or short for Arcus perp orders.' };
302
+ }
303
+ const market = resolveArcusMarket(idea);
304
+ if (!market) {
305
+ return { ok: false, reason: 'Trade idea is missing symbol/market for Arcus mapping.' };
306
+ }
307
+ if (!input.szHuman?.trim()) {
308
+ return { ok: false, reason: 'szHuman is required for Arcus perp orders.' };
309
+ }
310
+ const keys = arcusKeyGenFields(input);
311
+ if (!keys.ok)
312
+ return keys;
313
+ const validated = validateBuildTradePrices(idea, input);
314
+ if (!validated.ok) {
315
+ return validated;
316
+ }
317
+ const entryPx = validated.data.entry;
318
+ const tpPx = validated.data.target;
319
+ const slPx = validated.data.invalidation;
320
+ return {
321
+ ok: true,
322
+ data: {
323
+ secp256k1KeyGenId: keys.data.secp256k1KeyGenId,
324
+ ed25519KeyGenId: keys.data.ed25519KeyGenId,
325
+ chainId: input.chainId || DEFAULT_CHAIN_BY_PROTOCOL.arcus,
326
+ purposeText: input.purposeText,
327
+ market,
328
+ isBuy: idea.side === 'long',
329
+ limitPxHuman: formatHumanPrice(entryPx),
330
+ szHuman: input.szHuman.trim(),
331
+ ...(tpPx != null ? { takeProfitTriggerPxHuman: formatHumanPrice(tpPx) } : {}),
332
+ ...(slPx != null ? { stopLossTriggerPxHuman: formatHumanPrice(slPx) } : {}),
333
+ ...(input.expiryDate != null && input.expiryDate > 0 ? { expiryDate: Math.floor(input.expiryDate) } : {}),
334
+ },
335
+ };
336
+ }
337
+ export function mapTradeIdeaToArcusSpotRfqInput(idea, input) {
338
+ if (idea.side !== 'long' && idea.side !== 'short') {
339
+ return { ok: false, reason: 'Trade idea side must be long or short for Arcus spot RFQ.' };
340
+ }
341
+ const ticker = resolveArcusSpotTicker(idea);
342
+ if (!ticker) {
343
+ return { ok: false, reason: 'Trade idea is missing symbol/ticker for Arcus spot mapping.' };
344
+ }
345
+ if (!input.szHuman?.trim()) {
346
+ return { ok: false, reason: 'szHuman is required for Arcus spot RFQ (sizeHuman).' };
347
+ }
348
+ const keys = arcusKeyGenFields(input);
349
+ if (!keys.ok)
350
+ return keys;
351
+ const validated = validateBuildTradePrices(idea, input);
352
+ if (!validated.ok) {
353
+ return validated;
354
+ }
355
+ const entryPx = validated.data.entry;
356
+ return {
357
+ ok: true,
358
+ data: {
359
+ secp256k1KeyGenId: keys.data.secp256k1KeyGenId,
360
+ ed25519KeyGenId: keys.data.ed25519KeyGenId,
361
+ chainId: input.chainId || DEFAULT_CHAIN_BY_PROTOCOL.arcus,
362
+ purposeText: input.purposeText,
363
+ ticker,
364
+ isBuy: idea.side === 'long',
365
+ sizeHuman: input.szHuman.trim(),
366
+ limitPxHuman: formatHumanPrice(entryPx),
367
+ ...(input.expiryDate != null && input.expiryDate > 0 ? { expiryDate: Math.floor(input.expiryDate) } : {}),
368
+ },
369
+ };
370
+ }
174
371
  export function mapTradeIdeaToHyperliquidLimitInput(idea, input) {
175
372
  if (idea.side !== 'long' && idea.side !== 'short') {
176
373
  return { ok: false, reason: 'Trade idea side must be long or short for Hyperliquid limit orders.' };
@@ -187,6 +384,10 @@ export function mapTradeIdeaToHyperliquidLimitInput(idea, input) {
187
384
  return validated;
188
385
  }
189
386
  const entryPx = validated.data.entry;
387
+ const tpPx = validated.data.target;
388
+ const slPx = validated.data.invalidation;
389
+ const hlDesk = hyperliquidTradeDeskDefaults();
390
+ const tpslExecMode = input.tpslExecMode ?? hlDesk.tpslExecMode;
190
391
  return {
191
392
  ok: true,
192
393
  data: {
@@ -200,6 +401,9 @@ export function mapTradeIdeaToHyperliquidLimitInput(idea, input) {
200
401
  szHuman: input.szHuman.trim(),
201
402
  marketKind: input.marketKind ?? 'perp',
202
403
  tif: input.tif ?? 'gtc',
404
+ ...(tpPx != null ? { takeProfitTriggerPxHuman: formatHumanPrice(tpPx) } : {}),
405
+ ...(slPx != null ? { stopLossTriggerPxHuman: formatHumanPrice(slPx) } : {}),
406
+ ...(tpPx != null || slPx != null ? { tpslExecMode } : {}),
203
407
  ...(input.expiryDate != null && input.expiryDate > 0 ? { expiryDate: Math.floor(input.expiryDate) } : {}),
204
408
  },
205
409
  };
@@ -226,7 +430,8 @@ export function mapTradeIdeaToGmxIncreaseInput(idea, input) {
226
430
  return validated;
227
431
  }
228
432
  const triggerPx = validated.data.entry;
229
- const pfE = validated.data.invalidation;
433
+ const tpPx = validated.data.target;
434
+ const slPx = validated.data.invalidation;
230
435
  return {
231
436
  ok: true,
232
437
  data: {
@@ -241,7 +446,9 @@ export function mapTradeIdeaToGmxIncreaseInput(idea, input) {
241
446
  collateralToken: input.collateralToken.trim(),
242
447
  collateralAmountHuman: input.collateralAmountHuman.trim(),
243
448
  triggerPriceUsdHuman: formatHumanPrice(triggerPx),
244
- ...(pfE != null ? { patternFailureUsdHuman: formatHumanPrice(pfE) } : {}),
449
+ ...(tpPx != null ? { takeProfitPriceUsdHuman: formatHumanPrice(tpPx) } : {}),
450
+ ...(slPx != null ? { stopLossPriceUsdHuman: formatHumanPrice(slPx) } : {}),
451
+ ...(slPx != null ? { patternFailureUsdHuman: formatHumanPrice(slPx) } : {}),
245
452
  ...(input.slippageBps != null ? { slippageBps: input.slippageBps } : {}),
246
453
  ...(input.expiryDate != null && input.expiryDate > 0 ? { expiryDate: Math.floor(input.expiryDate) } : {}),
247
454
  },
@@ -261,6 +468,33 @@ export async function buildTradeFromTradeIdea(config, defiContext, input) {
261
468
  if (!proximity.ok) {
262
469
  return proximity;
263
470
  }
471
+ const orderKind = input.orderKind ?? 'market';
472
+ if (orderKind === 'limit') {
473
+ const built = await buildUniswapLimitOrderFromTradeIdea(config, defiContext, idea, input);
474
+ if (!built.ok) {
475
+ return built;
476
+ }
477
+ return {
478
+ ok: true,
479
+ data: {
480
+ requestId: built.data.requestId,
481
+ tradeIdeaId: idea.id,
482
+ mappedTool: built.data.mappedTool,
483
+ protocolId,
484
+ entryPriceHuman: formatHumanPrice(proximity.data.entry),
485
+ ...(proximity.data.invalidation != null
486
+ ? {
487
+ invalidationPriceHuman: formatHumanPrice(proximity.data.invalidation),
488
+ stopLossPriceHuman: formatHumanPrice(proximity.data.invalidation),
489
+ }
490
+ : {}),
491
+ ...(proximity.data.target != null
492
+ ? { takeProfitPriceHuman: formatHumanPrice(proximity.data.target) }
493
+ : {}),
494
+ side: idea.side,
495
+ },
496
+ };
497
+ }
264
498
  const built = await buildUniswapSpotSwapFromTradeIdea(config, defiContext, idea, input);
265
499
  if (!built.ok) {
266
500
  return built;
@@ -273,18 +507,37 @@ export async function buildTradeFromTradeIdea(config, defiContext, input) {
273
507
  mappedTool: built.data.mappedTool,
274
508
  protocolId,
275
509
  entryPriceHuman: formatHumanPrice(proximity.data.entry),
510
+ ...(proximity.data.invalidation != null
511
+ ? {
512
+ invalidationPriceHuman: formatHumanPrice(proximity.data.invalidation),
513
+ stopLossPriceHuman: formatHumanPrice(proximity.data.invalidation),
514
+ }
515
+ : {}),
516
+ ...(proximity.data.target != null
517
+ ? { takeProfitPriceHuman: formatHumanPrice(proximity.data.target) }
518
+ : {}),
276
519
  side: idea.side,
277
520
  },
278
521
  };
279
522
  }
280
- const mappedTool = protocolId === 'hyperliquid' ? HYPERLIQUID_LIMIT_TOOL : GMX_INCREASE_TOOL;
523
+ const mappedTool = protocolId === 'hyperliquid'
524
+ ? HYPERLIQUID_LIMIT_TOOL
525
+ : protocolId === 'arcus'
526
+ ? (input.marketKind ?? 'perp') === 'spot'
527
+ ? ARCUS_SPOT_RFQ_TOOL
528
+ : ARCUS_PERP_PLACE_TOOL
529
+ : GMX_INCREASE_TOOL;
281
530
  const tool = findDefiTool(mappedTool);
282
531
  if (!tool) {
283
532
  return { ok: false, reason: `DeFi tool ${mappedTool} is not registered.` };
284
533
  }
285
534
  const mapped = protocolId === 'hyperliquid'
286
535
  ? mapTradeIdeaToHyperliquidLimitInput(idea, input)
287
- : mapTradeIdeaToGmxIncreaseInput(idea, input);
536
+ : protocolId === 'arcus'
537
+ ? (input.marketKind ?? 'perp') === 'spot'
538
+ ? mapTradeIdeaToArcusSpotRfqInput(idea, input)
539
+ : mapTradeIdeaToArcusPerpPlaceOrderInput(idea, input)
540
+ : mapTradeIdeaToGmxIncreaseInput(idea, input);
288
541
  if (!mapped.ok) {
289
542
  return mapped;
290
543
  }
@@ -313,7 +566,13 @@ export async function buildTradeFromTradeIdea(config, defiContext, input) {
313
566
  protocolId,
314
567
  entryPriceHuman: formatHumanPrice(validated.data.entry),
315
568
  ...(validated.data.invalidation != null
316
- ? { invalidationPriceHuman: formatHumanPrice(validated.data.invalidation) }
569
+ ? {
570
+ invalidationPriceHuman: formatHumanPrice(validated.data.invalidation),
571
+ stopLossPriceHuman: formatHumanPrice(validated.data.invalidation),
572
+ }
573
+ : {}),
574
+ ...(validated.data.target != null
575
+ ? { takeProfitPriceHuman: formatHumanPrice(validated.data.target) }
317
576
  : {}),
318
577
  side: idea.side,
319
578
  },