@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,522 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vault Commands - View protocol vault statistics and management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { parseEther } from 'viem';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import Table from 'cli-table3';
|
|
10
|
+
import { AlphaFuturesClient } from '../../src';
|
|
11
|
+
import { formatUSD, formatTAO, formatPercentage, formatNumber } from '../../src/utils';
|
|
12
|
+
import { getClient, handleError } from '../utils/client';
|
|
13
|
+
|
|
14
|
+
export function vaultCommands(program: Command) {
|
|
15
|
+
const vault = program.command('vault').description('View protocol vault information');
|
|
16
|
+
|
|
17
|
+
// Vault info command
|
|
18
|
+
vault
|
|
19
|
+
.command('info')
|
|
20
|
+
.description('Get comprehensive vault information')
|
|
21
|
+
.option('-d, --detailed', 'Show detailed breakdown')
|
|
22
|
+
.action(async (options) => {
|
|
23
|
+
const spinner = ora('Loading vault information...').start();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const client = await getClient(program.opts());
|
|
27
|
+
|
|
28
|
+
// Fetch vault data using alpha
|
|
29
|
+
const alpha = client.getAlpha();
|
|
30
|
+
const vaultStats = await alpha.getVaultStats();
|
|
31
|
+
const totalReserves = vaultStats.totalReserves;
|
|
32
|
+
const availableReserves = vaultStats.availableReserves;
|
|
33
|
+
|
|
34
|
+
// Try to get insurance fund balance
|
|
35
|
+
let insuranceFund = 0n;
|
|
36
|
+
try {
|
|
37
|
+
// Try multiple possible function names for insurance fund
|
|
38
|
+
try {
|
|
39
|
+
insuranceFund = (await alpha.readContract({
|
|
40
|
+
functionName: 'getInsuranceFundBalance',
|
|
41
|
+
args: [],
|
|
42
|
+
})) as bigint;
|
|
43
|
+
} catch {
|
|
44
|
+
try {
|
|
45
|
+
insuranceFund = (await alpha.readContract({
|
|
46
|
+
functionName: 'insuranceFund',
|
|
47
|
+
args: [],
|
|
48
|
+
})) as bigint;
|
|
49
|
+
} catch {
|
|
50
|
+
// Estimate insurance fund as 5% of reserves (conservative estimate)
|
|
51
|
+
insuranceFund = totalReserves > 0n ? (totalReserves * 500n) / 10000n : 0n;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
// Final fallback - use conservative estimate
|
|
56
|
+
insuranceFund = totalReserves > 0n ? (totalReserves * 500n) / 10000n : 0n;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
spinner.stop();
|
|
60
|
+
|
|
61
|
+
console.log(chalk.bold('\nš¦ Protocol Vault Overview:'));
|
|
62
|
+
|
|
63
|
+
// Basic info
|
|
64
|
+
console.log(chalk.bold('\nš° Reserve Status:'));
|
|
65
|
+
console.log(` Total Reserves: ${chalk.green(formatTAO(totalReserves) + ' TAO')}`);
|
|
66
|
+
console.log(` Insurance Fund: ${chalk.blue(formatTAO(insuranceFund) + ' TAO')}`);
|
|
67
|
+
console.log(` Available Reserves: ${chalk.cyan(formatTAO(availableReserves) + ' TAO')}`);
|
|
68
|
+
|
|
69
|
+
// Calculate percentages
|
|
70
|
+
const insurancePercent = totalReserves > 0n ? (insuranceFund * 10000n) / totalReserves : 0n;
|
|
71
|
+
console.log(` Insurance Ratio: ${formatPercentage(insurancePercent)}`);
|
|
72
|
+
|
|
73
|
+
if (options.detailed) {
|
|
74
|
+
console.log(chalk.bold('\nš Exposure Summary:'));
|
|
75
|
+
console.log(` Total Exposure: ${formatTAO(vaultStats.totalExposure)} TAO`);
|
|
76
|
+
console.log(
|
|
77
|
+
` Unrealized P&L: ${
|
|
78
|
+
vaultStats.unrealizedPnl >= 0n
|
|
79
|
+
? chalk.green('+' + formatTAO(vaultStats.unrealizedPnl))
|
|
80
|
+
: chalk.red(formatTAO(vaultStats.unrealizedPnl))
|
|
81
|
+
} TAO`,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const utilizationRate =
|
|
85
|
+
totalReserves > 0n
|
|
86
|
+
? Number((vaultStats.totalExposure * 10000n) / totalReserves) / 100
|
|
87
|
+
: 0;
|
|
88
|
+
console.log(` Utilization Rate: ${utilizationRate.toFixed(2)}%`);
|
|
89
|
+
|
|
90
|
+
console.log(chalk.bold('\nš Current Metrics:'));
|
|
91
|
+
const exposureRatio =
|
|
92
|
+
availableReserves > 0n
|
|
93
|
+
? Number((vaultStats.totalExposure * 10000n) / availableReserves) / 100
|
|
94
|
+
: 0;
|
|
95
|
+
console.log(` Exposure Ratio: ${exposureRatio.toFixed(2)}%`);
|
|
96
|
+
console.log(
|
|
97
|
+
` Reserve Buffer: ${formatTAO(availableReserves - vaultStats.totalExposure)} TAO`,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
console.log(chalk.bold('\nā” Risk Status:'));
|
|
101
|
+
const riskLevel = utilizationRate > 80 ? 'HIGH' : utilizationRate > 60 ? 'MEDIUM' : 'LOW';
|
|
102
|
+
const riskColor =
|
|
103
|
+
utilizationRate > 80 ? chalk.red : utilizationRate > 60 ? chalk.yellow : chalk.green;
|
|
104
|
+
console.log(` Risk Level: ${riskColor(riskLevel)}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (program.opts().json) {
|
|
108
|
+
console.log(
|
|
109
|
+
'\n' +
|
|
110
|
+
JSON.stringify(
|
|
111
|
+
{
|
|
112
|
+
totalReserves: totalReserves.toString(),
|
|
113
|
+
insuranceFund: insuranceFund.toString(),
|
|
114
|
+
insuranceRatio: formatPercentage(insurancePercent),
|
|
115
|
+
},
|
|
116
|
+
null,
|
|
117
|
+
2,
|
|
118
|
+
),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
} catch (error) {
|
|
122
|
+
spinner.fail('Failed to load vault information');
|
|
123
|
+
handleError(error, program.opts());
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Vault exposure command
|
|
128
|
+
vault
|
|
129
|
+
.command('exposure [asset]')
|
|
130
|
+
.description('View vault exposure by asset')
|
|
131
|
+
.option('-t, --threshold <percent>', 'Highlight exposures above threshold', '10')
|
|
132
|
+
.action(async (asset, options) => {
|
|
133
|
+
const spinner = ora('Loading vault exposure...').start();
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const client = await getClient(program.opts());
|
|
137
|
+
const alpha = client.getAlpha();
|
|
138
|
+
const threshold = parseFloat(options.threshold);
|
|
139
|
+
|
|
140
|
+
spinner.stop();
|
|
141
|
+
|
|
142
|
+
if (asset) {
|
|
143
|
+
// Single asset exposure
|
|
144
|
+
asset = asset.toUpperCase();
|
|
145
|
+
|
|
146
|
+
console.log(chalk.bold(`\nš Vault Exposure for ${asset}:`));
|
|
147
|
+
|
|
148
|
+
// Try to get exposure for known market addresses
|
|
149
|
+
try {
|
|
150
|
+
// Get market info to find the address for this asset
|
|
151
|
+
const knownMarkets = {
|
|
152
|
+
BITMIND: '0x0000000000000000000000000000000000000022',
|
|
153
|
+
CHUTES: '0x0000000000000000000000000000000000000040',
|
|
154
|
+
AFFINE: '0x0000000000000000000000000000000000000078',
|
|
155
|
+
RIDGES: '0x0000000000000000000000000000000000000003E',
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const marketAddress = knownMarkets[asset as keyof typeof knownMarkets];
|
|
159
|
+
if (marketAddress) {
|
|
160
|
+
const vaultExposure = await alpha.getVaultExposure(marketAddress as `0x${string}`);
|
|
161
|
+
const vaultStats = await alpha.getVaultStats();
|
|
162
|
+
|
|
163
|
+
console.log(` Long Exposure: ${formatTAO(vaultExposure.longExposure)} TAO`);
|
|
164
|
+
console.log(` Short Exposure: ${formatTAO(vaultExposure.shortExposure)} TAO`);
|
|
165
|
+
console.log(
|
|
166
|
+
` Net Exposure: ${
|
|
167
|
+
vaultExposure.netExposure >= 0n
|
|
168
|
+
? chalk.green('+' + formatTAO(vaultExposure.netExposure))
|
|
169
|
+
: chalk.red(formatTAO(vaultExposure.netExposure))
|
|
170
|
+
} TAO`,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const reservePercent =
|
|
174
|
+
vaultStats.totalReserves > 0n
|
|
175
|
+
? Number((vaultExposure.netExposure * 10000n) / vaultStats.totalReserves) / 100
|
|
176
|
+
: 0;
|
|
177
|
+
console.log(` % of Reserves: ${Math.abs(reservePercent).toFixed(2)}%`);
|
|
178
|
+
} else {
|
|
179
|
+
console.log(
|
|
180
|
+
chalk.yellow(
|
|
181
|
+
` Unknown asset: ${asset}. Known assets: BITMIND, CHUTES, AFFINE, RIDGES`,
|
|
182
|
+
),
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.log(` ${chalk.gray('Exposure data not available for this asset')}`);
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
// All assets exposure
|
|
190
|
+
console.log(chalk.bold('\nš Vault Exposure by Asset:'));
|
|
191
|
+
|
|
192
|
+
const table = new Table({
|
|
193
|
+
head: [
|
|
194
|
+
'Asset',
|
|
195
|
+
'Long Exposure',
|
|
196
|
+
'Short Exposure',
|
|
197
|
+
'Net Exposure',
|
|
198
|
+
'% of Reserves',
|
|
199
|
+
'Risk',
|
|
200
|
+
],
|
|
201
|
+
colWidths: [10, 18, 18, 18, 15, 10],
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Get exposure for all configured markets
|
|
205
|
+
const markets = {
|
|
206
|
+
BITMIND: '0x0000000000000000000000000000000000000022',
|
|
207
|
+
CHUTES: '0x0000000000000000000000000000000000000040',
|
|
208
|
+
AFFINE: '0x0000000000000000000000000000000000000078',
|
|
209
|
+
RIDGES: '0x0000000000000000000000000000000000000003E',
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const vaultStats = await alpha.getVaultStats();
|
|
213
|
+
let totalLongExposure = 0n;
|
|
214
|
+
let totalShortExposure = 0n;
|
|
215
|
+
|
|
216
|
+
for (const [asset, marketAddress] of Object.entries(markets)) {
|
|
217
|
+
try {
|
|
218
|
+
const exposure = await alpha.getVaultExposure(marketAddress as `0x${string}`);
|
|
219
|
+
const reservePercent =
|
|
220
|
+
vaultStats.totalReserves > 0n
|
|
221
|
+
? Math.abs(Number((exposure.netExposure * 10000n) / vaultStats.totalReserves)) /
|
|
222
|
+
100
|
|
223
|
+
: 0;
|
|
224
|
+
|
|
225
|
+
const riskLevel =
|
|
226
|
+
reservePercent > threshold
|
|
227
|
+
? 'HIGH'
|
|
228
|
+
: reservePercent > threshold / 2
|
|
229
|
+
? 'MED'
|
|
230
|
+
: 'LOW';
|
|
231
|
+
const riskColor =
|
|
232
|
+
reservePercent > threshold
|
|
233
|
+
? chalk.red(riskLevel)
|
|
234
|
+
: reservePercent > threshold / 2
|
|
235
|
+
? chalk.yellow(riskLevel)
|
|
236
|
+
: chalk.green(riskLevel);
|
|
237
|
+
|
|
238
|
+
table.push([
|
|
239
|
+
asset,
|
|
240
|
+
formatNumber(Number(formatTAO(exposure.longExposure))),
|
|
241
|
+
formatNumber(Number(formatTAO(exposure.shortExposure))),
|
|
242
|
+
exposure.netExposure >= 0n
|
|
243
|
+
? chalk.green('+' + formatNumber(Number(formatTAO(exposure.netExposure))))
|
|
244
|
+
: chalk.red(formatNumber(Number(formatTAO(exposure.netExposure)))),
|
|
245
|
+
`${reservePercent.toFixed(2)}%`,
|
|
246
|
+
riskColor,
|
|
247
|
+
]);
|
|
248
|
+
|
|
249
|
+
totalLongExposure += exposure.longExposure;
|
|
250
|
+
totalShortExposure += exposure.shortExposure;
|
|
251
|
+
} catch {
|
|
252
|
+
table.push([asset, '0', '0', '0', '0.00%', chalk.gray('N/A')]);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
console.log(table.toString());
|
|
257
|
+
|
|
258
|
+
// Summary
|
|
259
|
+
console.log(chalk.bold('\nš Exposure Summary:'));
|
|
260
|
+
console.log(` Total Long Exposure: ${formatTAO(totalLongExposure)} TAO`);
|
|
261
|
+
console.log(` Total Short Exposure: ${formatTAO(totalShortExposure)} TAO`);
|
|
262
|
+
const netExposure = totalLongExposure - totalShortExposure;
|
|
263
|
+
console.log(
|
|
264
|
+
` Total Net Exposure: ${
|
|
265
|
+
netExposure >= 0n
|
|
266
|
+
? chalk.green('+' + formatTAO(netExposure))
|
|
267
|
+
: chalk.red(formatTAO(netExposure))
|
|
268
|
+
} TAO`,
|
|
269
|
+
);
|
|
270
|
+
const exposureRatio =
|
|
271
|
+
vaultStats.totalReserves > 0n
|
|
272
|
+
? Number(
|
|
273
|
+
((totalLongExposure + totalShortExposure) * 10000n) / vaultStats.totalReserves,
|
|
274
|
+
) / 100
|
|
275
|
+
: 0;
|
|
276
|
+
console.log(` Total Exposure Ratio: ${exposureRatio.toFixed(2)}%`);
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
spinner.fail('Failed to load exposure data');
|
|
280
|
+
handleError(error, program.opts());
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// Vault history command
|
|
285
|
+
vault
|
|
286
|
+
.command('history')
|
|
287
|
+
.description('View vault balance history')
|
|
288
|
+
.option('-p, --period <period>', 'Time period: 24h, 7d, 30d', '7d')
|
|
289
|
+
.option('-i, --interval <interval>', 'Data interval: hourly, daily', 'daily')
|
|
290
|
+
.action(async (options) => {
|
|
291
|
+
const spinner = ora('Loading vault history...').start();
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
const client = await getClient(program.opts());
|
|
295
|
+
|
|
296
|
+
spinner.stop();
|
|
297
|
+
|
|
298
|
+
console.log(chalk.bold('\nš Vault Balance History:'));
|
|
299
|
+
console.log(chalk.gray(`Period: ${options.period}, Interval: ${options.interval}`));
|
|
300
|
+
|
|
301
|
+
// ASCII chart placeholder
|
|
302
|
+
console.log('\n' + chalk.gray('Coming soon: ASCII chart showing vault balance over time'));
|
|
303
|
+
|
|
304
|
+
// Stats table
|
|
305
|
+
console.log(chalk.bold('\nš Period Statistics:'));
|
|
306
|
+
console.log(` Starting Balance: ${chalk.gray('Coming soon')}`);
|
|
307
|
+
console.log(` Ending Balance: ${chalk.gray('Coming soon')}`);
|
|
308
|
+
console.log(` Net Change: ${chalk.gray('Coming soon')}`);
|
|
309
|
+
console.log(` % Change: ${chalk.gray('Coming soon')}`);
|
|
310
|
+
console.log(` Peak Balance: ${chalk.gray('Coming soon')}`);
|
|
311
|
+
console.log(` Lowest Balance: ${chalk.gray('Coming soon')}`);
|
|
312
|
+
} catch (error) {
|
|
313
|
+
spinner.fail('Failed to load history');
|
|
314
|
+
handleError(error, program.opts());
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Vault performance command
|
|
319
|
+
vault
|
|
320
|
+
.command('performance')
|
|
321
|
+
.description('View vault performance metrics')
|
|
322
|
+
.option('-p, --period <period>', 'Time period: 24h, 7d, 30d, ytd, all', '30d')
|
|
323
|
+
.action(async (options) => {
|
|
324
|
+
const spinner = ora('Loading performance metrics...').start();
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
const client = await getClient(program.opts());
|
|
328
|
+
|
|
329
|
+
spinner.stop();
|
|
330
|
+
|
|
331
|
+
console.log(chalk.bold('\nš Vault Performance Metrics:'));
|
|
332
|
+
console.log(chalk.gray(`Period: ${options.period}`));
|
|
333
|
+
|
|
334
|
+
console.log(chalk.bold('\nš° Returns:'));
|
|
335
|
+
console.log(` Total Return: ${chalk.gray('Coming soon')}`);
|
|
336
|
+
console.log(` APY: ${chalk.gray('Coming soon')}`);
|
|
337
|
+
console.log(` Daily Average: ${chalk.gray('Coming soon')}`);
|
|
338
|
+
|
|
339
|
+
console.log(chalk.bold('\nš Revenue Breakdown:'));
|
|
340
|
+
const revenueTable = new Table({
|
|
341
|
+
head: ['Source', 'Amount (TAO)', '% of Total'],
|
|
342
|
+
colWidths: [20, 20, 15],
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// Placeholder data
|
|
346
|
+
revenueTable.push(
|
|
347
|
+
['Trading Fees', chalk.gray('Coming soon'), chalk.gray('--')],
|
|
348
|
+
['Funding Payments', chalk.gray('Coming soon'), chalk.gray('--')],
|
|
349
|
+
['Liquidation Fees', chalk.gray('Coming soon'), chalk.gray('--')],
|
|
350
|
+
['Other', chalk.gray('Coming soon'), chalk.gray('--')],
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
console.log(revenueTable.toString());
|
|
354
|
+
|
|
355
|
+
console.log(chalk.bold('\nā” Risk-Adjusted Metrics:'));
|
|
356
|
+
console.log(` Sharpe Ratio: ${chalk.gray('Coming soon')}`);
|
|
357
|
+
console.log(` Sortino Ratio: ${chalk.gray('Coming soon')}`);
|
|
358
|
+
console.log(` Max Drawdown: ${chalk.gray('Coming soon')}`);
|
|
359
|
+
console.log(` Win Rate: ${chalk.gray('Coming soon')}`);
|
|
360
|
+
} catch (error) {
|
|
361
|
+
spinner.fail('Failed to load performance metrics');
|
|
362
|
+
handleError(error, program.opts());
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// Vault transactions command
|
|
367
|
+
vault
|
|
368
|
+
.command('transactions')
|
|
369
|
+
.alias('txs')
|
|
370
|
+
.description('View recent vault transactions')
|
|
371
|
+
.option('-l, --limit <number>', 'Number of transactions to show', '20')
|
|
372
|
+
.option('-t, --type <type>', 'Filter by type: deposit, withdraw, fee, funding')
|
|
373
|
+
.action(async (options) => {
|
|
374
|
+
const spinner = ora('Loading vault transactions...').start();
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
const client = await getClient(program.opts());
|
|
378
|
+
|
|
379
|
+
// Query vault events
|
|
380
|
+
// TODO: Implement proper event filtering
|
|
381
|
+
|
|
382
|
+
spinner.stop();
|
|
383
|
+
|
|
384
|
+
console.log(chalk.bold('\nš Recent Vault Transactions:'));
|
|
385
|
+
|
|
386
|
+
const table = new Table({
|
|
387
|
+
head: ['Time', 'Type', 'Amount', 'Balance After', 'Details', 'Tx Hash'],
|
|
388
|
+
colWidths: [20, 12, 15, 15, 25, 15],
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Placeholder - would query actual events
|
|
392
|
+
console.log(table.toString());
|
|
393
|
+
console.log(chalk.yellow('\nā ļø Transaction history coming soon'));
|
|
394
|
+
} catch (error) {
|
|
395
|
+
spinner.fail('Failed to load transactions');
|
|
396
|
+
handleError(error, program.opts());
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// Vault health check
|
|
401
|
+
vault
|
|
402
|
+
.command('health')
|
|
403
|
+
.description('Check vault health and risk parameters')
|
|
404
|
+
.action(async () => {
|
|
405
|
+
const spinner = ora('Running vault health check...').start();
|
|
406
|
+
|
|
407
|
+
try {
|
|
408
|
+
const client = await getClient(program.opts());
|
|
409
|
+
|
|
410
|
+
// Perform health checks using alpha
|
|
411
|
+
const alpha = client.getAlpha();
|
|
412
|
+
const vaultStats = await alpha.getVaultStats();
|
|
413
|
+
const totalReserves = vaultStats.totalReserves;
|
|
414
|
+
const insuranceFund = 0n; // Would need getInsuranceFundBalance() method
|
|
415
|
+
|
|
416
|
+
spinner.stop();
|
|
417
|
+
|
|
418
|
+
console.log(chalk.bold('\nš„ Vault Health Check:'));
|
|
419
|
+
|
|
420
|
+
// Get protocol constants for proper health checks (with fallbacks)
|
|
421
|
+
let constants;
|
|
422
|
+
try {
|
|
423
|
+
constants = await alpha.getConstants();
|
|
424
|
+
} catch (error) {
|
|
425
|
+
// Fallback to known protocol values if getConstants() fails
|
|
426
|
+
constants = {
|
|
427
|
+
maxTotalUtilization: 8000n, // 80% max utilization
|
|
428
|
+
liquidationThreshold: 2000n, // 20% liquidation threshold
|
|
429
|
+
basisPoints: 10000n,
|
|
430
|
+
precision: 10n ** 18n,
|
|
431
|
+
maxLeverage: 3000n, // 30x leverage (3000 basis points)
|
|
432
|
+
maintenanceMargin: 2000n, // 20% maintenance margin
|
|
433
|
+
liquidationFee: 500n, // 5% liquidation fee
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Reserve adequacy - Use actual seed amount (3,103 TAO) as baseline
|
|
438
|
+
const minimumReserves = parseEther('1000'); // 1,000 TAO minimum operational threshold
|
|
439
|
+
const reserveCheck = vaultStats.totalReserves >= minimumReserves;
|
|
440
|
+
console.log(
|
|
441
|
+
`\nā Reserve Adequacy: ${reserveCheck ? chalk.green('PASS') : chalk.red('FAIL')}`,
|
|
442
|
+
);
|
|
443
|
+
console.log(` Current: ${formatTAO(vaultStats.totalReserves)} TAO`);
|
|
444
|
+
console.log(` Minimum: ${formatTAO(minimumReserves)} TAO`);
|
|
445
|
+
|
|
446
|
+
// Insurance fund ratio (target 5-10% of reserves)
|
|
447
|
+
const insuranceRatio =
|
|
448
|
+
vaultStats.totalReserves > 0n
|
|
449
|
+
? Number((insuranceFund * 10000n) / vaultStats.totalReserves) / 100
|
|
450
|
+
: 0;
|
|
451
|
+
const insuranceCheck = insuranceRatio >= 5; // 5% minimum for healthy operations
|
|
452
|
+
console.log(
|
|
453
|
+
`\nā Insurance Fund: ${insuranceCheck ? chalk.green('PASS') : chalk.yellow('WARNING')}`,
|
|
454
|
+
);
|
|
455
|
+
console.log(` Current: ${insuranceRatio.toFixed(2)}%`);
|
|
456
|
+
console.log(` Target: 5-10% of reserves`);
|
|
457
|
+
|
|
458
|
+
// Exposure limits - Check against protocol max utilization
|
|
459
|
+
const maxUtilization = Number(constants.maxTotalUtilization) / 100; // Convert from basis points
|
|
460
|
+
const utilizationRate =
|
|
461
|
+
vaultStats.totalReserves > 0n
|
|
462
|
+
? Number((vaultStats.totalExposure * 10000n) / vaultStats.totalReserves) / 100
|
|
463
|
+
: 0;
|
|
464
|
+
const exposureCheck = utilizationRate <= maxUtilization;
|
|
465
|
+
console.log(
|
|
466
|
+
`\nā Exposure Limits: ${exposureCheck ? chalk.green('PASS') : chalk.red('FAIL')}`,
|
|
467
|
+
);
|
|
468
|
+
console.log(` Current Utilization: ${utilizationRate.toFixed(2)}%`);
|
|
469
|
+
console.log(` Max Allowed: ${maxUtilization.toFixed(2)}%`);
|
|
470
|
+
|
|
471
|
+
// Liquidity check - Available reserves vs total exposure
|
|
472
|
+
const liquidityBuffer = vaultStats.availableReserves - vaultStats.totalExposure;
|
|
473
|
+
const liquidityCheck = liquidityBuffer > 0n;
|
|
474
|
+
console.log(
|
|
475
|
+
`\nā Liquidity: ${liquidityCheck ? chalk.green('PASS') : chalk.yellow('WARNING')}`,
|
|
476
|
+
);
|
|
477
|
+
console.log(` Available Buffer: ${formatTAO(liquidityBuffer)} TAO`);
|
|
478
|
+
console.log(
|
|
479
|
+
` Buffer Ratio: ${
|
|
480
|
+
vaultStats.totalReserves > 0n
|
|
481
|
+
? (Number((liquidityBuffer * 10000n) / vaultStats.totalReserves) / 100).toFixed(2)
|
|
482
|
+
: '0.00'
|
|
483
|
+
}%`,
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
// Overall health score calculation
|
|
487
|
+
let healthScore = 0;
|
|
488
|
+
const checks = [reserveCheck, insuranceCheck, exposureCheck, liquidityCheck];
|
|
489
|
+
healthScore = (checks.filter(Boolean).length / checks.length) * 100;
|
|
490
|
+
|
|
491
|
+
console.log(chalk.bold('\nšÆ Overall Health Score:'));
|
|
492
|
+
const scoreColor =
|
|
493
|
+
healthScore >= 75 ? chalk.green : healthScore >= 50 ? chalk.yellow : chalk.red;
|
|
494
|
+
console.log(
|
|
495
|
+
` ${scoreColor(healthScore.toFixed(0) + '%')} (${checks.filter(Boolean).length}/${checks.length} checks passed)`,
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
// Recommendations
|
|
499
|
+
console.log(chalk.bold('\nš” Recommendations:'));
|
|
500
|
+
if (!reserveCheck) {
|
|
501
|
+
console.log(
|
|
502
|
+
chalk.yellow(' ⢠Increase vault reserves above minimum operational threshold'),
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
if (!insuranceCheck) {
|
|
506
|
+
console.log(chalk.yellow(' ⢠Build up insurance fund to 5-10% of total reserves'));
|
|
507
|
+
}
|
|
508
|
+
if (!exposureCheck) {
|
|
509
|
+
console.log(chalk.red(' ⢠CRITICAL: Reduce exposure below maximum utilization limit'));
|
|
510
|
+
}
|
|
511
|
+
if (!liquidityCheck) {
|
|
512
|
+
console.log(chalk.yellow(' ⢠Monitor liquidity buffer and consider reducing exposure'));
|
|
513
|
+
}
|
|
514
|
+
if (healthScore === 100) {
|
|
515
|
+
console.log(chalk.green(' ⢠Vault is operating within all safety parameters'));
|
|
516
|
+
}
|
|
517
|
+
} catch (error) {
|
|
518
|
+
spinner.fail('Health check failed');
|
|
519
|
+
handleError(error, program.opts());
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
}
|
package/cli/index.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Alpha Futures CLI - Main Entry Point
|
|
5
|
+
*
|
|
6
|
+
* A comprehensive command-line interface for interacting with the Alpha Futures protocol
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Load environment variables FIRST before any other imports
|
|
10
|
+
import * as dotenv from 'dotenv';
|
|
11
|
+
import { resolve } from 'path';
|
|
12
|
+
import { existsSync } from 'fs';
|
|
13
|
+
|
|
14
|
+
// Load environment variables with priority:
|
|
15
|
+
// 1. .env.anvil in parent directory (for localhost/Anvil testing)
|
|
16
|
+
// 2. .env in parent directory
|
|
17
|
+
// 3. .env in current directory
|
|
18
|
+
const parentAnvilEnvPath = resolve(process.cwd(), '..', '.env.anvil');
|
|
19
|
+
const parentEnvPath = resolve(process.cwd(), '..', '.env');
|
|
20
|
+
const currentAnvilEnvPath = resolve(process.cwd(), '.env.anvil');
|
|
21
|
+
|
|
22
|
+
if (existsSync(parentAnvilEnvPath)) {
|
|
23
|
+
dotenv.config({ path: parentAnvilEnvPath });
|
|
24
|
+
} else if (existsSync(currentAnvilEnvPath)) {
|
|
25
|
+
dotenv.config({ path: currentAnvilEnvPath });
|
|
26
|
+
} else if (existsSync(parentEnvPath)) {
|
|
27
|
+
dotenv.config({ path: parentEnvPath });
|
|
28
|
+
} else {
|
|
29
|
+
// Fallback to current directory .env
|
|
30
|
+
dotenv.config();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
import { Command } from 'commander';
|
|
34
|
+
import chalk from 'chalk';
|
|
35
|
+
import figlet from 'figlet';
|
|
36
|
+
|
|
37
|
+
// Import command modules
|
|
38
|
+
import { accountCommands } from './commands/account';
|
|
39
|
+
import { positionCommands } from './commands/position';
|
|
40
|
+
import { tradingCommands } from './commands/trading';
|
|
41
|
+
import { marketCommands } from './commands/market';
|
|
42
|
+
import { liquidationCommands } from './commands/liquidation';
|
|
43
|
+
import { vaultCommands } from './commands/vault';
|
|
44
|
+
import { fundingCommands } from './commands/funding';
|
|
45
|
+
import { orderCommands } from './commands/orders';
|
|
46
|
+
import { utilityCommands } from './commands/utils';
|
|
47
|
+
import { startInteractiveMode } from './interactive';
|
|
48
|
+
import { loadConfig, saveConfig } from './utils/config';
|
|
49
|
+
|
|
50
|
+
// Create main program
|
|
51
|
+
const program = new Command();
|
|
52
|
+
|
|
53
|
+
// Display banner unless --no-banner flag is set
|
|
54
|
+
if (!process.argv.includes('--no-banner')) {
|
|
55
|
+
console.log(
|
|
56
|
+
chalk.cyan(
|
|
57
|
+
figlet.textSync('Alpha Futures', {
|
|
58
|
+
font: 'Standard',
|
|
59
|
+
horizontalLayout: 'default',
|
|
60
|
+
verticalLayout: 'default',
|
|
61
|
+
}),
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
console.log(chalk.gray('Perpetual Futures Protocol on Bittensor EVM\n'));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Configure main program
|
|
68
|
+
program
|
|
69
|
+
.name('alpha-futures')
|
|
70
|
+
.description('CLI for Alpha Futures perpetual futures protocol')
|
|
71
|
+
.version('1.0.0')
|
|
72
|
+
.option('-n, --network <network>', 'Network to connect to', 'bittensor')
|
|
73
|
+
.option('-r, --rpc <url>', 'Custom RPC URL')
|
|
74
|
+
.option('-k, --key <privateKey>', 'Private key for transactions')
|
|
75
|
+
.option('-c, --config <path>', 'Path to config file', '~/.alpha-futures/config.json')
|
|
76
|
+
.option('--no-color', 'Disable color output')
|
|
77
|
+
.option('--json', 'Output in JSON format')
|
|
78
|
+
.option('--no-banner', 'Disable ASCII banner')
|
|
79
|
+
.hook('preAction', async (thisCommand) => {
|
|
80
|
+
// Load saved config
|
|
81
|
+
const config = await loadConfig(thisCommand.opts().config);
|
|
82
|
+
|
|
83
|
+
// Merge config with command options
|
|
84
|
+
Object.keys(config).forEach((key) => {
|
|
85
|
+
if (!thisCommand.opts()[key]) {
|
|
86
|
+
thisCommand.opts()[key] = config[key];
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Interactive mode command
|
|
92
|
+
program
|
|
93
|
+
.command('interactive')
|
|
94
|
+
.alias('i')
|
|
95
|
+
.description('Start interactive trading mode')
|
|
96
|
+
.action(async () => {
|
|
97
|
+
const options = program.opts();
|
|
98
|
+
await startInteractiveMode(options);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Config management commands
|
|
102
|
+
program
|
|
103
|
+
.command('config')
|
|
104
|
+
.description('Manage CLI configuration')
|
|
105
|
+
.addCommand(
|
|
106
|
+
new Command('set')
|
|
107
|
+
.description('Set a configuration value')
|
|
108
|
+
.argument('<key>', 'Configuration key')
|
|
109
|
+
.argument('<value>', 'Configuration value')
|
|
110
|
+
.action(async (key, value) => {
|
|
111
|
+
const configPath = program.opts().config;
|
|
112
|
+
const config = await loadConfig(configPath);
|
|
113
|
+
config[key] = value;
|
|
114
|
+
await saveConfig(configPath, config);
|
|
115
|
+
console.log(chalk.green(`ā Configuration updated: ${key} = ${value}`));
|
|
116
|
+
}),
|
|
117
|
+
)
|
|
118
|
+
.addCommand(
|
|
119
|
+
new Command('get')
|
|
120
|
+
.description('Get a configuration value')
|
|
121
|
+
.argument('<key>', 'Configuration key')
|
|
122
|
+
.action(async (key) => {
|
|
123
|
+
const config = await loadConfig(program.opts().config);
|
|
124
|
+
console.log(config[key] || chalk.yellow('Not set'));
|
|
125
|
+
}),
|
|
126
|
+
)
|
|
127
|
+
.addCommand(
|
|
128
|
+
new Command('list').description('List all configuration values').action(async () => {
|
|
129
|
+
const config = await loadConfig(program.opts().config);
|
|
130
|
+
console.log(chalk.bold('\nConfiguration:'));
|
|
131
|
+
Object.entries(config).forEach(([key, value]) => {
|
|
132
|
+
console.log(` ${chalk.cyan(key)}: ${value}`);
|
|
133
|
+
});
|
|
134
|
+
}),
|
|
135
|
+
)
|
|
136
|
+
.addCommand(
|
|
137
|
+
new Command('reset').description('Reset configuration to defaults').action(async () => {
|
|
138
|
+
await saveConfig(program.opts().config, {});
|
|
139
|
+
console.log(chalk.green('ā Configuration reset to defaults'));
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Register command modules
|
|
144
|
+
accountCommands(program);
|
|
145
|
+
positionCommands(program);
|
|
146
|
+
tradingCommands(program);
|
|
147
|
+
marketCommands(program);
|
|
148
|
+
liquidationCommands(program);
|
|
149
|
+
vaultCommands(program);
|
|
150
|
+
fundingCommands(program);
|
|
151
|
+
orderCommands(program);
|
|
152
|
+
utilityCommands(program);
|
|
153
|
+
|
|
154
|
+
// Global error handling
|
|
155
|
+
process.on('unhandledRejection', (reason: any) => {
|
|
156
|
+
console.error(chalk.red('\nā Error:'), reason.message || reason);
|
|
157
|
+
if (program.opts().debug) {
|
|
158
|
+
console.error(reason.stack);
|
|
159
|
+
}
|
|
160
|
+
process.exit(1);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Parse arguments and execute
|
|
164
|
+
program.parse();
|
|
165
|
+
|
|
166
|
+
// Show help if no command provided
|
|
167
|
+
if (!process.argv.slice(2).length) {
|
|
168
|
+
program.outputHelp();
|
|
169
|
+
}
|