@megatao/sdk 1.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 (228) hide show
  1. package/.env.example +37 -0
  2. package/CHANGELOG.md +19 -0
  3. package/README.md +199 -0
  4. package/bin/alf +4 -0
  5. package/cli/README.md +198 -0
  6. package/cli/TEST_MANUAL.md +577 -0
  7. package/cli/commands/account.ts +545 -0
  8. package/cli/commands/funding.ts +481 -0
  9. package/cli/commands/liquidation.ts +523 -0
  10. package/cli/commands/market.ts +590 -0
  11. package/cli/commands/orders.ts +395 -0
  12. package/cli/commands/position.ts +1085 -0
  13. package/cli/commands/shared/positionUtils.ts +239 -0
  14. package/cli/commands/trading.ts +483 -0
  15. package/cli/commands/utils.ts +281 -0
  16. package/cli/commands/vault.ts +522 -0
  17. package/cli/index.ts +169 -0
  18. package/cli/interactive.ts +530 -0
  19. package/cli/utils/client.ts +457 -0
  20. package/cli/utils/config.ts +226 -0
  21. package/cli/utils/display.ts +258 -0
  22. package/cli/utils/index.ts +10 -0
  23. package/cli/utils/prompts.ts +364 -0
  24. package/config.example.json +23 -0
  25. package/dist/AlphaFuturesClient.d.ts +36 -0
  26. package/dist/AlphaFuturesClient.d.ts.map +1 -0
  27. package/dist/AlphaFuturesClient.js +116 -0
  28. package/dist/AlphaFuturesClient.js.map +1 -0
  29. package/dist/abi/Alpha.json +5987 -0
  30. package/dist/abi/abis.d.ts +319 -0
  31. package/dist/abi/abis.d.ts.map +1 -0
  32. package/dist/abi/abis.js +128 -0
  33. package/dist/abi/abis.js.map +1 -0
  34. package/dist/abi/index.d.ts +11 -0
  35. package/dist/abi/index.d.ts.map +1 -0
  36. package/dist/abi/index.js +15 -0
  37. package/dist/abi/index.js.map +1 -0
  38. package/dist/config/contracts.config.d.ts +70 -0
  39. package/dist/config/contracts.config.d.ts.map +1 -0
  40. package/dist/config/contracts.config.js +137 -0
  41. package/dist/config/contracts.config.js.map +1 -0
  42. package/dist/config/environments/alpha.config.d.ts +17 -0
  43. package/dist/config/environments/alpha.config.d.ts.map +1 -0
  44. package/dist/config/environments/alpha.config.js +140 -0
  45. package/dist/config/environments/alpha.config.js.map +1 -0
  46. package/dist/config/environments/beta.config.d.ts +16 -0
  47. package/dist/config/environments/beta.config.d.ts.map +1 -0
  48. package/dist/config/environments/beta.config.js +131 -0
  49. package/dist/config/environments/beta.config.js.map +1 -0
  50. package/dist/config/environments/dev.config.d.ts +13 -0
  51. package/dist/config/environments/dev.config.d.ts.map +1 -0
  52. package/dist/config/environments/dev.config.js +123 -0
  53. package/dist/config/environments/dev.config.js.map +1 -0
  54. package/dist/config/environments/index.d.ts +48 -0
  55. package/dist/config/environments/index.d.ts.map +1 -0
  56. package/dist/config/environments/index.js +81 -0
  57. package/dist/config/environments/index.js.map +1 -0
  58. package/dist/config/environments/localhost.config.d.ts +16 -0
  59. package/dist/config/environments/localhost.config.d.ts.map +1 -0
  60. package/dist/config/environments/localhost.config.js +152 -0
  61. package/dist/config/environments/localhost.config.js.map +1 -0
  62. package/dist/config/environments/prod.config.d.ts +20 -0
  63. package/dist/config/environments/prod.config.d.ts.map +1 -0
  64. package/dist/config/environments/prod.config.js +143 -0
  65. package/dist/config/environments/prod.config.js.map +1 -0
  66. package/dist/config/index.d.ts +7 -0
  67. package/dist/config/index.d.ts.map +1 -0
  68. package/dist/config/index.js +41 -0
  69. package/dist/config/index.js.map +1 -0
  70. package/dist/constants/assets.d.ts +76 -0
  71. package/dist/constants/assets.d.ts.map +1 -0
  72. package/dist/constants/assets.js +277 -0
  73. package/dist/constants/assets.js.map +1 -0
  74. package/dist/constants/contracts.d.ts +41 -0
  75. package/dist/constants/contracts.d.ts.map +1 -0
  76. package/dist/constants/contracts.js +57 -0
  77. package/dist/constants/contracts.js.map +1 -0
  78. package/dist/constants/index.d.ts +36 -0
  79. package/dist/constants/index.d.ts.map +1 -0
  80. package/dist/constants/index.js +75 -0
  81. package/dist/constants/index.js.map +1 -0
  82. package/dist/constants/networks.d.ts +32 -0
  83. package/dist/constants/networks.d.ts.map +1 -0
  84. package/dist/constants/networks.js +174 -0
  85. package/dist/constants/networks.js.map +1 -0
  86. package/dist/contracts/index.d.ts +5 -0
  87. package/dist/contracts/index.d.ts.map +1 -0
  88. package/dist/contracts/index.js +21 -0
  89. package/dist/contracts/index.js.map +1 -0
  90. package/dist/contracts/viem/AlphaViem.d.ts +518 -0
  91. package/dist/contracts/viem/AlphaViem.d.ts.map +1 -0
  92. package/dist/contracts/viem/AlphaViem.js +1287 -0
  93. package/dist/contracts/viem/AlphaViem.js.map +1 -0
  94. package/dist/contracts/viem/PriceOracleViem.d.ts +71 -0
  95. package/dist/contracts/viem/PriceOracleViem.d.ts.map +1 -0
  96. package/dist/contracts/viem/PriceOracleViem.js +212 -0
  97. package/dist/contracts/viem/PriceOracleViem.js.map +1 -0
  98. package/dist/contracts/viem/index.d.ts +9 -0
  99. package/dist/contracts/viem/index.d.ts.map +1 -0
  100. package/dist/contracts/viem/index.js +17 -0
  101. package/dist/contracts/viem/index.js.map +1 -0
  102. package/dist/errors/index.d.ts +44 -0
  103. package/dist/errors/index.d.ts.map +1 -0
  104. package/dist/errors/index.js +83 -0
  105. package/dist/errors/index.js.map +1 -0
  106. package/dist/index.d.ts +19 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +60 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/types/alpha.d.ts +299 -0
  111. package/dist/types/alpha.d.ts.map +1 -0
  112. package/dist/types/alpha.js +6 -0
  113. package/dist/types/alpha.js.map +1 -0
  114. package/dist/types/client.d.ts +24 -0
  115. package/dist/types/client.d.ts.map +1 -0
  116. package/dist/types/client.js +13 -0
  117. package/dist/types/client.js.map +1 -0
  118. package/dist/types/contracts.d.ts +48 -0
  119. package/dist/types/contracts.d.ts.map +1 -0
  120. package/dist/types/contracts.js +6 -0
  121. package/dist/types/contracts.js.map +1 -0
  122. package/dist/types/funding.d.ts +27 -0
  123. package/dist/types/funding.d.ts.map +1 -0
  124. package/dist/types/funding.js +6 -0
  125. package/dist/types/funding.js.map +1 -0
  126. package/dist/types/index.d.ts +92 -0
  127. package/dist/types/index.d.ts.map +1 -0
  128. package/dist/types/index.js +47 -0
  129. package/dist/types/index.js.map +1 -0
  130. package/dist/types/liquidation.d.ts +20 -0
  131. package/dist/types/liquidation.d.ts.map +1 -0
  132. package/dist/types/liquidation.js +6 -0
  133. package/dist/types/liquidation.js.map +1 -0
  134. package/dist/types/margin.d.ts +29 -0
  135. package/dist/types/margin.d.ts.map +1 -0
  136. package/dist/types/margin.js +6 -0
  137. package/dist/types/margin.js.map +1 -0
  138. package/dist/types/oracle.d.ts +21 -0
  139. package/dist/types/oracle.d.ts.map +1 -0
  140. package/dist/types/oracle.js +6 -0
  141. package/dist/types/oracle.js.map +1 -0
  142. package/dist/types/positions.d.ts +43 -0
  143. package/dist/types/positions.d.ts.map +1 -0
  144. package/dist/types/positions.js +13 -0
  145. package/dist/types/positions.js.map +1 -0
  146. package/dist/utils/calculations.d.ts +84 -0
  147. package/dist/utils/calculations.d.ts.map +1 -0
  148. package/dist/utils/calculations.js +155 -0
  149. package/dist/utils/calculations.js.map +1 -0
  150. package/dist/utils/errors.d.ts +24 -0
  151. package/dist/utils/errors.d.ts.map +1 -0
  152. package/dist/utils/errors.js +129 -0
  153. package/dist/utils/errors.js.map +1 -0
  154. package/dist/utils/events.d.ts +40 -0
  155. package/dist/utils/events.d.ts.map +1 -0
  156. package/dist/utils/events.js +73 -0
  157. package/dist/utils/events.js.map +1 -0
  158. package/dist/utils/format.d.ts +40 -0
  159. package/dist/utils/format.d.ts.map +1 -0
  160. package/dist/utils/format.js +86 -0
  161. package/dist/utils/format.js.map +1 -0
  162. package/dist/utils/index.d.ts +10 -0
  163. package/dist/utils/index.d.ts.map +1 -0
  164. package/dist/utils/index.js +26 -0
  165. package/dist/utils/index.js.map +1 -0
  166. package/dist/utils/network.d.ts +52 -0
  167. package/dist/utils/network.d.ts.map +1 -0
  168. package/dist/utils/network.js +192 -0
  169. package/dist/utils/network.js.map +1 -0
  170. package/dist/utils/positionCalculations.d.ts +145 -0
  171. package/dist/utils/positionCalculations.d.ts.map +1 -0
  172. package/dist/utils/positionCalculations.js +278 -0
  173. package/dist/utils/positionCalculations.js.map +1 -0
  174. package/dist/utils/validation.d.ts +28 -0
  175. package/dist/utils/validation.d.ts.map +1 -0
  176. package/dist/utils/validation.js +68 -0
  177. package/dist/utils/validation.js.map +1 -0
  178. package/docs/README.md +40 -0
  179. package/docs/api/API.md +831 -0
  180. package/docs/guides/GETTING_STARTED.md +316 -0
  181. package/docs/guides/TRADING_GUIDE.md +677 -0
  182. package/docs/integration/INTEGRATION_GUIDE.md +1679 -0
  183. package/docs/integration/VIEM_INTEGRATION.md +294 -0
  184. package/docs/reference/CLI_QUICK_REFERENCE.md +197 -0
  185. package/docs/reference/TROUBLESHOOTING.md +922 -0
  186. package/package.json +113 -0
  187. package/src/AlphaFuturesClient.ts +158 -0
  188. package/src/abi/.gitkeep +1 -0
  189. package/src/abi/Alpha.json +5987 -0
  190. package/src/abi/README.md +99 -0
  191. package/src/abi/abis.ts +131 -0
  192. package/src/abi/index.ts +13 -0
  193. package/src/config/contracts.config.ts +186 -0
  194. package/src/config/environments/alpha.config.ts +139 -0
  195. package/src/config/environments/beta.config.ts +130 -0
  196. package/src/config/environments/dev.config.ts +122 -0
  197. package/src/config/environments/index.ts +87 -0
  198. package/src/config/environments/localhost.config.ts +153 -0
  199. package/src/config/environments/prod.config.ts +142 -0
  200. package/src/config/index.ts +29 -0
  201. package/src/constants/assets.ts +299 -0
  202. package/src/constants/contracts.ts +64 -0
  203. package/src/constants/index.ts +69 -0
  204. package/src/constants/networks.ts +182 -0
  205. package/src/contracts/index.ts +5 -0
  206. package/src/contracts/viem/AlphaViem.ts +1615 -0
  207. package/src/contracts/viem/PriceOracleViem.ts +272 -0
  208. package/src/contracts/viem/index.ts +11 -0
  209. package/src/errors/index.ts +87 -0
  210. package/src/index.ts +59 -0
  211. package/src/types/VIEM_TYPES_README.md +70 -0
  212. package/src/types/alpha.ts +358 -0
  213. package/src/types/client.ts +27 -0
  214. package/src/types/contracts.ts +74 -0
  215. package/src/types/funding.ts +31 -0
  216. package/src/types/index.ts +108 -0
  217. package/src/types/liquidation.ts +23 -0
  218. package/src/types/margin.ts +34 -0
  219. package/src/types/oracle.ts +24 -0
  220. package/src/types/positions.ts +48 -0
  221. package/src/utils/calculations.ts +175 -0
  222. package/src/utils/errors.ts +147 -0
  223. package/src/utils/events.ts +98 -0
  224. package/src/utils/format.ts +84 -0
  225. package/src/utils/index.ts +10 -0
  226. package/src/utils/network.ts +212 -0
  227. package/src/utils/positionCalculations.ts +317 -0
  228. package/src/utils/validation.ts +76 -0
@@ -0,0 +1,590 @@
1
+ /**
2
+ * Market Commands - View market data and analytics
3
+ */
4
+
5
+ import { Command } from 'commander';
6
+ import chalk from 'chalk';
7
+ import ora from 'ora';
8
+ import Table from 'cli-table3';
9
+ import { AlphaFuturesClient } from '../../src';
10
+ import { formatUSD, formatPercentage, formatNumber, formatTAO } from '../../src/utils';
11
+ import {
12
+ getClient,
13
+ handleError,
14
+ getMarketAddress,
15
+ listAvailableMarketAddresses,
16
+ } from '../utils/client';
17
+ import { createPriceChart, createVolumeChart } from '../utils/display';
18
+
19
+ export function marketCommands(program: Command) {
20
+ const market = program
21
+ .command('market')
22
+ .alias('mkt')
23
+ .description('View market data and analytics');
24
+
25
+ // Price command
26
+ market
27
+ .command('price <asset>')
28
+ .description('Get current price and 24h statistics')
29
+ .option('-w, --watch', 'Watch price in real-time')
30
+ .option('-i, --interval <seconds>', 'Update interval (default: 5)', '5')
31
+ .action(async (asset, options) => {
32
+ const spinner = ora('Loading price data...').start();
33
+
34
+ try {
35
+ const client = await getClient(program.opts());
36
+ asset = asset.toUpperCase();
37
+
38
+ const displayPrice = async () => {
39
+ const marketAddress = getMarketAddress(asset);
40
+ const currentPrice = await client.oracle.getPrice(marketAddress);
41
+ // Note: Monolith doesn't have getLatestPriceData method
42
+ const currentTime = Math.floor(Date.now() / 1000);
43
+
44
+ if (!options.watch) spinner.stop();
45
+
46
+ console.clear();
47
+ console.log(chalk.bold(`\n💹 ${asset} Price Information:`));
48
+ console.log(` Current Price: ${chalk.cyan(formatUSD(currentPrice))}`);
49
+ console.log(` Last Update: ${new Date(currentTime * 1000).toLocaleString()}`);
50
+
51
+ // 24h statistics require external data indexing
52
+ console.log(chalk.bold('\n📊 24h Statistics:'));
53
+ console.log(` ${chalk.yellow('⚠️ 24h statistics require external indexing service')}`);
54
+ console.log(` ${chalk.gray('Current implementation tracks real-time data only')}`);
55
+
56
+ if (program.opts().json) {
57
+ console.log(
58
+ '\n' +
59
+ JSON.stringify(
60
+ {
61
+ asset,
62
+ price: currentPrice.toString(),
63
+ timestamp: currentTime.toString(),
64
+ },
65
+ null,
66
+ 2,
67
+ ),
68
+ );
69
+ }
70
+ };
71
+
72
+ await displayPrice();
73
+
74
+ if (options.watch) {
75
+ const interval = parseInt(options.interval) * 1000;
76
+ setInterval(displayPrice, interval);
77
+
78
+ console.log(chalk.gray(`\nWatching price... (Ctrl+C to stop)`));
79
+
80
+ process.on('SIGINT', () => {
81
+ console.log(chalk.yellow('\n\nStopped watching'));
82
+ process.exit(0);
83
+ });
84
+ }
85
+ } catch (error) {
86
+ spinner.fail('Failed to load price data');
87
+ handleError(error, program.opts());
88
+ }
89
+ });
90
+
91
+ // Funding rate command (redirects to main funding command)
92
+ market
93
+ .command('funding [asset]')
94
+ .description('View funding rates (use "alpha-futures funding rate" for full features)')
95
+ .option('-h, --history', 'Show funding rate history')
96
+ .action(async (asset, options) => {
97
+ console.log(chalk.yellow('\n💡 Funding Rate Information:'));
98
+ console.log(chalk.gray('This command has been consolidated with the main funding command.'));
99
+ console.log(chalk.cyan('\nFor comprehensive funding rate information, use:'));
100
+ if (asset) {
101
+ console.log(chalk.white(` alpha-futures funding rate ${asset}`));
102
+ } else {
103
+ console.log(chalk.white(' alpha-futures funding rate --all'));
104
+ }
105
+ if (options.history) {
106
+ console.log(chalk.white(' alpha-futures funding history'));
107
+ }
108
+ });
109
+
110
+ // Open interest command
111
+ market
112
+ .command('oi [asset]')
113
+ .alias('openinterest')
114
+ .description('View open interest statistics')
115
+ .option('-d, --detailed', 'Show detailed breakdown')
116
+ .action(async (asset, options) => {
117
+ const spinner = ora('Loading open interest...').start();
118
+
119
+ try {
120
+ const client = await getClient(program.opts());
121
+
122
+ spinner.stop();
123
+
124
+ console.log(chalk.bold('\n📊 Open Interest Statistics:'));
125
+
126
+ if (asset) {
127
+ asset = asset.toUpperCase();
128
+
129
+ const marketAddress = getMarketAddress(asset);
130
+ try {
131
+ const openInterest = await client.getAlpha().getMarketOpenInterest(marketAddress);
132
+ const totalOI = openInterest.longOI + openInterest.shortOI;
133
+ const longRatio =
134
+ totalOI > 0n ? (Number(openInterest.longOI) * 100) / Number(totalOI) : 0;
135
+ const shortRatio =
136
+ totalOI > 0n ? (Number(openInterest.shortOI) * 100) / Number(totalOI) : 0;
137
+
138
+ console.log(`\n${chalk.cyan(asset)} Open Interest:`);
139
+ console.log(` Total OI: ${formatUSD(totalOI)}`);
140
+ console.log(` Long OI: ${formatUSD(openInterest.longOI)} (${longRatio.toFixed(1)}%)`);
141
+ console.log(
142
+ ` Short OI: ${formatUSD(openInterest.shortOI)} (${shortRatio.toFixed(1)}%)`,
143
+ );
144
+
145
+ if (totalOI > 0n) {
146
+ const ratio = Number(openInterest.longOI) / Number(openInterest.shortOI);
147
+ console.log(` Long/Short Ratio: ${ratio.toFixed(2)}`);
148
+
149
+ // Show skew indicator
150
+ if (longRatio > 60) {
151
+ console.log(` ${chalk.red('⚠️ Long-heavy market (potential funding payments)')}`);
152
+ } else if (shortRatio > 60) {
153
+ console.log(
154
+ ` ${chalk.red('⚠️ Short-heavy market (potential funding payments)')}`,
155
+ );
156
+ } else {
157
+ console.log(` ${chalk.green('✅ Balanced market')}`);
158
+ }
159
+ }
160
+ } catch (error) {
161
+ console.log(`\n${chalk.cyan(asset)} Open Interest:`);
162
+ console.log(` ${chalk.yellow('⚠️ Unable to fetch open interest data')}`);
163
+ console.log(` ${chalk.gray('Contract may not be properly initialized')}`);
164
+ }
165
+ } else {
166
+ // Overview of all assets
167
+ const table = new Table({
168
+ head: ['Asset', 'Total OI', 'Long OI', 'Short OI', 'L/S Ratio', 'Skew'],
169
+ colWidths: [10, 15, 15, 15, 12, 10],
170
+ });
171
+
172
+ // Get open interest for all markets
173
+ const availableMarkets = listAvailableMarketAddresses();
174
+ const markets = Object.keys(availableMarkets);
175
+
176
+ for (const asset of markets) {
177
+ try {
178
+ const marketAddress = getMarketAddress(asset);
179
+ const openInterest = await client.getAlpha().getMarketOpenInterest(marketAddress);
180
+ const totalOI = openInterest.longOI + openInterest.shortOI;
181
+ const longRatio =
182
+ totalOI > 0n ? (Number(openInterest.longOI) * 100) / Number(totalOI) : 0;
183
+ const shortRatio =
184
+ totalOI > 0n ? (Number(openInterest.shortOI) * 100) / Number(totalOI) : 0;
185
+ const ratio =
186
+ totalOI > 0n ? Number(openInterest.longOI) / Number(openInterest.shortOI) : 0;
187
+
188
+ // Calculate skew percentage
189
+ const skew =
190
+ totalOI > 0n
191
+ ? ((Number(openInterest.longOI) - Number(openInterest.shortOI)) /
192
+ Number(totalOI)) *
193
+ 100
194
+ : 0;
195
+ const skewDisplay = skew > 0 ? `+${skew.toFixed(1)}%` : `${skew.toFixed(1)}%`;
196
+
197
+ table.push([
198
+ asset,
199
+ formatUSD(totalOI),
200
+ formatUSD(openInterest.longOI),
201
+ formatUSD(openInterest.shortOI),
202
+ ratio > 0 ? ratio.toFixed(2) : 'N/A',
203
+ totalOI > 0n ? skewDisplay : 'N/A',
204
+ ]);
205
+ } catch (error) {
206
+ table.push([
207
+ asset,
208
+ chalk.gray('Error'),
209
+ chalk.gray('Error'),
210
+ chalk.gray('Error'),
211
+ chalk.gray('N/A'),
212
+ chalk.gray('N/A'),
213
+ ]);
214
+ }
215
+ }
216
+
217
+ console.log(table.toString());
218
+ console.log(chalk.gray('\n✅ Live open interest data from contract'));
219
+ }
220
+
221
+ if (options.detailed) {
222
+ console.log(chalk.bold('\n📈 OI Distribution Analysis:'));
223
+ console.log(
224
+ ` ${chalk.yellow('⚠️ Position size distribution requires event indexing')}`,
225
+ );
226
+ console.log(` ${chalk.gray('Available: Total OI, Long/Short breakdown, Market skew')}`);
227
+ console.log(
228
+ ` ${chalk.gray('Missing: Individual position size analysis, trader distribution')}`,
229
+ );
230
+ }
231
+ } catch (error) {
232
+ spinner.fail('Failed to load open interest');
233
+ handleError(error, program.opts());
234
+ }
235
+ });
236
+
237
+ // Stats command
238
+ market
239
+ .command('stats')
240
+ .description('View protocol-wide statistics')
241
+ .option('-p, --period <period>', 'Time period: 24h, 7d, 30d', '24h')
242
+ .action(async (options) => {
243
+ const spinner = ora('Loading protocol statistics...').start();
244
+
245
+ try {
246
+ const client = await getClient(program.opts());
247
+ const alpha = client.getAlpha();
248
+
249
+ // Get vault stats
250
+ const vaultStats = await alpha.getVaultStats();
251
+ const totalReserves = vaultStats.totalReserves;
252
+ const insuranceFund = 0n; // Not available in alpha structure
253
+
254
+ spinner.stop();
255
+
256
+ console.log(chalk.bold('\n📊 Protocol Statistics:'));
257
+ console.log(chalk.gray(`Period: ${options.period}`));
258
+
259
+ console.log(chalk.bold('\n💰 Vault Status:'));
260
+ console.log(` Total Reserves: ${formatUSD(totalReserves)}`);
261
+ console.log(` Insurance Fund: ${formatUSD(insuranceFund)}`);
262
+ console.log(` Utilization: ${chalk.gray('Coming soon')}`);
263
+
264
+ console.log(chalk.bold('\n📈 Trading Volume:'));
265
+ console.log(` ${options.period} Volume: ${chalk.gray('Coming soon')}`);
266
+ console.log(` Total Volume: ${chalk.gray('Coming soon')}`);
267
+ console.log(` Active Traders: ${chalk.gray('Coming soon')}`);
268
+ console.log(` Total Trades: ${chalk.gray('Coming soon')}`);
269
+
270
+ // Try to get current funding rates for context
271
+ try {
272
+ const availableMarkets = listAvailableMarketAddresses();
273
+ const markets = Object.keys(availableMarkets);
274
+
275
+ console.log(chalk.bold('\n🔄 Current Funding Rates:'));
276
+ for (const asset of markets.slice(0, 3)) {
277
+ // Limit to first 3 to avoid spam
278
+ try {
279
+ const marketAddress = getMarketAddress(asset);
280
+ const fundingRate = await alpha.getFundingRate(marketAddress);
281
+ console.log(` ${asset}: ${formatPercentage(fundingRate)} (per 8h)`);
282
+ } catch (e) {
283
+ console.log(` ${asset}: ${chalk.gray('N/A')}`);
284
+ }
285
+ }
286
+ } catch (e) {
287
+ console.log(chalk.bold('\n🔄 Funding Rates:'));
288
+ console.log(` ${chalk.gray('Unable to fetch current rates')}`);
289
+ }
290
+
291
+ console.log(chalk.bold('\n💸 Historical Data:'));
292
+ console.log(` ${chalk.yellow('⚠️ Trading volume, fees, and liquidation history')}`);
293
+ console.log(` ${chalk.yellow(' require external indexing service')}`);
294
+ console.log(
295
+ ` ${chalk.gray('Available: Current vault balance, funding rates, open interest')}`,
296
+ );
297
+ console.log(
298
+ ` ${chalk.gray('Missing: Historical volume, fee collection, liquidation events')}`,
299
+ );
300
+ } catch (error) {
301
+ spinner.fail('Failed to load statistics');
302
+ handleError(error, program.opts());
303
+ }
304
+ });
305
+
306
+ // Orderbook command
307
+ market
308
+ .command('book <asset>')
309
+ .alias('orderbook')
310
+ .description('View orderbook for an asset')
311
+ .option('-d, --depth <levels>', 'Number of levels to show', '10')
312
+ .option('-w, --watch', 'Watch orderbook in real-time')
313
+ .action(async (asset, options) => {
314
+ const spinner = ora('Loading orderbook...').start();
315
+
316
+ try {
317
+ const client = await getClient(program.opts());
318
+ const alpha = client.getAlpha();
319
+
320
+ asset = asset.toUpperCase();
321
+ const depth = parseInt(options.depth);
322
+ const marketAddress = getMarketAddress(asset);
323
+
324
+ const displayOrderbook = async () => {
325
+ // Get orderbook data using the orderBook client
326
+ const orderBookData = await client.orderBook.getOrderBook(marketAddress);
327
+ const { buyOrders: bids, sellOrders: asks } = orderBookData;
328
+
329
+ if (!options.watch) spinner.stop();
330
+
331
+ // Get current price
332
+ const currentPrice = await client.oracle.getPrice(marketAddress);
333
+
334
+ console.clear();
335
+ console.log(chalk.bold(`\n📖 ${asset} Orderbook:`));
336
+ console.log(` Current Price: ${formatUSD(currentPrice)}`);
337
+
338
+ // Calculate spread if we have bids and asks
339
+ if (bids.length > 0 && asks.length > 0) {
340
+ const spreadInfo = await client.orderBook.getSpread(marketAddress);
341
+ const spread = spreadInfo.spread;
342
+ const spreadPercent = (Number(spread) * 100) / Number(currentPrice);
343
+ console.log(` Spread: ${formatUSD(spread)} (${spreadPercent.toFixed(3)}%)`);
344
+ }
345
+
346
+ console.log('');
347
+
348
+ // Create orderbook table
349
+ const table = new Table({
350
+ head: [
351
+ chalk.green('Bid Price'),
352
+ chalk.green('Size'),
353
+ chalk.green('Total'),
354
+ '│',
355
+ chalk.red('Ask Price'),
356
+ chalk.red('Size'),
357
+ chalk.red('Total'),
358
+ ],
359
+ colWidths: [12, 12, 12, 3, 12, 12, 12],
360
+ style: { 'padding-left': 0, 'padding-right': 0 },
361
+ });
362
+
363
+ // Process bids and asks
364
+ let bidTotal = 0n;
365
+ let askTotal = 0n;
366
+
367
+ const maxRows = Math.max(bids.length, asks.length);
368
+
369
+ for (let i = 0; i < maxRows; i++) {
370
+ const bidRow = ['', '', ''];
371
+ const askRow = ['', '', ''];
372
+
373
+ if (i < bids.length) {
374
+ bidTotal += bids[i].size;
375
+ bidRow[0] = formatUSD(bids[i].price);
376
+ bidRow[1] = formatUSD(bids[i].size);
377
+ bidRow[2] = formatUSD(bidTotal);
378
+ }
379
+
380
+ if (i < asks.length) {
381
+ askTotal += asks[i].size;
382
+ askRow[0] = formatUSD(asks[i].price);
383
+ askRow[1] = formatUSD(asks[i].size);
384
+ askRow[2] = formatUSD(askTotal);
385
+ }
386
+
387
+ table.push([...bidRow, '│', ...askRow]);
388
+ }
389
+
390
+ console.log(table.toString());
391
+
392
+ // Show market depth stats
393
+ console.log(chalk.bold('\n📊 Market Depth:'));
394
+ console.log(` Total Bids: ${formatUSD(bidTotal)}`);
395
+ console.log(` Total Asks: ${formatUSD(askTotal)}`);
396
+ console.log(
397
+ ` Imbalance: ${bidTotal > askTotal ? chalk.green('+' + formatUSD(bidTotal - askTotal) + ' (bid heavy)') : chalk.red('-' + formatUSD(askTotal - bidTotal) + ' (ask heavy)')}`,
398
+ );
399
+
400
+ if (options.watch) {
401
+ console.log(chalk.gray('\n⟳ Refreshing every 2 seconds... (Ctrl+C to exit)'));
402
+ }
403
+ };
404
+
405
+ await displayOrderbook();
406
+
407
+ if (options.watch) {
408
+ // Update every 2 seconds
409
+ const interval = setInterval(displayOrderbook, 2000);
410
+
411
+ // Handle exit
412
+ process.on('SIGINT', () => {
413
+ clearInterval(interval);
414
+ console.log(chalk.yellow('\n\nStopped watching orderbook'));
415
+ process.exit(0);
416
+ });
417
+ }
418
+ } catch (error) {
419
+ spinner.fail('Failed to load orderbook');
420
+ // If orderbook not available, show a message
421
+ if (
422
+ error.message?.includes('function') ||
423
+ error.message?.includes('getOrderBook') ||
424
+ error.message?.includes('execution reverted')
425
+ ) {
426
+ console.log(chalk.yellow('\n⚠️ Orderbook functionality not available'));
427
+ console.log(
428
+ chalk.gray('This feature requires orderbook data from the protocol contracts.'),
429
+ );
430
+ console.log(chalk.gray('You can still view market prices and funding information.'));
431
+ } else {
432
+ handleError(error, program.opts());
433
+ }
434
+ }
435
+ });
436
+
437
+ // Markets overview command
438
+ market
439
+ .command('list')
440
+ .alias('ls')
441
+ .description('List all available markets')
442
+ .option('-s, --sort <field>', 'Sort by: volume, price, change', 'volume')
443
+ .action(async (options) => {
444
+ const spinner = ora('Loading markets...').start();
445
+
446
+ try {
447
+ const client = await getClient(program.opts());
448
+ const alpha = client.getAlpha();
449
+
450
+ spinner.stop();
451
+
452
+ console.log(chalk.bold('\n📈 Available Markets:'));
453
+
454
+ const table = new Table({
455
+ head: ['Asset', 'Price', '24h Change', '24h Volume', 'Funding', 'OI'],
456
+ colWidths: [10, 15, 15, 15, 15, 15],
457
+ });
458
+
459
+ // Get list of all markets from environment variables
460
+ const availableMarkets = listAvailableMarketAddresses();
461
+ const markets = Object.keys(availableMarkets);
462
+
463
+ for (const asset of markets) {
464
+ try {
465
+ const marketAddress = getMarketAddress(asset);
466
+ const price = await client.oracle.getPrice(marketAddress);
467
+ const fundingRate = await alpha.getFundingRate(marketAddress);
468
+
469
+ // Get open interest
470
+ let openInterestDisplay = chalk.gray('N/A');
471
+ try {
472
+ const openInterest = await alpha.getMarketOpenInterest(marketAddress);
473
+ const totalOI = openInterest.longOI + openInterest.shortOI;
474
+ openInterestDisplay = formatUSD(totalOI);
475
+ } catch {
476
+ openInterestDisplay = chalk.gray('N/A');
477
+ }
478
+
479
+ table.push([
480
+ asset,
481
+ formatUSD(price),
482
+ chalk.gray('N/A'), // 24h change
483
+ chalk.gray('N/A'), // 24h volume
484
+ formatPercentage(fundingRate),
485
+ openInterestDisplay,
486
+ ]);
487
+ } catch (e) {
488
+ table.push([
489
+ asset,
490
+ chalk.gray('N/A'),
491
+ chalk.gray('N/A'),
492
+ chalk.gray('N/A'),
493
+ chalk.gray('N/A'),
494
+ chalk.gray('N/A'),
495
+ ]);
496
+ }
497
+ }
498
+
499
+ console.log(table.toString());
500
+ console.log(chalk.gray('\n✅ Live data: prices, funding rates, open interest'));
501
+ console.log(chalk.yellow('⚠️ 24h statistics require external indexing service'));
502
+ } catch (error) {
503
+ spinner.fail('Failed to load markets');
504
+ handleError(error, program.opts());
505
+ }
506
+ });
507
+
508
+ // Chart command (ASCII charts)
509
+ market
510
+ .command('chart <asset>')
511
+ .description('Display price chart (ASCII)')
512
+ .option('-p, --period <period>', 'Time period: 1h, 4h, 1d, 1w', '1d')
513
+ .option('-t, --type <type>', 'Chart type: line, candle', 'line')
514
+ .action(async (asset, options) => {
515
+ console.log(chalk.yellow('\n⚠️ Price charts coming soon!'));
516
+ console.log(chalk.gray('Will display ASCII charts for quick price visualization'));
517
+
518
+ // Mock chart display
519
+ console.log(chalk.bold(`\n${asset.toUpperCase()} - ${options.period} Chart:`));
520
+ console.log(createPriceChart()); // Placeholder function
521
+ });
522
+
523
+ // Configuration validation command
524
+ market
525
+ .command('config')
526
+ .alias('env')
527
+ .description('Check market configuration and available assets')
528
+ .action(async () => {
529
+ try {
530
+ console.log(chalk.bold('\n🔧 Market Configuration Status:'));
531
+
532
+ const availableMarkets = listAvailableMarketAddresses();
533
+
534
+ if (Object.keys(availableMarkets).length === 0) {
535
+ console.log(chalk.red('\n❌ No market addresses found!'));
536
+ console.log(
537
+ chalk.yellow('\nPlease ensure you have set the required environment variables:'),
538
+ );
539
+ console.log(' • Available subnet markets: BITMIND, CHUTES, AFFINE, RIDGES');
540
+ console.log(' • All markets use contract addresses from constants');
541
+ return;
542
+ }
543
+
544
+ console.log(chalk.green('\n✅ Available Markets:'));
545
+ const table = new Table({
546
+ head: ['Asset', 'Contract Address'],
547
+ colWidths: [15, 45],
548
+ });
549
+
550
+ Object.entries(availableMarkets).forEach(([asset, address]) => {
551
+ table.push([chalk.cyan(asset), chalk.gray(address)]);
552
+ });
553
+
554
+ console.log(table.toString());
555
+
556
+ // Show environment variables being used
557
+ console.log(chalk.bold('\n📋 Environment Variables:'));
558
+ const envTable = new Table({
559
+ head: ['Variable', 'Value'],
560
+ colWidths: [30, 45],
561
+ });
562
+
563
+ const relevantEnvVars = Object.keys(process.env)
564
+ .filter(
565
+ (key) =>
566
+ key.startsWith('ALPHA_') ||
567
+ key.startsWith('ANVIL_ALPHA_') ||
568
+ key.includes('_ADDRESS'),
569
+ )
570
+ .sort();
571
+
572
+ relevantEnvVars.forEach((key) => {
573
+ const value = process.env[key];
574
+ if (value) {
575
+ const displayValue = value.length > 42 ? `${value.slice(0, 42)}...` : value;
576
+ envTable.push([chalk.cyan(key), chalk.gray(displayValue)]);
577
+ }
578
+ });
579
+
580
+ console.log(envTable.toString());
581
+
582
+ console.log(chalk.bold('\n💡 Usage Examples:'));
583
+ console.log(' alpha-futures market price BITMIND');
584
+ console.log(' alpha-futures market funding CHUTES');
585
+ console.log(' alpha-futures position open -a BITMIND -d long -s 1000 -m 333');
586
+ } catch (error) {
587
+ handleError(error, program.opts());
588
+ }
589
+ });
590
+ }