@raintree-technology/perps 0.1.0

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 (316) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +21 -0
  3. package/README.md +175 -0
  4. package/dist/adapters/aevo.d.ts +64 -0
  5. package/dist/adapters/aevo.js +899 -0
  6. package/dist/adapters/certification.d.ts +33 -0
  7. package/dist/adapters/certification.js +99 -0
  8. package/dist/adapters/decibel/order-manager.d.ts +45 -0
  9. package/dist/adapters/decibel/order-manager.js +140 -0
  10. package/dist/adapters/decibel/rest-client.d.ts +176 -0
  11. package/dist/adapters/decibel/rest-client.js +155 -0
  12. package/dist/adapters/decibel/ws-feed.d.ts +28 -0
  13. package/dist/adapters/decibel/ws-feed.js +166 -0
  14. package/dist/adapters/decibel.d.ts +108 -0
  15. package/dist/adapters/decibel.js +1377 -0
  16. package/dist/adapters/hyperliquid.d.ts +63 -0
  17. package/dist/adapters/hyperliquid.js +797 -0
  18. package/dist/adapters/index.d.ts +11 -0
  19. package/dist/adapters/index.js +12 -0
  20. package/dist/adapters/interface.d.ts +310 -0
  21. package/dist/adapters/interface.js +15 -0
  22. package/dist/adapters/orderly.d.ts +70 -0
  23. package/dist/adapters/orderly.js +936 -0
  24. package/dist/adapters/paradex.d.ts +69 -0
  25. package/dist/adapters/paradex.js +862 -0
  26. package/dist/adapters/utils.d.ts +17 -0
  27. package/dist/adapters/utils.js +122 -0
  28. package/dist/cli/command-metadata.d.ts +2 -0
  29. package/dist/cli/command-metadata.js +44 -0
  30. package/dist/cli/context.d.ts +14 -0
  31. package/dist/cli/context.js +59 -0
  32. package/dist/cli/experience.d.ts +48 -0
  33. package/dist/cli/experience.js +243 -0
  34. package/dist/cli/ink/app/AppShell.d.ts +12 -0
  35. package/dist/cli/ink/app/AppShell.js +32 -0
  36. package/dist/cli/ink/app/MetricStrip.d.ts +6 -0
  37. package/dist/cli/ink/app/MetricStrip.js +14 -0
  38. package/dist/cli/ink/app/Panel.d.ts +9 -0
  39. package/dist/cli/ink/app/Panel.js +7 -0
  40. package/dist/cli/ink/app/ascii.d.ts +2 -0
  41. package/dist/cli/ink/app/ascii.js +46 -0
  42. package/dist/cli/ink/app/index.d.ts +5 -0
  43. package/dist/cli/ink/app/index.js +4 -0
  44. package/dist/cli/ink/app/types.d.ts +15 -0
  45. package/dist/cli/ink/app/types.js +1 -0
  46. package/dist/cli/ink/components/PnL.d.ts +12 -0
  47. package/dist/cli/ink/components/PnL.js +23 -0
  48. package/dist/cli/ink/components/Spinner.d.ts +13 -0
  49. package/dist/cli/ink/components/Spinner.js +13 -0
  50. package/dist/cli/ink/components/Table.d.ts +14 -0
  51. package/dist/cli/ink/components/Table.js +42 -0
  52. package/dist/cli/ink/components/WatchHeader.d.ts +10 -0
  53. package/dist/cli/ink/components/WatchHeader.js +18 -0
  54. package/dist/cli/ink/components/index.d.ts +4 -0
  55. package/dist/cli/ink/components/index.js +4 -0
  56. package/dist/cli/ink/index.d.ts +4 -0
  57. package/dist/cli/ink/index.js +4 -0
  58. package/dist/cli/ink/render.d.ts +12 -0
  59. package/dist/cli/ink/render.js +21 -0
  60. package/dist/cli/ink/theme.d.ts +29 -0
  61. package/dist/cli/ink/theme.js +40 -0
  62. package/dist/cli/network-defaults.d.ts +10 -0
  63. package/dist/cli/network-defaults.js +35 -0
  64. package/dist/cli/output.d.ts +11 -0
  65. package/dist/cli/output.js +115 -0
  66. package/dist/cli/program.d.ts +18 -0
  67. package/dist/cli/program.js +164 -0
  68. package/dist/cli/watch.d.ts +19 -0
  69. package/dist/cli/watch.js +35 -0
  70. package/dist/client/index.d.ts +55 -0
  71. package/dist/client/index.js +157 -0
  72. package/dist/commands/account/add.d.ts +2 -0
  73. package/dist/commands/account/add.js +510 -0
  74. package/dist/commands/account/balances-simple.d.ts +5 -0
  75. package/dist/commands/account/balances-simple.js +63 -0
  76. package/dist/commands/account/index.d.ts +2 -0
  77. package/dist/commands/account/index.js +17 -0
  78. package/dist/commands/account/ls.d.ts +2 -0
  79. package/dist/commands/account/ls.js +95 -0
  80. package/dist/commands/account/positions-simple.d.ts +5 -0
  81. package/dist/commands/account/positions-simple.js +77 -0
  82. package/dist/commands/account/remove.d.ts +2 -0
  83. package/dist/commands/account/remove.js +47 -0
  84. package/dist/commands/account/set-default.d.ts +2 -0
  85. package/dist/commands/account/set-default.js +47 -0
  86. package/dist/commands/agent/index.d.ts +2 -0
  87. package/dist/commands/agent/index.js +126 -0
  88. package/dist/commands/arb/alert.d.ts +6 -0
  89. package/dist/commands/arb/alert.js +88 -0
  90. package/dist/commands/arb/basis-execute.d.ts +6 -0
  91. package/dist/commands/arb/basis-execute.js +332 -0
  92. package/dist/commands/arb/basis.d.ts +6 -0
  93. package/dist/commands/arb/basis.js +181 -0
  94. package/dist/commands/arb/compare.d.ts +6 -0
  95. package/dist/commands/arb/compare.js +216 -0
  96. package/dist/commands/arb/execute.d.ts +6 -0
  97. package/dist/commands/arb/execute.js +467 -0
  98. package/dist/commands/arb/funding.d.ts +6 -0
  99. package/dist/commands/arb/funding.js +201 -0
  100. package/dist/commands/arb/history.d.ts +6 -0
  101. package/dist/commands/arb/history.js +153 -0
  102. package/dist/commands/arb/index.d.ts +6 -0
  103. package/dist/commands/arb/index.js +29 -0
  104. package/dist/commands/arb/positions.d.ts +6 -0
  105. package/dist/commands/arb/positions.js +158 -0
  106. package/dist/commands/arb/spread.d.ts +6 -0
  107. package/dist/commands/arb/spread.js +253 -0
  108. package/dist/commands/arb/track.d.ts +6 -0
  109. package/dist/commands/arb/track.js +259 -0
  110. package/dist/commands/asset/book-simple.d.ts +5 -0
  111. package/dist/commands/asset/book-simple.js +77 -0
  112. package/dist/commands/asset/index.d.ts +2 -0
  113. package/dist/commands/asset/index.js +5 -0
  114. package/dist/commands/completion.d.ts +2 -0
  115. package/dist/commands/completion.js +161 -0
  116. package/dist/commands/config/index.d.ts +5 -0
  117. package/dist/commands/config/index.js +109 -0
  118. package/dist/commands/data/index.d.ts +31 -0
  119. package/dist/commands/data/index.js +1466 -0
  120. package/dist/commands/doctor.d.ts +2 -0
  121. package/dist/commands/doctor.js +201 -0
  122. package/dist/commands/exchange/index.d.ts +2 -0
  123. package/dist/commands/exchange/index.js +107 -0
  124. package/dist/commands/index.d.ts +2 -0
  125. package/dist/commands/index.js +48 -0
  126. package/dist/commands/markets/index.d.ts +2 -0
  127. package/dist/commands/markets/index.js +5 -0
  128. package/dist/commands/markets/ls-simple.d.ts +7 -0
  129. package/dist/commands/markets/ls-simple.js +277 -0
  130. package/dist/commands/operator/index.d.ts +2 -0
  131. package/dist/commands/operator/index.js +146 -0
  132. package/dist/commands/order/cancel-simple.d.ts +5 -0
  133. package/dist/commands/order/cancel-simple.js +104 -0
  134. package/dist/commands/order/index.d.ts +2 -0
  135. package/dist/commands/order/index.js +13 -0
  136. package/dist/commands/order/limit-simple.d.ts +5 -0
  137. package/dist/commands/order/limit-simple.js +195 -0
  138. package/dist/commands/order/market-simple.d.ts +5 -0
  139. package/dist/commands/order/market-simple.js +190 -0
  140. package/dist/commands/order/shared.d.ts +17 -0
  141. package/dist/commands/order/shared.js +51 -0
  142. package/dist/commands/order/trigger-simple.d.ts +5 -0
  143. package/dist/commands/order/trigger-simple.js +246 -0
  144. package/dist/commands/referral/index.d.ts +2 -0
  145. package/dist/commands/referral/index.js +7 -0
  146. package/dist/commands/referral/set.d.ts +2 -0
  147. package/dist/commands/referral/set.js +26 -0
  148. package/dist/commands/referral/status.d.ts +2 -0
  149. package/dist/commands/referral/status.js +31 -0
  150. package/dist/commands/replay/index.d.ts +2 -0
  151. package/dist/commands/replay/index.js +152 -0
  152. package/dist/commands/risk/analytics.d.ts +2 -0
  153. package/dist/commands/risk/analytics.js +64 -0
  154. package/dist/commands/risk/audit.d.ts +2 -0
  155. package/dist/commands/risk/audit.js +52 -0
  156. package/dist/commands/risk/index.d.ts +2 -0
  157. package/dist/commands/risk/index.js +9 -0
  158. package/dist/commands/risk/rules.d.ts +2 -0
  159. package/dist/commands/risk/rules.js +102 -0
  160. package/dist/commands/server.d.ts +2 -0
  161. package/dist/commands/server.js +208 -0
  162. package/dist/commands/setup/index.d.ts +2 -0
  163. package/dist/commands/setup/index.js +478 -0
  164. package/dist/commands/signal/index.d.ts +2 -0
  165. package/dist/commands/signal/index.js +129 -0
  166. package/dist/commands/state/index.d.ts +2 -0
  167. package/dist/commands/state/index.js +5 -0
  168. package/dist/commands/state/show.d.ts +2 -0
  169. package/dist/commands/state/show.js +105 -0
  170. package/dist/commands/strategy/index.d.ts +4 -0
  171. package/dist/commands/strategy/index.js +73 -0
  172. package/dist/commands/traces/index.d.ts +2 -0
  173. package/dist/commands/traces/index.js +76 -0
  174. package/dist/commands/ui/demo.d.ts +9 -0
  175. package/dist/commands/ui/demo.js +195 -0
  176. package/dist/commands/ui/index.d.ts +2 -0
  177. package/dist/commands/ui/index.js +7 -0
  178. package/dist/commands/ui/terminal.d.ts +2 -0
  179. package/dist/commands/ui/terminal.js +255 -0
  180. package/dist/commands/upgrade.d.ts +2 -0
  181. package/dist/commands/upgrade.js +98 -0
  182. package/dist/index.d.ts +2 -0
  183. package/dist/index.js +4 -0
  184. package/dist/lib/agent/audit.d.ts +12 -0
  185. package/dist/lib/agent/audit.js +13 -0
  186. package/dist/lib/agent/gateway.d.ts +13 -0
  187. package/dist/lib/agent/gateway.js +598 -0
  188. package/dist/lib/agent/metrics.d.ts +33 -0
  189. package/dist/lib/agent/metrics.js +175 -0
  190. package/dist/lib/agent/signature.d.ts +8 -0
  191. package/dist/lib/agent/signature.js +28 -0
  192. package/dist/lib/agent/tools.d.ts +28 -0
  193. package/dist/lib/agent/tools.js +453 -0
  194. package/dist/lib/agent/x402.d.ts +23 -0
  195. package/dist/lib/agent/x402.js +62 -0
  196. package/dist/lib/api-wallet.d.ts +69 -0
  197. package/dist/lib/api-wallet.js +101 -0
  198. package/dist/lib/balance-watcher.d.ts +25 -0
  199. package/dist/lib/balance-watcher.js +83 -0
  200. package/dist/lib/book-watcher.d.ts +25 -0
  201. package/dist/lib/book-watcher.js +48 -0
  202. package/dist/lib/config.d.ts +88 -0
  203. package/dist/lib/config.js +427 -0
  204. package/dist/lib/constants.d.ts +50 -0
  205. package/dist/lib/constants.js +84 -0
  206. package/dist/lib/contracts.d.ts +7 -0
  207. package/dist/lib/contracts.js +8 -0
  208. package/dist/lib/credential-vault.d.ts +22 -0
  209. package/dist/lib/credential-vault.js +109 -0
  210. package/dist/lib/db/accounts.d.ts +83 -0
  211. package/dist/lib/db/accounts.js +203 -0
  212. package/dist/lib/db/funding-history.d.ts +69 -0
  213. package/dist/lib/db/funding-history.js +183 -0
  214. package/dist/lib/db/index.d.ts +11 -0
  215. package/dist/lib/db/index.js +272 -0
  216. package/dist/lib/events/bus.d.ts +10 -0
  217. package/dist/lib/events/bus.js +17 -0
  218. package/dist/lib/events/types.d.ts +51 -0
  219. package/dist/lib/events/types.js +1 -0
  220. package/dist/lib/exchange.d.ts +30 -0
  221. package/dist/lib/exchange.js +84 -0
  222. package/dist/lib/execution/journal.d.ts +25 -0
  223. package/dist/lib/execution/journal.js +158 -0
  224. package/dist/lib/execution/safety.d.ts +34 -0
  225. package/dist/lib/execution/safety.js +197 -0
  226. package/dist/lib/exit-codes.d.ts +18 -0
  227. package/dist/lib/exit-codes.js +60 -0
  228. package/dist/lib/fetch.d.ts +18 -0
  229. package/dist/lib/fetch.js +66 -0
  230. package/dist/lib/fs-security.d.ts +10 -0
  231. package/dist/lib/fs-security.js +26 -0
  232. package/dist/lib/funding-tracker.d.ts +40 -0
  233. package/dist/lib/funding-tracker.js +118 -0
  234. package/dist/lib/logger.d.ts +27 -0
  235. package/dist/lib/logger.js +82 -0
  236. package/dist/lib/network-model.d.ts +13 -0
  237. package/dist/lib/network-model.js +30 -0
  238. package/dist/lib/onboarding.d.ts +133 -0
  239. package/dist/lib/onboarding.js +1459 -0
  240. package/dist/lib/operator-state.d.ts +25 -0
  241. package/dist/lib/operator-state.js +82 -0
  242. package/dist/lib/orders-watcher.d.ts +24 -0
  243. package/dist/lib/orders-watcher.js +74 -0
  244. package/dist/lib/paths.d.ts +20 -0
  245. package/dist/lib/paths.js +23 -0
  246. package/dist/lib/portfolio-watcher.d.ts +33 -0
  247. package/dist/lib/portfolio-watcher.js +95 -0
  248. package/dist/lib/position-watcher.d.ts +16 -0
  249. package/dist/lib/position-watcher.js +44 -0
  250. package/dist/lib/price-watcher.d.ts +15 -0
  251. package/dist/lib/price-watcher.js +84 -0
  252. package/dist/lib/prompts.d.ts +32 -0
  253. package/dist/lib/prompts.js +105 -0
  254. package/dist/lib/rate-limit.d.ts +32 -0
  255. package/dist/lib/rate-limit.js +88 -0
  256. package/dist/lib/risk/analytics.d.ts +39 -0
  257. package/dist/lib/risk/analytics.js +98 -0
  258. package/dist/lib/risk/drawdown.d.ts +18 -0
  259. package/dist/lib/risk/drawdown.js +49 -0
  260. package/dist/lib/risk/evaluation-log.d.ts +29 -0
  261. package/dist/lib/risk/evaluation-log.js +61 -0
  262. package/dist/lib/risk/index.d.ts +4 -0
  263. package/dist/lib/risk/index.js +4 -0
  264. package/dist/lib/risk/limits.d.ts +23 -0
  265. package/dist/lib/risk/limits.js +27 -0
  266. package/dist/lib/risk/manager.d.ts +32 -0
  267. package/dist/lib/risk/manager.js +85 -0
  268. package/dist/lib/risk/policy-middleware.d.ts +33 -0
  269. package/dist/lib/risk/policy-middleware.js +267 -0
  270. package/dist/lib/risk/position-sizer.d.ts +9 -0
  271. package/dist/lib/risk/position-sizer.js +14 -0
  272. package/dist/lib/risk/rules-store.d.ts +16 -0
  273. package/dist/lib/risk/rules-store.js +47 -0
  274. package/dist/lib/schema.d.ts +254 -0
  275. package/dist/lib/schema.js +199 -0
  276. package/dist/lib/secrets.d.ts +3 -0
  277. package/dist/lib/secrets.js +62 -0
  278. package/dist/lib/settings.d.ts +24 -0
  279. package/dist/lib/settings.js +86 -0
  280. package/dist/lib/signals.d.ts +73 -0
  281. package/dist/lib/signals.js +136 -0
  282. package/dist/lib/stable-stringify.d.ts +6 -0
  283. package/dist/lib/stable-stringify.js +17 -0
  284. package/dist/lib/state-context.d.ts +44 -0
  285. package/dist/lib/state-context.js +133 -0
  286. package/dist/lib/strategy/basis-trade.d.ts +2 -0
  287. package/dist/lib/strategy/basis-trade.js +24 -0
  288. package/dist/lib/strategy/funding-arb.d.ts +2 -0
  289. package/dist/lib/strategy/funding-arb.js +23 -0
  290. package/dist/lib/strategy/interface.d.ts +23 -0
  291. package/dist/lib/strategy/interface.js +1 -0
  292. package/dist/lib/strategy/registry.d.ts +4 -0
  293. package/dist/lib/strategy/registry.js +10 -0
  294. package/dist/lib/telemetry.d.ts +25 -0
  295. package/dist/lib/telemetry.js +101 -0
  296. package/dist/lib/trace-queries.d.ts +20 -0
  297. package/dist/lib/trace-queries.js +133 -0
  298. package/dist/lib/trace.d.ts +1 -0
  299. package/dist/lib/trace.js +4 -0
  300. package/dist/lib/trade-reputation.d.ts +6 -0
  301. package/dist/lib/trade-reputation.js +99 -0
  302. package/dist/lib/ui-tokens.d.ts +21 -0
  303. package/dist/lib/ui-tokens.js +26 -0
  304. package/dist/lib/validate.d.ts +39 -0
  305. package/dist/lib/validate.js +108 -0
  306. package/dist/lib/validation.d.ts +9 -0
  307. package/dist/lib/validation.js +64 -0
  308. package/dist/server/cache.d.ts +38 -0
  309. package/dist/server/cache.js +56 -0
  310. package/dist/server/index.d.ts +2 -0
  311. package/dist/server/index.js +89 -0
  312. package/dist/server/ipc.d.ts +18 -0
  313. package/dist/server/ipc.js +159 -0
  314. package/dist/server/subscriptions.d.ts +18 -0
  315. package/dist/server/subscriptions.js +114 -0
  316. package/package.json +124 -0
@@ -0,0 +1,17 @@
1
+ export type Side = "buy" | "sell";
2
+ export type NormalizedSide = "long" | "short";
3
+ export declare function normalizeMarket(symbol: string): string;
4
+ export declare function normalizeSide(value: string): NormalizedSide;
5
+ export declare function validateSideWithAliases(value: string): Side;
6
+ export declare function getAssetIndex(publicClient: {
7
+ allPerpMetas: () => Promise<Array<{
8
+ universe: Array<{
9
+ name: string;
10
+ }>;
11
+ }>>;
12
+ spotMeta: () => Promise<{
13
+ universe: Array<{
14
+ name: string;
15
+ }>;
16
+ }>;
17
+ }, coin: string): Promise<number>;
@@ -0,0 +1,51 @@
1
+ export function normalizeMarket(symbol) {
2
+ let market = symbol.toUpperCase();
3
+ if (!market.includes("-")) {
4
+ market = `${market}-PERP`;
5
+ }
6
+ return market;
7
+ }
8
+ export function normalizeSide(value) {
9
+ const side = value.trim().toLowerCase();
10
+ if (!["buy", "long", "sell", "short"].includes(side)) {
11
+ throw new Error('Side must be: buy, long, sell, or short');
12
+ }
13
+ return side === "buy" || side === "long" ? "long" : "short";
14
+ }
15
+ export function validateSideWithAliases(value) {
16
+ const lower = value.toLowerCase();
17
+ if (lower === "long" || lower === "buy") {
18
+ return "buy";
19
+ }
20
+ if (lower === "short" || lower === "sell") {
21
+ return "sell";
22
+ }
23
+ throw new Error('Side must be "buy", "sell", "long", or "short"');
24
+ }
25
+ export async function getAssetIndex(publicClient, coin) {
26
+ // Fetch all perp metas (includes main dex at index 0 and builder dexes at index 1+)
27
+ const allPerpMetas = await publicClient.allPerpMetas();
28
+ // Check all perp dexes (case-sensitive matching)
29
+ for (let dexIndex = 0; dexIndex < allPerpMetas.length; dexIndex++) {
30
+ const dex = allPerpMetas[dexIndex];
31
+ const marketIndex = dex.universe.findIndex((a) => a.name === coin);
32
+ if (marketIndex !== -1) {
33
+ if (dexIndex === 0) {
34
+ // Main perp: just the index
35
+ return marketIndex;
36
+ }
37
+ else {
38
+ // Builder-deployed perp: 100000 + perp_dex_index * 10000 + index_in_meta
39
+ return 100000 + dexIndex * 10000 + marketIndex;
40
+ }
41
+ }
42
+ }
43
+ // Then check spot markets (case-sensitive matching)
44
+ const spotMeta = await publicClient.spotMeta();
45
+ const spotIndex = spotMeta.universe.findIndex((a) => a.name === coin);
46
+ if (spotIndex !== -1) {
47
+ // Spot assets use 10000 + index per Hyperliquid API docs
48
+ return 10000 + spotIndex;
49
+ }
50
+ throw new Error(`Unknown coin: ${coin}`);
51
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Trigger order commands using the adapter interface.
3
+ */
4
+ import { Command } from "commander";
5
+ export declare function registerTriggerOrderSimpleCommands(order: Command): void;
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Trigger order commands using the adapter interface.
3
+ */
4
+ import { getContext, getOutputOptions, getSelectedExchange } from "../../cli/program.js";
5
+ import { output, outputError, outputSuccess } from "../../cli/output.js";
6
+ import { getExchangeAdapter } from "../../lib/exchange.js";
7
+ import { getExchangeCredentials } from "../../lib/config.js";
8
+ import { RiskPolicyMiddleware } from "../../lib/risk/policy-middleware.js";
9
+ import { runWithExecutionJournal } from "../../lib/execution/journal.js";
10
+ import { withJsonContract } from "../../lib/contracts.js";
11
+ import { inferExitCode } from "../../lib/exit-codes.js";
12
+ import { assertTradeAllowed } from "../../lib/trade-reputation.js";
13
+ import { normalizeMarket, normalizeSide } from "./shared.js";
14
+ function parsePositive(value, field) {
15
+ const parsed = Number.parseFloat(value);
16
+ if (!Number.isFinite(parsed) || parsed <= 0) {
17
+ throw new Error(`${field} must be a positive number`);
18
+ }
19
+ return parsed;
20
+ }
21
+ function assertCapability(adapter, orderType) {
22
+ if (orderType === "take_profit" && !adapter.info.features.takeProfitOrders) {
23
+ throw new Error(`${adapter.info.name} does not support take-profit orders`);
24
+ }
25
+ if ((orderType === "stop" || orderType === "stop_limit") && !adapter.info.features.stopOrders) {
26
+ throw new Error(`${adapter.info.name} does not support stop orders`);
27
+ }
28
+ }
29
+ async function runTriggerOrder(args) {
30
+ const { command, commandName, orderType, side, symbol, size, triggerPrice, price, allowPostOnly } = args;
31
+ const ctx = getContext(command);
32
+ const outputOpts = getOutputOptions(command);
33
+ const exchangeId = getSelectedExchange(command);
34
+ const opts = command.opts();
35
+ try {
36
+ const market = normalizeMarket(symbol);
37
+ const normalizedSide = normalizeSide(side);
38
+ const requestedSize = parsePositive(size, "Size");
39
+ const trigger = parsePositive(triggerPrice, "Trigger price");
40
+ const limitPrice = price !== undefined ? parsePositive(price, "Price") : undefined;
41
+ const confidence = opts.confidence ? Number.parseFloat(opts.confidence) : 1;
42
+ if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1) {
43
+ throw new Error("Confidence must be a number between 0 and 1");
44
+ }
45
+ if (opts.postOnly && !allowPostOnly) {
46
+ throw new Error(`${commandName} does not support --post-only`);
47
+ }
48
+ const adapter = getExchangeAdapter();
49
+ const credentials = getExchangeCredentials(ctx.config, exchangeId, {
50
+ requireTrading: true,
51
+ });
52
+ await adapter.connect({
53
+ testnet: ctx.config.testnet,
54
+ rpcUrl: credentials.fullnodeUrl,
55
+ wsUrl: credentials.wsUrl,
56
+ credentials,
57
+ });
58
+ try {
59
+ assertCapability(adapter, orderType);
60
+ const referencePrice = limitPrice ?? trigger;
61
+ const riskPolicy = new RiskPolicyMiddleware(ctx.config, exchangeId);
62
+ const riskDecision = await riskPolicy.evaluateOrder(adapter, {
63
+ market,
64
+ side: normalizedSide,
65
+ requestedSizeBase: requestedSize,
66
+ referencePriceUsd: referencePrice,
67
+ confidence,
68
+ reason: `cli:order:${orderType}`,
69
+ });
70
+ if (!riskDecision.allowed || riskDecision.adjustedSizeBase <= 0) {
71
+ throw new Error(riskDecision.reason ?? "Order blocked by risk policy");
72
+ }
73
+ assertTradeAllowed({
74
+ exchangeId,
75
+ market,
76
+ command: `order.${commandName}`,
77
+ });
78
+ const finalSize = riskDecision.adjustedSizeBase;
79
+ const journaled = await runWithExecutionJournal({
80
+ idempotencyKey: opts.idempotencyKey,
81
+ metadata: {
82
+ command: `order.${commandName}`,
83
+ exchange: exchangeId,
84
+ testnet: ctx.config.testnet,
85
+ market,
86
+ side: normalizedSide,
87
+ orderType,
88
+ },
89
+ request: {
90
+ market,
91
+ side: normalizedSide,
92
+ orderType,
93
+ requestedSize: requestedSize.toFixed(8),
94
+ triggerPrice: trigger.toFixed(8),
95
+ price: limitPrice?.toFixed(8) ?? null,
96
+ reduceOnly: opts.reduceOnly ?? false,
97
+ postOnly: opts.postOnly ?? false,
98
+ confidence,
99
+ },
100
+ execute: async () => {
101
+ const order = await adapter.placeOrder({
102
+ market,
103
+ side: normalizedSide,
104
+ type: orderType,
105
+ size: finalSize.toFixed(8),
106
+ triggerPrice: trigger.toFixed(8),
107
+ price: limitPrice?.toFixed(8),
108
+ reduceOnly: opts.reduceOnly,
109
+ postOnly: opts.postOnly,
110
+ });
111
+ return {
112
+ order,
113
+ risk: {
114
+ requestedSize,
115
+ adjustedSize: finalSize,
116
+ adjustedNotionalUsd: riskDecision.adjustedSizeUsd,
117
+ referencePrice,
118
+ },
119
+ trigger: {
120
+ triggerPrice: trigger,
121
+ limitPrice: limitPrice ?? null,
122
+ },
123
+ };
124
+ },
125
+ });
126
+ const response = {
127
+ ...journaled.result.order,
128
+ risk: journaled.result.risk,
129
+ trigger: journaled.result.trigger,
130
+ idempotency: {
131
+ key: journaled.idempotencyKey,
132
+ replayed: journaled.replayed,
133
+ autoGenerated: journaled.autoGeneratedKey,
134
+ journalId: journaled.journalId,
135
+ },
136
+ };
137
+ if (outputOpts.json) {
138
+ output(withJsonContract("order.execution.result", {
139
+ executionStatus: journaled.replayed ? "replayed" : "executed",
140
+ ...response,
141
+ }), outputOpts);
142
+ }
143
+ else {
144
+ outputSuccess(journaled.replayed
145
+ ? "Order replayed from idempotency journal!"
146
+ : `${commandName} order placed!`);
147
+ console.log(` Order ID: ${response.id}`);
148
+ console.log(` Market: ${response.market}`);
149
+ console.log(` Side: ${response.side.toUpperCase()}`);
150
+ console.log(` Type: ${response.type}`);
151
+ console.log(` Size: ${response.size}`);
152
+ console.log(` Trigger: ${response.trigger.triggerPrice}`);
153
+ if (response.trigger.limitPrice !== null) {
154
+ console.log(` Limit: ${response.trigger.limitPrice}`);
155
+ }
156
+ console.log(` Status: ${response.status}`);
157
+ if (Math.abs(response.risk.adjustedSize - response.risk.requestedSize) > 1e-12) {
158
+ console.log(` Risk Size: adjusted from ${response.risk.requestedSize} to ${response.risk.adjustedSize.toFixed(8)}`);
159
+ }
160
+ console.log(` Idempotency: ${response.idempotency.key}` +
161
+ (response.idempotency.replayed ? " (replayed)" : ""));
162
+ console.log("");
163
+ }
164
+ }
165
+ finally {
166
+ await adapter.disconnect();
167
+ }
168
+ }
169
+ catch (err) {
170
+ const code = inferExitCode(err);
171
+ const message = err instanceof Error ? err.message : String(err);
172
+ if (outputOpts.json) {
173
+ output(withJsonContract("order.execution.result", {
174
+ status: "error",
175
+ error: {
176
+ message,
177
+ exitCode: code,
178
+ },
179
+ }), outputOpts);
180
+ }
181
+ else {
182
+ outputError(message);
183
+ }
184
+ process.exit(code);
185
+ }
186
+ }
187
+ export function registerTriggerOrderSimpleCommands(order) {
188
+ order
189
+ .command("stop <side> <symbol> <size> <triggerPrice>")
190
+ .description("Place a stop-market order (side: buy/long or sell/short)")
191
+ .option("--reduce-only", "Reduce-only order")
192
+ .option("--confidence <0-1>", "Signal confidence for risk policy (default: 1.0)")
193
+ .option("--idempotency-key <key>", "Idempotency key for safe retries")
194
+ .action(async function (side, symbol, size, triggerPrice) {
195
+ await runTriggerOrder({
196
+ command: this,
197
+ commandName: "stop",
198
+ orderType: "stop",
199
+ side,
200
+ symbol,
201
+ size,
202
+ triggerPrice,
203
+ allowPostOnly: false,
204
+ });
205
+ });
206
+ order
207
+ .command("stop-limit <side> <symbol> <size> <triggerPrice> <price>")
208
+ .description("Place a stop-limit order (side: buy/long or sell/short)")
209
+ .option("--reduce-only", "Reduce-only order")
210
+ .option("--post-only", "Post-only order")
211
+ .option("--confidence <0-1>", "Signal confidence for risk policy (default: 1.0)")
212
+ .option("--idempotency-key <key>", "Idempotency key for safe retries")
213
+ .action(async function (side, symbol, size, triggerPrice, price) {
214
+ await runTriggerOrder({
215
+ command: this,
216
+ commandName: "stop-limit",
217
+ orderType: "stop_limit",
218
+ side,
219
+ symbol,
220
+ size,
221
+ triggerPrice,
222
+ price,
223
+ allowPostOnly: true,
224
+ });
225
+ });
226
+ order
227
+ .command("take-profit <side> <symbol> <size> <triggerPrice> [price]")
228
+ .description("Place a take-profit order (side: buy/long or sell/short)")
229
+ .option("--reduce-only", "Reduce-only order")
230
+ .option("--post-only", "Post-only order")
231
+ .option("--confidence <0-1>", "Signal confidence for risk policy (default: 1.0)")
232
+ .option("--idempotency-key <key>", "Idempotency key for safe retries")
233
+ .action(async function (side, symbol, size, triggerPrice, price) {
234
+ await runTriggerOrder({
235
+ command: this,
236
+ commandName: "take-profit",
237
+ orderType: "take_profit",
238
+ side,
239
+ symbol,
240
+ size,
241
+ triggerPrice,
242
+ price,
243
+ allowPostOnly: true,
244
+ });
245
+ });
246
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerReferralCommands(program: Command): void;
@@ -0,0 +1,7 @@
1
+ import { registerSetCommand } from "./set.js";
2
+ import { registerStatusCommand } from "./status.js";
3
+ export function registerReferralCommands(program) {
4
+ const referral = program.command("referral").description("Referral management");
5
+ registerSetCommand(referral);
6
+ registerStatusCommand(referral);
7
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerSetCommand(referral: Command): void;
@@ -0,0 +1,26 @@
1
+ import { getContext, getOutputOptions } from "../../cli/program.js";
2
+ import { output, outputError, outputSuccess } from "../../cli/output.js";
3
+ export function registerSetCommand(referral) {
4
+ referral
5
+ .command("set")
6
+ .description("Set referral code (link to a referrer)")
7
+ .argument("<code>", "Referral code")
8
+ .action(async function (code) {
9
+ const ctx = getContext(this);
10
+ const outputOpts = getOutputOptions(this);
11
+ try {
12
+ const client = ctx.getWalletClient();
13
+ const result = await client.setReferrer({ code });
14
+ if (outputOpts.json) {
15
+ output(result, outputOpts);
16
+ }
17
+ else {
18
+ outputSuccess(`Referral code set: ${code}`);
19
+ }
20
+ }
21
+ catch (err) {
22
+ outputError(err instanceof Error ? err.message : String(err));
23
+ process.exit(1);
24
+ }
25
+ });
26
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerStatusCommand(referral: Command): void;
@@ -0,0 +1,31 @@
1
+ import { getContext, getOutputOptions } from "../../cli/program.js";
2
+ import { output, outputError } from "../../cli/output.js";
3
+ export function registerStatusCommand(referral) {
4
+ referral
5
+ .command("status")
6
+ .description("Get referral status")
7
+ .action(async function () {
8
+ const ctx = getContext(this);
9
+ const outputOpts = getOutputOptions(this);
10
+ try {
11
+ const client = ctx.getPublicClient();
12
+ const user = ctx.getWalletAddress();
13
+ const result = await client.referral({ user });
14
+ if (outputOpts.json) {
15
+ output(result, outputOpts);
16
+ }
17
+ else {
18
+ if (!result) {
19
+ console.log("No referral information found");
20
+ }
21
+ else {
22
+ output(result, outputOpts);
23
+ }
24
+ }
25
+ }
26
+ catch (err) {
27
+ outputError(err instanceof Error ? err.message : String(err));
28
+ process.exit(1);
29
+ }
30
+ });
31
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerReplayCommands(program: Command): void;
@@ -0,0 +1,152 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { getDb } from "../../lib/db/index.js";
3
+ import { AGENT_AUDIT_LOG_PATH } from "../../lib/paths.js";
4
+ import { queryRiskEvaluations } from "../../lib/risk/evaluation-log.js";
5
+ import { withJsonContract } from "../../lib/contracts.js";
6
+ import { output } from "../../cli/output.js";
7
+ import { getOutputOptions } from "../../cli/program.js";
8
+ function readAuditEventsForTrace(traceId) {
9
+ if (!existsSync(AGENT_AUDIT_LOG_PATH))
10
+ return [];
11
+ const lines = readFileSync(AGENT_AUDIT_LOG_PATH, "utf-8")
12
+ .split("\n")
13
+ .filter(Boolean);
14
+ return lines
15
+ .map((line) => {
16
+ try {
17
+ return JSON.parse(line);
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ })
23
+ .filter((event) => event?.traceId === traceId);
24
+ }
25
+ function formatCurrency(usd) {
26
+ return `$${usd.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
27
+ }
28
+ function formatHumanTimeline(traceId, events) {
29
+ const lines = [`Trace: ${traceId}`, ""];
30
+ for (let i = 0; i < events.length; i++) {
31
+ const event = events[i];
32
+ const ts = new Date(event.timestamp).toISOString();
33
+ const num = i + 1;
34
+ if (event.type === "risk_evaluation") {
35
+ const d = event.data;
36
+ lines.push(`${num}. [${ts}] Risk Evaluation`);
37
+ lines.push(` Exchange: ${d.exchange} | Market: ${d.market ?? "N/A"} | Side: ${d.side ?? "N/A"}`);
38
+ lines.push(` Requested: ${formatCurrency(d.requestedSizeUsd)} | Equity: ${formatCurrency(d.equity)} | Exposure: ${formatCurrency(d.exposureUsd)}`);
39
+ if (d.confidence !== undefined) {
40
+ lines.push(` Confidence: ${d.confidence}`);
41
+ }
42
+ const rulesEvaluated = d.rulesEvaluated;
43
+ const rulesFired = d.rulesFired;
44
+ lines.push(` Rules evaluated: ${rulesEvaluated.length > 0 ? rulesEvaluated.join(", ") : "(none)"}`);
45
+ lines.push(` Rules fired: ${rulesFired.length > 0 ? rulesFired.join(", ") : "(none)"}`);
46
+ const result = d.allowed ? "ALLOWED" : "DENIED";
47
+ const adjustedPart = d.adjustedSizeUsd !== undefined
48
+ ? ` | Adjusted size: ${formatCurrency(d.adjustedSizeUsd)}`
49
+ : "";
50
+ lines.push(` Result: ${result}${adjustedPart}`);
51
+ }
52
+ else if (event.type === "journal_entry") {
53
+ const d = event.data;
54
+ lines.push(`${num}. [${ts}] Execution Journal`);
55
+ lines.push(` Key: ${d.idempotencyKey} | Command: ${d.command}`);
56
+ lines.push(` Exchange: ${d.exchange} | Market: ${d.market ?? "N/A"}`);
57
+ lines.push(` Status: ${d.status}`);
58
+ }
59
+ else if (event.type === "audit_event") {
60
+ const d = event.data;
61
+ lines.push(`${num}. [${ts}] Audit Event`);
62
+ lines.push(` Action: ${d.action ?? "unknown"} | Status: ${d.status ?? "unknown"}`);
63
+ lines.push(` Exchange: ${d.exchange ?? "N/A"} | Market: ${d.market ?? "N/A"}`);
64
+ }
65
+ if (i < events.length - 1) {
66
+ lines.push("");
67
+ }
68
+ }
69
+ return lines.join("\n");
70
+ }
71
+ export function registerReplayCommands(program) {
72
+ program
73
+ .command("replay <trace-id>")
74
+ .description("Reconstruct the full execution timeline for a trace ID")
75
+ .action(async (traceId, _opts, command) => {
76
+ const { json } = getOutputOptions(command);
77
+ const events = [];
78
+ // 1. Query risk evaluation log
79
+ const riskEvals = queryRiskEvaluations({ traceId });
80
+ for (const r of riskEvals) {
81
+ events.push({
82
+ type: "risk_evaluation",
83
+ timestamp: r.createdAt,
84
+ data: {
85
+ exchange: r.exchange,
86
+ market: r.market,
87
+ side: r.side,
88
+ requestedSizeUsd: r.requestedSizeUsd,
89
+ equity: r.equity,
90
+ exposureUsd: r.exposureUsd,
91
+ confidence: r.confidence,
92
+ rulesEvaluated: r.rulesEvaluated,
93
+ rulesFired: r.rulesFired,
94
+ allowed: r.allowed,
95
+ adjustedSizeUsd: r.adjustedSizeUsd,
96
+ reason: r.reason,
97
+ },
98
+ });
99
+ }
100
+ // 2. Query execution journal
101
+ const db = getDb();
102
+ const journalEntries = db
103
+ .prepare("SELECT * FROM execution_journal WHERE trace_id = ? ORDER BY created_at")
104
+ .all(traceId);
105
+ for (const j of journalEntries) {
106
+ events.push({
107
+ type: "journal_entry",
108
+ timestamp: j.created_at,
109
+ data: {
110
+ idempotencyKey: j.idempotency_key,
111
+ command: j.command,
112
+ exchange: j.exchange,
113
+ market: j.market,
114
+ side: j.side,
115
+ orderType: j.order_type,
116
+ status: j.status,
117
+ errorMessage: j.error_message,
118
+ },
119
+ });
120
+ }
121
+ // 3. Scan audit log
122
+ const auditEvents = readAuditEventsForTrace(traceId);
123
+ for (const a of auditEvents) {
124
+ events.push({
125
+ type: "audit_event",
126
+ timestamp: a.timestamp,
127
+ data: {
128
+ action: a.action,
129
+ status: a.status,
130
+ exchange: a.exchange,
131
+ market: a.market,
132
+ },
133
+ });
134
+ }
135
+ // Sort chronologically
136
+ events.sort((a, b) => a.timestamp - b.timestamp);
137
+ if (events.length === 0) {
138
+ output(json
139
+ ? withJsonContract("replay.timeline", { traceId, events: [] })
140
+ : `No events found for trace ID: ${traceId}`, { json });
141
+ return;
142
+ }
143
+ if (json) {
144
+ output(withJsonContract("replay.timeline", { traceId, events }), {
145
+ json,
146
+ });
147
+ }
148
+ else {
149
+ output(formatHumanTimeline(traceId, events), { json });
150
+ }
151
+ });
152
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerRiskAnalyticsCommands(parent: Command): void;
@@ -0,0 +1,64 @@
1
+ import { getOutputOptions } from "../../cli/program.js";
2
+ import { output } from "../../cli/output.js";
3
+ import { withJsonContract } from "../../lib/contracts.js";
4
+ import { getDenialsByReason, getEvalWindows, detectAnomalies, } from "../../lib/risk/analytics.js";
5
+ export function registerRiskAnalyticsCommands(parent) {
6
+ parent
7
+ .command("patterns")
8
+ .description("Show denial patterns from risk evaluations")
9
+ .option("--minutes <n>", "Time window in minutes", Number.parseInt, 60)
10
+ .action(function () {
11
+ const outputOpts = getOutputOptions(this);
12
+ const opts = this.opts();
13
+ const denials = getDenialsByReason(opts.minutes);
14
+ const windows = getEvalWindows(5, opts.minutes);
15
+ if (outputOpts.json) {
16
+ output(withJsonContract("risk.patterns", { denials, windows }), outputOpts);
17
+ return;
18
+ }
19
+ if (denials.length === 0) {
20
+ console.log(`\nNo denials in the last ${opts.minutes} minutes.\n`);
21
+ return;
22
+ }
23
+ console.log(`\nDenial patterns (last ${opts.minutes} min):\n`);
24
+ for (const d of denials) {
25
+ const lastSeen = new Date(d.lastSeen).toISOString();
26
+ console.log(` ${d.reason}`);
27
+ console.log(` Count: ${d.count}`);
28
+ console.log(` Markets: ${d.markets.join(", ") || "(none)"}`);
29
+ console.log(` Last seen: ${lastSeen}`);
30
+ console.log("");
31
+ }
32
+ });
33
+ parent
34
+ .command("anomalies")
35
+ .description("Detect anomalies in recent risk evaluations")
36
+ .option("--threshold <0-1>", "Denial rate threshold", Number.parseFloat, 0.5)
37
+ .option("--window <minutes>", "Window size in minutes", Number.parseInt, 5)
38
+ .action(function () {
39
+ const outputOpts = getOutputOptions(this);
40
+ const opts = this.opts();
41
+ const alerts = detectAnomalies({
42
+ denialRateThreshold: opts.threshold,
43
+ windowMinutes: opts.window,
44
+ });
45
+ if (outputOpts.json) {
46
+ output(withJsonContract("risk.anomalies", {
47
+ alerts,
48
+ window: opts.window,
49
+ }), outputOpts);
50
+ return;
51
+ }
52
+ if (alerts.length === 0) {
53
+ console.log(`\nNo anomalies detected in the last ${opts.window} minutes.\n`);
54
+ return;
55
+ }
56
+ console.log(`\nAnomalies detected:\n`);
57
+ for (const a of alerts) {
58
+ const severity = a.severity === "critical" ? "CRITICAL" : "WARNING";
59
+ console.log(` [${severity}] ${a.type}`);
60
+ console.log(` ${a.message}`);
61
+ console.log("");
62
+ }
63
+ });
64
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerRiskAuditCommand(parent: Command): void;