@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.
- package/.env.example +37 -0
- package/CHANGELOG.md +19 -0
- package/README.md +199 -0
- package/bin/alf +4 -0
- package/cli/README.md +198 -0
- package/cli/TEST_MANUAL.md +577 -0
- package/cli/commands/account.ts +545 -0
- package/cli/commands/funding.ts +481 -0
- package/cli/commands/liquidation.ts +523 -0
- package/cli/commands/market.ts +590 -0
- package/cli/commands/orders.ts +395 -0
- package/cli/commands/position.ts +1085 -0
- package/cli/commands/shared/positionUtils.ts +239 -0
- package/cli/commands/trading.ts +483 -0
- package/cli/commands/utils.ts +281 -0
- package/cli/commands/vault.ts +522 -0
- package/cli/index.ts +169 -0
- package/cli/interactive.ts +530 -0
- package/cli/utils/client.ts +457 -0
- package/cli/utils/config.ts +226 -0
- package/cli/utils/display.ts +258 -0
- package/cli/utils/index.ts +10 -0
- package/cli/utils/prompts.ts +364 -0
- package/config.example.json +23 -0
- package/dist/AlphaFuturesClient.d.ts +36 -0
- package/dist/AlphaFuturesClient.d.ts.map +1 -0
- package/dist/AlphaFuturesClient.js +116 -0
- package/dist/AlphaFuturesClient.js.map +1 -0
- package/dist/abi/Alpha.json +5987 -0
- package/dist/abi/abis.d.ts +319 -0
- package/dist/abi/abis.d.ts.map +1 -0
- package/dist/abi/abis.js +128 -0
- package/dist/abi/abis.js.map +1 -0
- package/dist/abi/index.d.ts +11 -0
- package/dist/abi/index.d.ts.map +1 -0
- package/dist/abi/index.js +15 -0
- package/dist/abi/index.js.map +1 -0
- package/dist/config/contracts.config.d.ts +70 -0
- package/dist/config/contracts.config.d.ts.map +1 -0
- package/dist/config/contracts.config.js +137 -0
- package/dist/config/contracts.config.js.map +1 -0
- package/dist/config/environments/alpha.config.d.ts +17 -0
- package/dist/config/environments/alpha.config.d.ts.map +1 -0
- package/dist/config/environments/alpha.config.js +140 -0
- package/dist/config/environments/alpha.config.js.map +1 -0
- package/dist/config/environments/beta.config.d.ts +16 -0
- package/dist/config/environments/beta.config.d.ts.map +1 -0
- package/dist/config/environments/beta.config.js +131 -0
- package/dist/config/environments/beta.config.js.map +1 -0
- package/dist/config/environments/dev.config.d.ts +13 -0
- package/dist/config/environments/dev.config.d.ts.map +1 -0
- package/dist/config/environments/dev.config.js +123 -0
- package/dist/config/environments/dev.config.js.map +1 -0
- package/dist/config/environments/index.d.ts +48 -0
- package/dist/config/environments/index.d.ts.map +1 -0
- package/dist/config/environments/index.js +81 -0
- package/dist/config/environments/index.js.map +1 -0
- package/dist/config/environments/localhost.config.d.ts +16 -0
- package/dist/config/environments/localhost.config.d.ts.map +1 -0
- package/dist/config/environments/localhost.config.js +152 -0
- package/dist/config/environments/localhost.config.js.map +1 -0
- package/dist/config/environments/prod.config.d.ts +20 -0
- package/dist/config/environments/prod.config.d.ts.map +1 -0
- package/dist/config/environments/prod.config.js +143 -0
- package/dist/config/environments/prod.config.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +41 -0
- package/dist/config/index.js.map +1 -0
- package/dist/constants/assets.d.ts +76 -0
- package/dist/constants/assets.d.ts.map +1 -0
- package/dist/constants/assets.js +277 -0
- package/dist/constants/assets.js.map +1 -0
- package/dist/constants/contracts.d.ts +41 -0
- package/dist/constants/contracts.d.ts.map +1 -0
- package/dist/constants/contracts.js +57 -0
- package/dist/constants/contracts.js.map +1 -0
- package/dist/constants/index.d.ts +36 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +75 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/constants/networks.d.ts +32 -0
- package/dist/constants/networks.d.ts.map +1 -0
- package/dist/constants/networks.js +174 -0
- package/dist/constants/networks.js.map +1 -0
- package/dist/contracts/index.d.ts +5 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +21 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/viem/AlphaViem.d.ts +518 -0
- package/dist/contracts/viem/AlphaViem.d.ts.map +1 -0
- package/dist/contracts/viem/AlphaViem.js +1287 -0
- package/dist/contracts/viem/AlphaViem.js.map +1 -0
- package/dist/contracts/viem/PriceOracleViem.d.ts +71 -0
- package/dist/contracts/viem/PriceOracleViem.d.ts.map +1 -0
- package/dist/contracts/viem/PriceOracleViem.js +212 -0
- package/dist/contracts/viem/PriceOracleViem.js.map +1 -0
- package/dist/contracts/viem/index.d.ts +9 -0
- package/dist/contracts/viem/index.d.ts.map +1 -0
- package/dist/contracts/viem/index.js +17 -0
- package/dist/contracts/viem/index.js.map +1 -0
- package/dist/errors/index.d.ts +44 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +83 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/types/alpha.d.ts +299 -0
- package/dist/types/alpha.d.ts.map +1 -0
- package/dist/types/alpha.js +6 -0
- package/dist/types/alpha.js.map +1 -0
- package/dist/types/client.d.ts +24 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +13 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/contracts.d.ts +48 -0
- package/dist/types/contracts.d.ts.map +1 -0
- package/dist/types/contracts.js +6 -0
- package/dist/types/contracts.js.map +1 -0
- package/dist/types/funding.d.ts +27 -0
- package/dist/types/funding.d.ts.map +1 -0
- package/dist/types/funding.js +6 -0
- package/dist/types/funding.js.map +1 -0
- package/dist/types/index.d.ts +92 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +47 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/liquidation.d.ts +20 -0
- package/dist/types/liquidation.d.ts.map +1 -0
- package/dist/types/liquidation.js +6 -0
- package/dist/types/liquidation.js.map +1 -0
- package/dist/types/margin.d.ts +29 -0
- package/dist/types/margin.d.ts.map +1 -0
- package/dist/types/margin.js +6 -0
- package/dist/types/margin.js.map +1 -0
- package/dist/types/oracle.d.ts +21 -0
- package/dist/types/oracle.d.ts.map +1 -0
- package/dist/types/oracle.js +6 -0
- package/dist/types/oracle.js.map +1 -0
- package/dist/types/positions.d.ts +43 -0
- package/dist/types/positions.d.ts.map +1 -0
- package/dist/types/positions.js +13 -0
- package/dist/types/positions.js.map +1 -0
- package/dist/utils/calculations.d.ts +84 -0
- package/dist/utils/calculations.d.ts.map +1 -0
- package/dist/utils/calculations.js +155 -0
- package/dist/utils/calculations.js.map +1 -0
- package/dist/utils/errors.d.ts +24 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +129 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/events.d.ts +40 -0
- package/dist/utils/events.d.ts.map +1 -0
- package/dist/utils/events.js +73 -0
- package/dist/utils/events.js.map +1 -0
- package/dist/utils/format.d.ts +40 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +86 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +26 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/network.d.ts +52 -0
- package/dist/utils/network.d.ts.map +1 -0
- package/dist/utils/network.js +192 -0
- package/dist/utils/network.js.map +1 -0
- package/dist/utils/positionCalculations.d.ts +145 -0
- package/dist/utils/positionCalculations.d.ts.map +1 -0
- package/dist/utils/positionCalculations.js +278 -0
- package/dist/utils/positionCalculations.js.map +1 -0
- package/dist/utils/validation.d.ts +28 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +68 -0
- package/dist/utils/validation.js.map +1 -0
- package/docs/README.md +40 -0
- package/docs/api/API.md +831 -0
- package/docs/guides/GETTING_STARTED.md +316 -0
- package/docs/guides/TRADING_GUIDE.md +677 -0
- package/docs/integration/INTEGRATION_GUIDE.md +1679 -0
- package/docs/integration/VIEM_INTEGRATION.md +294 -0
- package/docs/reference/CLI_QUICK_REFERENCE.md +197 -0
- package/docs/reference/TROUBLESHOOTING.md +922 -0
- package/package.json +113 -0
- package/src/AlphaFuturesClient.ts +158 -0
- package/src/abi/.gitkeep +1 -0
- package/src/abi/Alpha.json +5987 -0
- package/src/abi/README.md +99 -0
- package/src/abi/abis.ts +131 -0
- package/src/abi/index.ts +13 -0
- package/src/config/contracts.config.ts +186 -0
- package/src/config/environments/alpha.config.ts +139 -0
- package/src/config/environments/beta.config.ts +130 -0
- package/src/config/environments/dev.config.ts +122 -0
- package/src/config/environments/index.ts +87 -0
- package/src/config/environments/localhost.config.ts +153 -0
- package/src/config/environments/prod.config.ts +142 -0
- package/src/config/index.ts +29 -0
- package/src/constants/assets.ts +299 -0
- package/src/constants/contracts.ts +64 -0
- package/src/constants/index.ts +69 -0
- package/src/constants/networks.ts +182 -0
- package/src/contracts/index.ts +5 -0
- package/src/contracts/viem/AlphaViem.ts +1615 -0
- package/src/contracts/viem/PriceOracleViem.ts +272 -0
- package/src/contracts/viem/index.ts +11 -0
- package/src/errors/index.ts +87 -0
- package/src/index.ts +59 -0
- package/src/types/VIEM_TYPES_README.md +70 -0
- package/src/types/alpha.ts +358 -0
- package/src/types/client.ts +27 -0
- package/src/types/contracts.ts +74 -0
- package/src/types/funding.ts +31 -0
- package/src/types/index.ts +108 -0
- package/src/types/liquidation.ts +23 -0
- package/src/types/margin.ts +34 -0
- package/src/types/oracle.ts +24 -0
- package/src/types/positions.ts +48 -0
- package/src/utils/calculations.ts +175 -0
- package/src/utils/errors.ts +147 -0
- package/src/utils/events.ts +98 -0
- package/src/utils/format.ts +84 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/network.ts +212 -0
- package/src/utils/positionCalculations.ts +317 -0
- 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
|
+
}
|