@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,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Commands - Manage margin accounts and balances
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { parseEther, formatEther, Address } from 'viem';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import Table from 'cli-table3';
|
|
10
|
+
import { formatTAO, formatUSD } from '../../src/utils';
|
|
11
|
+
import { getClient, handleError } from '../utils/client';
|
|
12
|
+
import { confirmAction } from '../utils/prompts';
|
|
13
|
+
|
|
14
|
+
export function accountCommands(program: Command) {
|
|
15
|
+
const account = program.command('account').alias('acc').description('Manage margin accounts');
|
|
16
|
+
|
|
17
|
+
// Deposit command
|
|
18
|
+
account
|
|
19
|
+
.command('deposit <amount>')
|
|
20
|
+
.description('Deposit TAO to your margin account')
|
|
21
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
22
|
+
.action(async (amount, options) => {
|
|
23
|
+
const spinner = ora('Processing deposit...').start();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const client = await getClient(program.opts());
|
|
27
|
+
const alpha = client.getAlpha();
|
|
28
|
+
const walletClient = client.getWalletClient();
|
|
29
|
+
|
|
30
|
+
if (!walletClient) {
|
|
31
|
+
throw new Error('Wallet client not initialized. Please provide a private key.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const depositAmount = parseEther(amount);
|
|
35
|
+
|
|
36
|
+
spinner.stop();
|
|
37
|
+
|
|
38
|
+
// Show deposit details
|
|
39
|
+
console.log(chalk.bold('\nš° Deposit Details:'));
|
|
40
|
+
console.log(` Amount: ${chalk.green(amount + ' TAO')}`);
|
|
41
|
+
console.log(` To: Margin Account`);
|
|
42
|
+
|
|
43
|
+
// Confirm action
|
|
44
|
+
if (!options.yes) {
|
|
45
|
+
const confirmed = await confirmAction('Proceed with deposit?');
|
|
46
|
+
if (!confirmed) {
|
|
47
|
+
console.log(chalk.yellow('Deposit cancelled'));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check and approve TAO token spending if needed
|
|
53
|
+
spinner.start('Checking TAO allowance...');
|
|
54
|
+
const publicClient = client.getPublicClient();
|
|
55
|
+
const alphaAddress = alpha.getContractAddress();
|
|
56
|
+
const userAddress = walletClient.account!.address;
|
|
57
|
+
|
|
58
|
+
// Get TAO token contract
|
|
59
|
+
const taoTokenAddress = client.getCollateralTokenAddress();
|
|
60
|
+
if (!taoTokenAddress) {
|
|
61
|
+
throw new Error('TAO token address not configured');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Check current allowance
|
|
65
|
+
const currentAllowance = (await publicClient.readContract({
|
|
66
|
+
address: taoTokenAddress,
|
|
67
|
+
abi: [
|
|
68
|
+
{
|
|
69
|
+
name: 'allowance',
|
|
70
|
+
type: 'function',
|
|
71
|
+
stateMutability: 'view',
|
|
72
|
+
inputs: [
|
|
73
|
+
{ name: 'owner', type: 'address' },
|
|
74
|
+
{ name: 'spender', type: 'address' },
|
|
75
|
+
],
|
|
76
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
functionName: 'allowance',
|
|
80
|
+
args: [userAddress, alphaAddress],
|
|
81
|
+
})) as bigint;
|
|
82
|
+
|
|
83
|
+
if (currentAllowance < depositAmount) {
|
|
84
|
+
spinner.text = 'Approving TAO spending...';
|
|
85
|
+
const approveHash = await walletClient.writeContract({
|
|
86
|
+
address: taoTokenAddress,
|
|
87
|
+
abi: [
|
|
88
|
+
{
|
|
89
|
+
name: 'approve',
|
|
90
|
+
type: 'function',
|
|
91
|
+
stateMutability: 'nonpayable',
|
|
92
|
+
inputs: [
|
|
93
|
+
{ name: 'spender', type: 'address' },
|
|
94
|
+
{ name: 'amount', type: 'uint256' },
|
|
95
|
+
],
|
|
96
|
+
outputs: [{ name: '', type: 'bool' }],
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
functionName: 'approve',
|
|
100
|
+
args: [alphaAddress, depositAmount],
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
await publicClient.waitForTransactionReceipt({ hash: approveHash });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
spinner.text = 'Depositing TAO...';
|
|
107
|
+
const hash = await alpha.deposit(depositAmount);
|
|
108
|
+
|
|
109
|
+
spinner.text = 'Waiting for confirmation...';
|
|
110
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
111
|
+
|
|
112
|
+
spinner.succeed('Deposit successful!');
|
|
113
|
+
console.log(chalk.gray(` Transaction: ${receipt.transactionHash}`));
|
|
114
|
+
console.log(chalk.gray(` Gas used: ${receipt.gasUsed.toString()}`));
|
|
115
|
+
|
|
116
|
+
// Show updated balance
|
|
117
|
+
const balance = await alpha.getMarginBalance(walletClient.account!.address);
|
|
118
|
+
console.log(chalk.cyan(`\n New balance: ${formatTAO(balance)} TAO`));
|
|
119
|
+
} catch (error) {
|
|
120
|
+
spinner.fail('Deposit failed');
|
|
121
|
+
handleError(error, program.opts());
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Withdraw command
|
|
126
|
+
account
|
|
127
|
+
.command('withdraw <amount>')
|
|
128
|
+
.description('Withdraw TAO from your margin account')
|
|
129
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
130
|
+
.option('-a, --all', 'Withdraw all available balance')
|
|
131
|
+
.action(async (amount, options) => {
|
|
132
|
+
const spinner = ora('Processing withdrawal...').start();
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const client = await getClient(program.opts());
|
|
136
|
+
const alpha = client.getAlpha();
|
|
137
|
+
const walletClient = client.getWalletClient();
|
|
138
|
+
|
|
139
|
+
if (!walletClient) {
|
|
140
|
+
throw new Error('Wallet client not initialized. Please provide a private key.');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const userAddress = walletClient.account!.address;
|
|
144
|
+
|
|
145
|
+
let withdrawAmount: bigint;
|
|
146
|
+
if (options.all) {
|
|
147
|
+
withdrawAmount = await alpha.getAvailableMargin(userAddress);
|
|
148
|
+
amount = formatEther(withdrawAmount);
|
|
149
|
+
} else {
|
|
150
|
+
withdrawAmount = parseEther(amount);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
spinner.stop();
|
|
154
|
+
|
|
155
|
+
// Check available balance
|
|
156
|
+
const available = await alpha.getAvailableMargin(userAddress);
|
|
157
|
+
if (withdrawAmount > available) {
|
|
158
|
+
spinner.fail('Insufficient available balance');
|
|
159
|
+
console.log(` Available: ${formatTAO(available)} TAO`);
|
|
160
|
+
console.log(` Requested: ${formatTAO(withdrawAmount)} TAO`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Show withdrawal details
|
|
165
|
+
console.log(chalk.bold('\nšø Withdrawal Details:'));
|
|
166
|
+
console.log(` Amount: ${chalk.red(amount + ' TAO')}`);
|
|
167
|
+
console.log(` From: Margin Account`);
|
|
168
|
+
console.log(` Available: ${formatTAO(available)} TAO`);
|
|
169
|
+
|
|
170
|
+
// Confirm action
|
|
171
|
+
if (!options.yes) {
|
|
172
|
+
const confirmed = await confirmAction('Proceed with withdrawal?');
|
|
173
|
+
if (!confirmed) {
|
|
174
|
+
console.log(chalk.yellow('Withdrawal cancelled'));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
spinner.start('Withdrawing TAO...');
|
|
180
|
+
const hash = await alpha.withdraw(withdrawAmount);
|
|
181
|
+
|
|
182
|
+
spinner.text = 'Waiting for confirmation...';
|
|
183
|
+
const publicClient = client.getPublicClient();
|
|
184
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
185
|
+
|
|
186
|
+
spinner.succeed('Withdrawal successful!');
|
|
187
|
+
console.log(chalk.gray(` Transaction: ${receipt.transactionHash}`));
|
|
188
|
+
console.log(chalk.gray(` Gas used: ${receipt.gasUsed.toString()}`));
|
|
189
|
+
|
|
190
|
+
// Show updated balance
|
|
191
|
+
const balance = await alpha.getMarginBalance(userAddress);
|
|
192
|
+
console.log(chalk.cyan(`\n Remaining balance: ${formatTAO(balance)} TAO`));
|
|
193
|
+
} catch (error) {
|
|
194
|
+
spinner.fail('Withdrawal failed');
|
|
195
|
+
handleError(error, program.opts());
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Enhanced balance command
|
|
200
|
+
account
|
|
201
|
+
.command('balance [address]')
|
|
202
|
+
.alias('bal')
|
|
203
|
+
.description('Check balances (TAO wallet where P&L settles + margin account for trading)')
|
|
204
|
+
.option('-d, --detailed', 'Show detailed breakdown')
|
|
205
|
+
.option('-w, --wallet-only', 'Show only TAO wallet balance')
|
|
206
|
+
.option('-m, --margin-only', 'Show only margin account balance')
|
|
207
|
+
.action(async (address, options) => {
|
|
208
|
+
const spinner = ora('Fetching balance...').start();
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
const client = await getClient(program.opts());
|
|
212
|
+
const alpha = client.getAlpha();
|
|
213
|
+
const walletClient = client.getWalletClient();
|
|
214
|
+
|
|
215
|
+
// Use provided address or wallet address
|
|
216
|
+
const userAddress = address || walletClient?.account?.address;
|
|
217
|
+
|
|
218
|
+
if (!userAddress) {
|
|
219
|
+
spinner.fail('No address provided and no wallet client available');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Fetch balance data using alpha - use direct methods for better compatibility
|
|
224
|
+
const balance = await alpha.getMarginBalance(userAddress as Address);
|
|
225
|
+
const available = await alpha.getAvailableMargin(userAddress as Address);
|
|
226
|
+
const locked = await alpha.getLockedMargin(userAddress as Address);
|
|
227
|
+
|
|
228
|
+
// For margin ratio, we'll need to calculate it based on positions
|
|
229
|
+
const userPositions = await alpha.getUserPositions(userAddress as Address);
|
|
230
|
+
let marginRatio = 0n;
|
|
231
|
+
if (userPositions.length > 0) {
|
|
232
|
+
// Get first position's margin ratio as proxy (in real app, would aggregate)
|
|
233
|
+
try {
|
|
234
|
+
marginRatio = await alpha.getMarginRatio(userPositions[0]);
|
|
235
|
+
} catch {
|
|
236
|
+
marginRatio = 0n;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
spinner.stop();
|
|
241
|
+
|
|
242
|
+
// Get TAO wallet balance if requested
|
|
243
|
+
let taoWalletBalance = 0n;
|
|
244
|
+
if (!options.marginOnly) {
|
|
245
|
+
try {
|
|
246
|
+
const publicClient = client.getPublicClient();
|
|
247
|
+
const taoTokenAddress = client.getCollateralTokenAddress();
|
|
248
|
+
if (taoTokenAddress) {
|
|
249
|
+
taoWalletBalance = (await publicClient.readContract({
|
|
250
|
+
address: taoTokenAddress,
|
|
251
|
+
abi: [
|
|
252
|
+
{
|
|
253
|
+
name: 'balanceOf',
|
|
254
|
+
type: 'function',
|
|
255
|
+
stateMutability: 'view',
|
|
256
|
+
inputs: [{ name: 'account', type: 'address' }],
|
|
257
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
functionName: 'balanceOf',
|
|
261
|
+
args: [userAddress as Address],
|
|
262
|
+
})) as bigint;
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
// TAO token not available or error reading balance
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
spinner.stop();
|
|
270
|
+
|
|
271
|
+
// Display balance summary
|
|
272
|
+
if (options.walletOnly) {
|
|
273
|
+
console.log(chalk.bold(`\nš³ TAO Wallet (P&L Settlement): ${chalk.cyan(userAddress)}`));
|
|
274
|
+
console.log(` TAO Balance: ${chalk.green(formatTAO(taoWalletBalance) + ' TAO')}`);
|
|
275
|
+
console.log(chalk.gray(' š” All position profits and losses are settled here'));
|
|
276
|
+
} else if (options.marginOnly) {
|
|
277
|
+
console.log(chalk.bold(`\nš° Margin Account: ${chalk.cyan(userAddress)}`));
|
|
278
|
+
console.log(` Balance: ${chalk.green(formatTAO(balance) + ' TAO')}`);
|
|
279
|
+
console.log(` Available: ${chalk.cyan(formatTAO(available) + ' TAO')}`);
|
|
280
|
+
console.log(` Locked: ${chalk.yellow(formatTAO(locked) + ' TAO')}`);
|
|
281
|
+
console.log(
|
|
282
|
+
chalk.gray(
|
|
283
|
+
' š” Tip: Use "alpha-futures account balance" to see TAO wallet where P&L settles',
|
|
284
|
+
),
|
|
285
|
+
);
|
|
286
|
+
} else {
|
|
287
|
+
console.log(chalk.bold(`\nš° Account Overview: ${chalk.cyan(userAddress)}`));
|
|
288
|
+
console.log(chalk.bold('\nš³ TAO Wallet (P&L Settlement):'));
|
|
289
|
+
console.log(` Balance: ${chalk.green(formatTAO(taoWalletBalance) + ' TAO')}`);
|
|
290
|
+
console.log(chalk.gray(' š” All position P&L is credited/debited here'));
|
|
291
|
+
console.log(chalk.bold('\nš¦ Margin Account (Trading Collateral):'));
|
|
292
|
+
console.log(` Total: ${chalk.green(formatTAO(balance) + ' TAO')}`);
|
|
293
|
+
console.log(` Available: ${chalk.cyan(formatTAO(available) + ' TAO')}`);
|
|
294
|
+
console.log(` Locked: ${chalk.yellow(formatTAO(locked) + ' TAO')}`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (options.detailed && !options.walletOnly) {
|
|
298
|
+
// Detailed table view
|
|
299
|
+
const table = new Table({
|
|
300
|
+
head: ['Type', 'Amount (TAO)', 'USD Value'],
|
|
301
|
+
colWidths: [20, 20, 20],
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// For now, we'll use a placeholder TAO price
|
|
305
|
+
// In production, this would come from an oracle
|
|
306
|
+
const taoPrice = parseEther('100'); // $100 placeholder
|
|
307
|
+
|
|
308
|
+
table.push(
|
|
309
|
+
[
|
|
310
|
+
'Total Balance',
|
|
311
|
+
formatTAO(balance),
|
|
312
|
+
formatUSD((balance * taoPrice) / parseEther('1')),
|
|
313
|
+
],
|
|
314
|
+
[
|
|
315
|
+
'Available',
|
|
316
|
+
chalk.green(formatTAO(available)),
|
|
317
|
+
chalk.green(formatUSD((available * taoPrice) / parseEther('1'))),
|
|
318
|
+
],
|
|
319
|
+
[
|
|
320
|
+
'Locked',
|
|
321
|
+
chalk.yellow(formatTAO(locked)),
|
|
322
|
+
chalk.yellow(formatUSD((locked * taoPrice) / parseEther('1'))),
|
|
323
|
+
],
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
console.log(table.toString());
|
|
327
|
+
|
|
328
|
+
// Margin ratio display
|
|
329
|
+
if (marginRatio > 0n) {
|
|
330
|
+
const marginRatioPercent = Number(marginRatio) / 100;
|
|
331
|
+
let marginColor = chalk.green;
|
|
332
|
+
if (marginRatioPercent < 50) marginColor = chalk.yellow;
|
|
333
|
+
if (marginRatioPercent < 30) marginColor = chalk.red;
|
|
334
|
+
|
|
335
|
+
console.log(`\nš Margin Ratio: ${marginColor(marginRatioPercent.toFixed(2) + '%')}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
} catch (error) {
|
|
339
|
+
spinner.fail('Failed to fetch balance');
|
|
340
|
+
handleError(error, program.opts());
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Token transfer command
|
|
345
|
+
account
|
|
346
|
+
.command('transfer <recipient> <amount>')
|
|
347
|
+
.description('Transfer TAO tokens to another address')
|
|
348
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
349
|
+
.action(async (recipient, amount, options) => {
|
|
350
|
+
const spinner = ora('Processing TAO transfer...').start();
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
const client = await getClient(program.opts());
|
|
354
|
+
const walletClient = client.getWalletClient();
|
|
355
|
+
|
|
356
|
+
if (!walletClient) {
|
|
357
|
+
throw new Error('Wallet client not initialized. Please provide a private key.');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const transferAmount = parseEther(amount);
|
|
361
|
+
const publicClient = client.getPublicClient();
|
|
362
|
+
const userAddress = walletClient.account!.address;
|
|
363
|
+
|
|
364
|
+
// Get TAO token contract address
|
|
365
|
+
const taoTokenAddress = client.getCollateralTokenAddress();
|
|
366
|
+
if (!taoTokenAddress) {
|
|
367
|
+
throw new Error('TAO token address not configured. Set TAO_TOKEN environment variable.');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Check sender's TAO balance
|
|
371
|
+
const senderBalance = (await publicClient.readContract({
|
|
372
|
+
address: taoTokenAddress,
|
|
373
|
+
abi: [
|
|
374
|
+
{
|
|
375
|
+
name: 'balanceOf',
|
|
376
|
+
type: 'function',
|
|
377
|
+
stateMutability: 'view',
|
|
378
|
+
inputs: [{ name: 'account', type: 'address' }],
|
|
379
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
380
|
+
},
|
|
381
|
+
],
|
|
382
|
+
functionName: 'balanceOf',
|
|
383
|
+
args: [userAddress],
|
|
384
|
+
})) as bigint;
|
|
385
|
+
|
|
386
|
+
if (senderBalance < transferAmount) {
|
|
387
|
+
spinner.fail('Insufficient TAO balance');
|
|
388
|
+
console.log(` Balance: ${formatTAO(senderBalance)} TAO`);
|
|
389
|
+
console.log(` Required: ${formatTAO(transferAmount)} TAO`);
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
spinner.stop();
|
|
394
|
+
|
|
395
|
+
// Show transfer details
|
|
396
|
+
console.log(chalk.bold('\nšø TAO Transfer Details:'));
|
|
397
|
+
console.log(` From: ${chalk.cyan(userAddress)}`);
|
|
398
|
+
console.log(` To: ${chalk.cyan(recipient)}`);
|
|
399
|
+
console.log(` Amount: ${chalk.green(amount + ' TAO')}`);
|
|
400
|
+
console.log(` Available: ${formatTAO(senderBalance)} TAO`);
|
|
401
|
+
|
|
402
|
+
// Confirm action
|
|
403
|
+
if (!options.yes) {
|
|
404
|
+
const confirmed = await confirmAction('Proceed with transfer?');
|
|
405
|
+
if (!confirmed) {
|
|
406
|
+
console.log(chalk.yellow('Transfer cancelled'));
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
spinner.start('Transferring TAO...');
|
|
412
|
+
const hash = await walletClient.writeContract({
|
|
413
|
+
address: taoTokenAddress,
|
|
414
|
+
abi: [
|
|
415
|
+
{
|
|
416
|
+
name: 'transfer',
|
|
417
|
+
type: 'function',
|
|
418
|
+
stateMutability: 'nonpayable',
|
|
419
|
+
inputs: [
|
|
420
|
+
{ name: 'to', type: 'address' },
|
|
421
|
+
{ name: 'amount', type: 'uint256' },
|
|
422
|
+
],
|
|
423
|
+
outputs: [{ name: '', type: 'bool' }],
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
functionName: 'transfer',
|
|
427
|
+
args: [recipient as Address, transferAmount],
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
spinner.text = 'Waiting for confirmation...';
|
|
431
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
432
|
+
|
|
433
|
+
spinner.succeed('TAO transfer successful!');
|
|
434
|
+
console.log(chalk.gray(` Transaction: ${receipt.transactionHash}`));
|
|
435
|
+
console.log(chalk.gray(` Gas used: ${receipt.gasUsed.toString()}`));
|
|
436
|
+
|
|
437
|
+
// Show updated balances
|
|
438
|
+
const newSenderBalance = (await publicClient.readContract({
|
|
439
|
+
address: taoTokenAddress,
|
|
440
|
+
abi: [
|
|
441
|
+
{
|
|
442
|
+
name: 'balanceOf',
|
|
443
|
+
type: 'function',
|
|
444
|
+
stateMutability: 'view',
|
|
445
|
+
inputs: [{ name: 'account', type: 'address' }],
|
|
446
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
447
|
+
},
|
|
448
|
+
],
|
|
449
|
+
functionName: 'balanceOf',
|
|
450
|
+
args: [userAddress],
|
|
451
|
+
})) as bigint;
|
|
452
|
+
|
|
453
|
+
console.log(chalk.cyan(`\n Your new balance: ${formatTAO(newSenderBalance)} TAO`));
|
|
454
|
+
} catch (error) {
|
|
455
|
+
spinner.fail('TAO transfer failed');
|
|
456
|
+
handleError(error, program.opts());
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
// Account info command
|
|
461
|
+
account
|
|
462
|
+
.command('info [address]')
|
|
463
|
+
.description('Get detailed account information (use "balance" for quick balance check)')
|
|
464
|
+
.action(async (address) => {
|
|
465
|
+
const spinner = ora('Fetching account info...').start();
|
|
466
|
+
|
|
467
|
+
try {
|
|
468
|
+
const client = await getClient(program.opts());
|
|
469
|
+
const alpha = client.getAlpha();
|
|
470
|
+
const walletClient = client.getWalletClient();
|
|
471
|
+
|
|
472
|
+
const userAddress = address || walletClient?.account?.address;
|
|
473
|
+
|
|
474
|
+
if (!userAddress) {
|
|
475
|
+
spinner.fail('No address provided and no wallet client available');
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Fetch comprehensive account data via single RPC call
|
|
480
|
+
const [summary, positionIds] = await Promise.all([
|
|
481
|
+
alpha.getAccountSummary(userAddress as Address),
|
|
482
|
+
alpha.getUserPositions(userAddress as Address),
|
|
483
|
+
]);
|
|
484
|
+
const balance = summary.accountEquity;
|
|
485
|
+
const available = summary.availableMargin;
|
|
486
|
+
const locked = summary.lockedMargin;
|
|
487
|
+
|
|
488
|
+
// Calculate margin ratio from positions
|
|
489
|
+
let marginRatio = 0n;
|
|
490
|
+
if (positionIds.length > 0) {
|
|
491
|
+
try {
|
|
492
|
+
marginRatio = await alpha.getMarginRatio(positionIds[0]);
|
|
493
|
+
} catch {
|
|
494
|
+
marginRatio = 0n;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
spinner.stop();
|
|
499
|
+
|
|
500
|
+
// Display account summary
|
|
501
|
+
console.log(chalk.bold(`\nš Account Information`));
|
|
502
|
+
console.log(chalk.gray(`Address: ${userAddress}`));
|
|
503
|
+
|
|
504
|
+
// Balance info
|
|
505
|
+
console.log(chalk.bold('\nš° Balances:'));
|
|
506
|
+
console.log(` Total: ${formatTAO(balance)} TAO`);
|
|
507
|
+
console.log(` Available: ${chalk.green(formatTAO(available) + ' TAO')}`);
|
|
508
|
+
console.log(` Locked: ${chalk.yellow(formatTAO(locked) + ' TAO')}`);
|
|
509
|
+
|
|
510
|
+
// Margin info
|
|
511
|
+
if (marginRatio > 0n) {
|
|
512
|
+
const marginRatioPercent = Number(marginRatio) / 100;
|
|
513
|
+
let marginColor = chalk.green;
|
|
514
|
+
if (marginRatioPercent < 50) marginColor = chalk.yellow;
|
|
515
|
+
if (marginRatioPercent < 30) marginColor = chalk.red;
|
|
516
|
+
|
|
517
|
+
console.log(chalk.bold('\nš Margin Status:'));
|
|
518
|
+
console.log(` Ratio: ${marginColor(marginRatioPercent.toFixed(2) + '%')}`);
|
|
519
|
+
console.log(
|
|
520
|
+
` Health: ${marginRatioPercent >= 50 ? 'ā
Healthy' : marginRatioPercent >= 30 ? 'ā ļø Warning' : 'šØ Critical'}`,
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Position summary
|
|
525
|
+
console.log(chalk.bold('\nš Positions:'));
|
|
526
|
+
console.log(` Active: ${positionIds.length}`);
|
|
527
|
+
if (positionIds.length > 0) {
|
|
528
|
+
// Fetch full position details for summary
|
|
529
|
+
const positions = await Promise.all(positionIds.map((id) => alpha.getPosition(id)));
|
|
530
|
+
|
|
531
|
+
let totalNotionalValue = 0n;
|
|
532
|
+
let totalMargin = 0n;
|
|
533
|
+
for (const pos of positions) {
|
|
534
|
+
totalNotionalValue += pos.notionalValue;
|
|
535
|
+
totalMargin += pos.margin;
|
|
536
|
+
}
|
|
537
|
+
console.log(` Total Notional: ${formatTAO(totalNotionalValue)} TAO`);
|
|
538
|
+
console.log(` Total Margin: ${formatTAO(totalMargin)} TAO`);
|
|
539
|
+
}
|
|
540
|
+
} catch (error) {
|
|
541
|
+
spinner.fail('Failed to fetch account info');
|
|
542
|
+
handleError(error, program.opts());
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
}
|