@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,510 @@
1
+ import { getContext, getOutputOptions } from "../../cli/program.js";
2
+ import { output, outputError, outputSuccess } from "../../cli/output.js";
3
+ import { validateAddressForExchange, validatePrivateKey } from "../../lib/validation.js";
4
+ import { prompt, select, confirm } from "../../lib/prompts.js";
5
+ import { createAccount, getAccountCount, isAliasTaken } from "../../lib/db/index.js";
6
+ import { generateApiWallet, validateApiKey } from "../../lib/api-wallet.js";
7
+ import { getExchangeId } from "../../lib/exchange.js";
8
+ import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
9
+ import { Ed25519Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
10
+ import { ec } from "starknet";
11
+ function maskSecret(secret) {
12
+ if (secret.length <= 12) {
13
+ return "[HIDDEN]";
14
+ }
15
+ return `${secret.slice(0, 6)}...${secret.slice(-4)}`;
16
+ }
17
+ async function maybeRevealGeneratedSecret(label, secret) {
18
+ console.log(` ${label}: ${maskSecret(secret)} (hidden by default)`);
19
+ const shouldReveal = await confirm("Reveal full generated secret in terminal output?", false);
20
+ if (shouldReveal) {
21
+ console.log(` ${label}: ${secret}`);
22
+ console.log(" Warning: terminal logs/history may expose full secret values.");
23
+ }
24
+ }
25
+ export function registerAddCommand(account) {
26
+ account
27
+ .command("add")
28
+ .description("Add a new account (interactive wizard)")
29
+ .action(async function () {
30
+ const ctx = getContext(this);
31
+ const outputOpts = getOutputOptions(this);
32
+ const isTestnet = ctx.config.testnet;
33
+ const exchangeId = getExchangeId();
34
+ try {
35
+ console.log("\n=== Add New Account ===\n");
36
+ // Step 1: Choose setup method
37
+ const setupMethod = await select("How would you like to add your account?", getSetupOptions(exchangeId, isTestnet));
38
+ if (setupMethod === "new") {
39
+ await handleGeneratedWallet(isTestnet, outputOpts, exchangeId);
40
+ return;
41
+ }
42
+ if (setupMethod === "existing") {
43
+ if (exchangeId === "hyperliquid") {
44
+ await handleHyperliquidApiWallet(isTestnet, outputOpts, exchangeId);
45
+ }
46
+ else {
47
+ await handleGenericSigningKey(outputOpts, exchangeId);
48
+ }
49
+ }
50
+ else {
51
+ await handleReadOnly(outputOpts, exchangeId);
52
+ }
53
+ }
54
+ catch (err) {
55
+ outputError(err instanceof Error ? err.message : String(err));
56
+ process.exit(1);
57
+ }
58
+ });
59
+ }
60
+ function getSetupOptions(exchangeId, isTestnet) {
61
+ if (exchangeId === "hyperliquid") {
62
+ return [
63
+ {
64
+ value: "existing",
65
+ label: "Use existing API wallet",
66
+ description: `Import from ${isTestnet ? "https://app.hyperliquid-testnet.xyz/API" : "https://app.hyperliquid.xyz/API"}`,
67
+ },
68
+ {
69
+ value: "new",
70
+ label: "Create new wallet",
71
+ description: "Generate a new API wallet locally (stored encrypted in profile DB)",
72
+ },
73
+ {
74
+ value: "readonly",
75
+ label: "Add read-only account",
76
+ description: "Watch a wallet without trading capabilities",
77
+ },
78
+ ];
79
+ }
80
+ if (exchangeId === "orderly") {
81
+ return [
82
+ {
83
+ value: "existing",
84
+ label: "Import trading secret",
85
+ description: "Store account ID + trading secret for this profile",
86
+ },
87
+ {
88
+ value: "new",
89
+ label: "Generate trading secret",
90
+ description: "Generate a local trading secret and account profile",
91
+ },
92
+ {
93
+ value: "readonly",
94
+ label: "Add account identifier",
95
+ description: "Store an account identifier for tracking/default selection",
96
+ },
97
+ ];
98
+ }
99
+ return [
100
+ {
101
+ value: "existing",
102
+ label: "Import signing key",
103
+ description: "Store local trading key for this exchange profile",
104
+ },
105
+ {
106
+ value: "new",
107
+ label: "Generate signing key",
108
+ description: "Generate a local signing key and account profile",
109
+ },
110
+ {
111
+ value: "readonly",
112
+ label: "Add read-only account",
113
+ description: "Watch an account without storing a signing key",
114
+ },
115
+ ];
116
+ }
117
+ async function promptSetAsDefault(exchangeId) {
118
+ const existingCount = getAccountCount(exchangeId);
119
+ if (existingCount === 0) {
120
+ return false;
121
+ }
122
+ return confirm("\nSet this as your default account?", true);
123
+ }
124
+ function printAccountCreated(args) {
125
+ const { outputOpts, account, maskedPrivateKey = true, generatedPrivateKey, generatedPublicKey, userAddressLabel = "Address", } = args;
126
+ if (outputOpts.json) {
127
+ output({
128
+ ...account,
129
+ apiWalletPrivateKey: maskedPrivateKey ? "[REDACTED]" : account.apiWalletPrivateKey,
130
+ generated: generatedPublicKey
131
+ ? {
132
+ publicKey: generatedPublicKey,
133
+ privateKey: generatedPrivateKey ? "[REDACTED]" : undefined,
134
+ }
135
+ : undefined,
136
+ }, outputOpts);
137
+ return;
138
+ }
139
+ console.log("");
140
+ outputSuccess(`Account "${account.alias}" added successfully!`);
141
+ console.log("");
142
+ console.log("Account details:");
143
+ console.log(` Alias: ${account.alias}`);
144
+ console.log(` ${userAddressLabel}: ${account.userAddress}`);
145
+ console.log(` Type: ${account.type}`);
146
+ if (account.apiWalletPublicKey) {
147
+ console.log(` Signing Key Address: ${account.apiWalletPublicKey}`);
148
+ }
149
+ if (generatedPrivateKey) {
150
+ console.log(` Generated Secret: ${maskSecret(generatedPrivateKey)} (full value hidden)`);
151
+ console.log(" Security: stored encrypted in the local DB profile");
152
+ }
153
+ console.log(` Default: ${account.isDefault ? "Yes" : "No"}`);
154
+ console.log("");
155
+ }
156
+ async function handleGeneratedWallet(isTestnet, outputOpts, exchangeId) {
157
+ if (exchangeId === "hyperliquid") {
158
+ const generated = generateApiWallet();
159
+ const apiUrl = isTestnet
160
+ ? "https://app.hyperliquid-testnet.xyz/API"
161
+ : "https://app.hyperliquid.xyz/API";
162
+ console.log("");
163
+ console.log("Generated Hyperliquid API wallet:");
164
+ console.log(` API Wallet Address: ${generated.publicKey}`);
165
+ await maybeRevealGeneratedSecret("API Private Key", generated.privateKey);
166
+ console.log("");
167
+ console.log(`Register/approve this API wallet at: ${apiUrl}`);
168
+ console.log("");
169
+ const addressInput = await prompt("Enter your Hyperliquid master wallet address: ");
170
+ let userAddress = validateAddressForExchange(addressInput, exchangeId);
171
+ const shouldValidate = await confirm("Validate API wallet approval now?", true);
172
+ if (shouldValidate) {
173
+ console.log("\nValidating API wallet...");
174
+ const result = await validateApiKey(generated.privateKey, isTestnet);
175
+ if (!result.valid) {
176
+ throw new Error(`${result.error}. Approve wallet at ${apiUrl} and try again.`);
177
+ }
178
+ userAddress = result.masterAddress;
179
+ console.log(`Approved API wallet for ${userAddress.slice(0, 6)}...${userAddress.slice(-4)}`);
180
+ }
181
+ const alias = await promptForAlias(exchangeId);
182
+ const setAsDefault = await promptSetAsDefault(exchangeId);
183
+ const account = createAccount({
184
+ alias,
185
+ exchange: exchangeId,
186
+ userAddress,
187
+ type: "api_wallet",
188
+ source: "cli_import",
189
+ apiWalletPrivateKey: generated.privateKey,
190
+ apiWalletPublicKey: generated.publicKey,
191
+ setAsDefault,
192
+ });
193
+ printAccountCreated({
194
+ outputOpts,
195
+ account,
196
+ generatedPrivateKey: generated.privateKey,
197
+ generatedPublicKey: generated.publicKey,
198
+ });
199
+ return;
200
+ }
201
+ if (exchangeId === "decibel") {
202
+ const aptosPrivateKeyObj = Ed25519PrivateKey.generate();
203
+ const aptosPrivateKey = aptosPrivateKeyObj.toString();
204
+ const aptosAddress = new Ed25519Account({ privateKey: aptosPrivateKeyObj })
205
+ .accountAddress
206
+ .toString();
207
+ console.log("");
208
+ console.log("Generated Decibel signing wallet:");
209
+ console.log(` Aptos Address: ${aptosAddress}`);
210
+ await maybeRevealGeneratedSecret("Private Key", aptosPrivateKey);
211
+ const alias = await promptForAlias(exchangeId);
212
+ const setAsDefault = await promptSetAsDefault(exchangeId);
213
+ const account = createAccount({
214
+ alias,
215
+ exchange: exchangeId,
216
+ userAddress: aptosAddress,
217
+ type: "api_wallet",
218
+ source: "cli_import",
219
+ apiWalletPrivateKey: aptosPrivateKey,
220
+ apiWalletPublicKey: aptosAddress,
221
+ setAsDefault,
222
+ });
223
+ printAccountCreated({
224
+ outputOpts,
225
+ account,
226
+ generatedPrivateKey: aptosPrivateKey,
227
+ generatedPublicKey: aptosAddress,
228
+ });
229
+ return;
230
+ }
231
+ if (exchangeId === "aevo") {
232
+ const privateKey = generatePrivateKey();
233
+ const address = privateKeyToAccount(privateKey).address;
234
+ console.log("");
235
+ console.log("Generated Aevo signing wallet:");
236
+ console.log(` Address: ${address}`);
237
+ await maybeRevealGeneratedSecret("Private Key", privateKey);
238
+ const alias = await promptForAlias(exchangeId);
239
+ const setAsDefault = await promptSetAsDefault(exchangeId);
240
+ const account = createAccount({
241
+ alias,
242
+ exchange: exchangeId,
243
+ userAddress: address,
244
+ type: "api_wallet",
245
+ source: "cli_import",
246
+ apiWalletPrivateKey: privateKey,
247
+ apiWalletPublicKey: address,
248
+ setAsDefault,
249
+ });
250
+ printAccountCreated({
251
+ outputOpts,
252
+ account,
253
+ generatedPrivateKey: privateKey,
254
+ generatedPublicKey: address,
255
+ });
256
+ return;
257
+ }
258
+ if (exchangeId === "orderly") {
259
+ const privateKey = generatePrivateKey();
260
+ const generatedAddress = privateKeyToAccount(privateKey).address;
261
+ console.log("");
262
+ console.log("Generated Orderly trading secret:");
263
+ console.log(` Wallet Address: ${generatedAddress}`);
264
+ await maybeRevealGeneratedSecret("Trading Secret", privateKey);
265
+ console.log(" Note: complete Orderly account onboarding to issue account/key/secret values.");
266
+ const accountIdInput = await prompt("Enter your Orderly account ID (or press Enter to use generated wallet address): ");
267
+ const userAddress = accountIdInput.trim()
268
+ ? validateAddressForExchange(accountIdInput, exchangeId)
269
+ : generatedAddress;
270
+ const alias = await promptForAlias(exchangeId);
271
+ const setAsDefault = await promptSetAsDefault(exchangeId);
272
+ const account = createAccount({
273
+ alias,
274
+ exchange: exchangeId,
275
+ userAddress: userAddress,
276
+ type: "api_wallet",
277
+ source: "cli_import",
278
+ apiWalletPrivateKey: privateKey,
279
+ apiWalletPublicKey: generatedAddress,
280
+ setAsDefault,
281
+ });
282
+ printAccountCreated({
283
+ outputOpts,
284
+ account,
285
+ generatedPrivateKey: privateKey,
286
+ generatedPublicKey: generatedAddress,
287
+ userAddressLabel: "Account ID",
288
+ });
289
+ return;
290
+ }
291
+ if (exchangeId === "paradex") {
292
+ const starkPrivateKeyBytes = ec.starkCurve.utils.randomPrivateKey();
293
+ const privateKey = `0x${Buffer.from(starkPrivateKeyBytes).toString("hex")}`;
294
+ const publicKey = ec.starkCurve.getStarkKey(privateKey);
295
+ console.log("");
296
+ console.log("Generated Paradex signing key:");
297
+ console.log(` Stark Public Key: ${publicKey}`);
298
+ await maybeRevealGeneratedSecret("Stark Private Key", privateKey);
299
+ const accountInput = await prompt("Enter your Paradex account address: ");
300
+ const userAddress = validateAddressForExchange(accountInput, exchangeId);
301
+ const alias = await promptForAlias(exchangeId);
302
+ const setAsDefault = await promptSetAsDefault(exchangeId);
303
+ const account = createAccount({
304
+ alias,
305
+ exchange: exchangeId,
306
+ userAddress: userAddress,
307
+ type: "api_wallet",
308
+ source: "cli_import",
309
+ apiWalletPrivateKey: privateKey,
310
+ apiWalletPublicKey: publicKey,
311
+ setAsDefault,
312
+ });
313
+ printAccountCreated({
314
+ outputOpts,
315
+ account,
316
+ generatedPrivateKey: privateKey,
317
+ generatedPublicKey: publicKey,
318
+ userAddressLabel: "Account",
319
+ });
320
+ return;
321
+ }
322
+ throw new Error(`Wallet generation is not supported for "${exchangeId}"`);
323
+ }
324
+ async function handleHyperliquidApiWallet(isTestnet, outputOpts, exchangeId) {
325
+ // Step 1: Get API private key
326
+ const apiUrl = isTestnet
327
+ ? "https://app.hyperliquid-testnet.xyz/API"
328
+ : "https://app.hyperliquid.xyz/API";
329
+ console.log(`\nVisit ${apiUrl} and click "Generate" to create one.\n`);
330
+ const apiKeyInput = await prompt("Enter your API wallet private key: ");
331
+ // Normalize the key (add 0x prefix if missing)
332
+ let apiPrivateKey;
333
+ if (apiKeyInput.startsWith("0x")) {
334
+ apiPrivateKey = apiKeyInput;
335
+ }
336
+ else {
337
+ apiPrivateKey = `0x${apiKeyInput}`;
338
+ }
339
+ // Validate key format
340
+ validatePrivateKey(apiPrivateKey);
341
+ // Step 2: Validate the API key
342
+ console.log("\nValidating API key...");
343
+ const result = await validateApiKey(apiPrivateKey, isTestnet);
344
+ if (!result.valid) {
345
+ throw new Error(result.error);
346
+ }
347
+ const apiWalletPublicKey = result.apiWalletAddress;
348
+ const userAddress = result.masterAddress;
349
+ console.log(`Valid API wallet for ${userAddress.slice(0, 6)}...${userAddress.slice(-4)}`);
350
+ // Step 3: Get alias
351
+ const alias = await promptForAlias(exchangeId);
352
+ // Step 4: Check if user wants to set as default
353
+ let setAsDefault = false;
354
+ const existingCount = getAccountCount(exchangeId);
355
+ if (existingCount > 0) {
356
+ setAsDefault = await confirm("\nSet this as your default account?", true);
357
+ }
358
+ // Step 5: Save account
359
+ const newAccount = createAccount({
360
+ alias,
361
+ exchange: exchangeId,
362
+ userAddress,
363
+ type: "api_wallet",
364
+ source: "cli_import",
365
+ apiWalletPrivateKey: apiPrivateKey,
366
+ apiWalletPublicKey,
367
+ setAsDefault,
368
+ });
369
+ if (outputOpts.json) {
370
+ output({
371
+ ...newAccount,
372
+ apiWalletPrivateKey: "[REDACTED]",
373
+ }, outputOpts);
374
+ }
375
+ else {
376
+ console.log("");
377
+ outputSuccess(`Account "${alias}" added successfully!`);
378
+ console.log("");
379
+ console.log("Account details:");
380
+ console.log(` Alias: ${newAccount.alias}`);
381
+ console.log(` Address: ${newAccount.userAddress}`);
382
+ console.log(` Type: ${newAccount.type}`);
383
+ console.log(` API Wallet: ${newAccount.apiWalletPublicKey}`);
384
+ console.log(` Default: ${newAccount.isDefault ? "Yes" : "No"}`);
385
+ console.log("");
386
+ }
387
+ }
388
+ async function handleGenericSigningKey(outputOpts, exchangeId) {
389
+ console.log("");
390
+ const privateKeyInput = await prompt("Enter your signing private key: ");
391
+ const privateKey = normalizePrivateKey(privateKeyInput);
392
+ validatePrivateKey(privateKey);
393
+ let userAddress;
394
+ let apiWalletPublicKey;
395
+ if (exchangeId === "decibel") {
396
+ const account = new Ed25519Account({ privateKey: new Ed25519PrivateKey(privateKey) });
397
+ userAddress = account.accountAddress.toString();
398
+ apiWalletPublicKey = userAddress;
399
+ }
400
+ else if (exchangeId === "aevo") {
401
+ userAddress = privateKeyToAccount(privateKey).address;
402
+ apiWalletPublicKey = userAddress;
403
+ }
404
+ else if (exchangeId === "paradex") {
405
+ const accountInput = await prompt("Enter your Paradex account address: ");
406
+ userAddress = validateAddressForExchange(accountInput, exchangeId);
407
+ }
408
+ else if (exchangeId === "orderly") {
409
+ const accountId = await prompt("Enter your Orderly account ID: ");
410
+ userAddress = validateAddressForExchange(accountId, exchangeId);
411
+ }
412
+ else {
413
+ throw new Error(`Signing-key import is not supported for "${exchangeId}"`);
414
+ }
415
+ const alias = await promptForAlias(exchangeId);
416
+ let setAsDefault = false;
417
+ const existingCount = getAccountCount(exchangeId);
418
+ if (existingCount > 0) {
419
+ setAsDefault = await confirm("\nSet this as your default account?", true);
420
+ }
421
+ const newAccount = createAccount({
422
+ alias,
423
+ exchange: exchangeId,
424
+ userAddress: userAddress,
425
+ type: "api_wallet",
426
+ source: "cli_import",
427
+ apiWalletPrivateKey: privateKey,
428
+ apiWalletPublicKey: apiWalletPublicKey,
429
+ setAsDefault,
430
+ });
431
+ if (outputOpts.json) {
432
+ output({
433
+ ...newAccount,
434
+ apiWalletPrivateKey: "[REDACTED]",
435
+ }, outputOpts);
436
+ return;
437
+ }
438
+ console.log("");
439
+ outputSuccess(`Account "${alias}" added successfully!`);
440
+ console.log("");
441
+ console.log("Account details:");
442
+ console.log(` Alias: ${newAccount.alias}`);
443
+ console.log(` Address: ${newAccount.userAddress}`);
444
+ console.log(` Type: ${newAccount.type}`);
445
+ if (newAccount.apiWalletPublicKey) {
446
+ console.log(` Signing Key Address: ${newAccount.apiWalletPublicKey}`);
447
+ }
448
+ console.log(` Default: ${newAccount.isDefault ? "Yes" : "No"}`);
449
+ console.log("");
450
+ }
451
+ async function handleReadOnly(outputOpts, exchangeId) {
452
+ // Step 1: Get wallet address
453
+ console.log("");
454
+ const promptLabel = exchangeId === "orderly"
455
+ ? "Enter the account identifier to watch: "
456
+ : "Enter the account address to watch: ";
457
+ const userAddressInput = await prompt(promptLabel);
458
+ const userAddress = validateAddressForExchange(userAddressInput, exchangeId);
459
+ // Step 2: Get alias
460
+ const alias = await promptForAlias(exchangeId);
461
+ // Step 3: Check if user wants to set as default
462
+ let setAsDefault = false;
463
+ const existingCount = getAccountCount(exchangeId);
464
+ if (existingCount > 0) {
465
+ setAsDefault = await confirm("\nSet this as your default account?", true);
466
+ }
467
+ // Step 4: Save account
468
+ const newAccount = createAccount({
469
+ alias,
470
+ exchange: exchangeId,
471
+ userAddress: userAddress,
472
+ type: "readonly",
473
+ source: "cli_import",
474
+ setAsDefault,
475
+ });
476
+ if (outputOpts.json) {
477
+ output(newAccount, outputOpts);
478
+ }
479
+ else {
480
+ console.log("");
481
+ outputSuccess(`Account "${alias}" added successfully!`);
482
+ console.log("");
483
+ console.log("Account details:");
484
+ console.log(` Alias: ${newAccount.alias}`);
485
+ console.log(` Address: ${newAccount.userAddress}`);
486
+ console.log(` Type: ${newAccount.type}`);
487
+ console.log(` Default: ${newAccount.isDefault ? "Yes" : "No"}`);
488
+ console.log("");
489
+ }
490
+ }
491
+ function normalizePrivateKey(raw) {
492
+ if (raw.startsWith("0x")) {
493
+ return raw;
494
+ }
495
+ return `0x${raw}`;
496
+ }
497
+ async function promptForAlias(exchangeId) {
498
+ while (true) {
499
+ const alias = await prompt("Enter an alias for this account (e.g., 'main', 'trading'): ");
500
+ if (!alias) {
501
+ console.log("Alias cannot be empty.");
502
+ continue;
503
+ }
504
+ if (isAliasTaken(alias, exchangeId)) {
505
+ console.log(`Alias "${alias}" is already taken on ${exchangeId}. Please choose another.`);
506
+ continue;
507
+ }
508
+ return alias;
509
+ }
510
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Simple balances command using the adapter interface
3
+ */
4
+ import { Command } from "commander";
5
+ export declare function registerBalancesSimpleCommand(account: Command): void;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Simple balances command using the adapter interface
3
+ */
4
+ import { getContext, getOutputOptions, getSelectedExchange } from "../../cli/program.js";
5
+ import { output, outputError } from "../../cli/output.js";
6
+ import { getExchangeAdapter } from "../../lib/exchange.js";
7
+ import { getExchangeCredentials } from "../../lib/config.js";
8
+ export function registerBalancesSimpleCommand(account) {
9
+ account
10
+ .command("balances")
11
+ .alias("bal")
12
+ .description("Show account balances")
13
+ .action(async function () {
14
+ const ctx = getContext(this);
15
+ const outputOpts = getOutputOptions(this);
16
+ const exchangeId = getSelectedExchange(this);
17
+ const adapter = getExchangeAdapter();
18
+ let connected = false;
19
+ try {
20
+ const credentials = getExchangeCredentials(ctx.config, exchangeId, {
21
+ requireReadAccess: true,
22
+ });
23
+ await adapter.connect({
24
+ testnet: ctx.config.testnet,
25
+ rpcUrl: credentials.fullnodeUrl,
26
+ wsUrl: credentials.wsUrl,
27
+ credentials,
28
+ });
29
+ connected = true;
30
+ const balances = await adapter.getBalances();
31
+ if (outputOpts.json) {
32
+ output(balances, outputOpts);
33
+ }
34
+ else {
35
+ console.log(`\n${adapter.info.name} Account Balance:\n`);
36
+ for (const bal of balances) {
37
+ const total = parseFloat(bal.total);
38
+ const available = parseFloat(bal.available);
39
+ const locked = parseFloat(bal.locked);
40
+ const pnl = parseFloat(bal.unrealizedPnl);
41
+ const pnlColor = pnl >= 0 ? "\x1b[32m" : "\x1b[31m";
42
+ const pnlStr = `${pnl >= 0 ? "+" : ""}$${pnl.toFixed(2)}`;
43
+ console.log(` ${bal.asset}`);
44
+ console.log(` ${"─".repeat(40)}`);
45
+ console.log(` Total: $${total.toFixed(2)}`);
46
+ console.log(` Available: $${available.toFixed(2)}`);
47
+ console.log(` In Positions: $${locked.toFixed(2)}`);
48
+ console.log(` Unrealized: ${pnlColor}${pnlStr}\x1b[0m`);
49
+ console.log("");
50
+ }
51
+ }
52
+ }
53
+ catch (err) {
54
+ outputError(err instanceof Error ? err.message : String(err));
55
+ process.exitCode = 1;
56
+ }
57
+ finally {
58
+ if (connected) {
59
+ await adapter.disconnect().catch(() => undefined);
60
+ }
61
+ }
62
+ });
63
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerAccountCommands(program: Command): void;
@@ -0,0 +1,17 @@
1
+ import { registerPositionsSimpleCommand } from "./positions-simple.js";
2
+ import { registerBalancesSimpleCommand } from "./balances-simple.js";
3
+ import { registerAddCommand } from "./add.js";
4
+ import { registerLsCommand } from "./ls.js";
5
+ import { registerSetDefaultCommand } from "./set-default.js";
6
+ import { registerRemoveCommand } from "./remove.js";
7
+ export function registerAccountCommands(program) {
8
+ const account = program.command("account").description("Account management and information");
9
+ // Account management commands
10
+ registerAddCommand(account);
11
+ registerLsCommand(account);
12
+ registerSetDefaultCommand(account);
13
+ registerRemoveCommand(account);
14
+ // Account information commands (using adapter)
15
+ registerPositionsSimpleCommand(account);
16
+ registerBalancesSimpleCommand(account);
17
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerLsCommand(account: Command): void;