bittensor-cli 9.7.1__py3-none-any.whl → 9.8.1__py3-none-any.whl
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.
- bittensor_cli/cli.py +340 -24
- bittensor_cli/src/__init__.py +8 -0
- bittensor_cli/src/bittensor/chain_data.py +81 -33
- bittensor_cli/src/bittensor/subtensor_interface.py +111 -26
- bittensor_cli/src/bittensor/utils.py +9 -0
- bittensor_cli/src/commands/liquidity/__init__.py +0 -0
- bittensor_cli/src/commands/liquidity/liquidity.py +628 -0
- bittensor_cli/src/commands/liquidity/utils.py +200 -0
- bittensor_cli/src/commands/stake/add.py +34 -22
- bittensor_cli/src/commands/stake/list.py +35 -48
- bittensor_cli/src/commands/stake/move.py +18 -44
- bittensor_cli/src/commands/stake/remove.py +33 -95
- bittensor_cli/src/commands/subnets/subnets.py +6 -0
- bittensor_cli/src/commands/sudo.py +21 -8
- bittensor_cli/src/commands/wallets.py +20 -48
- {bittensor_cli-9.7.1.dist-info → bittensor_cli-9.8.1.dist-info}/METADATA +1 -1
- {bittensor_cli-9.7.1.dist-info → bittensor_cli-9.8.1.dist-info}/RECORD +20 -17
- {bittensor_cli-9.7.1.dist-info → bittensor_cli-9.8.1.dist-info}/WHEEL +0 -0
- {bittensor_cli-9.7.1.dist-info → bittensor_cli-9.8.1.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-9.7.1.dist-info → bittensor_cli-9.8.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,200 @@
|
|
1
|
+
"""
|
2
|
+
This module provides utilities for managing liquidity positions and price conversions in the Bittensor network. The
|
3
|
+
module handles conversions between TAO and Alpha tokens while maintaining precise calculations for liquidity
|
4
|
+
provisioning and fee distribution.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import math
|
8
|
+
from dataclasses import dataclass
|
9
|
+
from typing import Any
|
10
|
+
|
11
|
+
from rich.prompt import IntPrompt, FloatPrompt
|
12
|
+
|
13
|
+
from bittensor_cli.src.bittensor.balances import Balance, fixed_to_float
|
14
|
+
from bittensor_cli.src.bittensor.utils import (
|
15
|
+
console,
|
16
|
+
)
|
17
|
+
|
18
|
+
# These three constants are unchangeable at the level of Uniswap math
|
19
|
+
MIN_TICK = -887272
|
20
|
+
MAX_TICK = 887272
|
21
|
+
PRICE_STEP = 1.0001
|
22
|
+
|
23
|
+
|
24
|
+
@dataclass
|
25
|
+
class LiquidityPosition:
|
26
|
+
id: int
|
27
|
+
price_low: Balance # RAO
|
28
|
+
price_high: Balance # RAO
|
29
|
+
liquidity: Balance # TAO + ALPHA (sqrt by TAO balance * Alpha Balance -> math under the hood)
|
30
|
+
fees_tao: Balance # RAO
|
31
|
+
fees_alpha: Balance # RAO
|
32
|
+
netuid: int
|
33
|
+
|
34
|
+
def to_token_amounts(
|
35
|
+
self, current_subnet_price: Balance
|
36
|
+
) -> tuple[Balance, Balance]:
|
37
|
+
"""Convert a position to token amounts.
|
38
|
+
|
39
|
+
Arguments:
|
40
|
+
current_subnet_price: current subnet price in Alpha.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
tuple[int, int]:
|
44
|
+
Amount of Alpha in liquidity
|
45
|
+
Amount of TAO in liquidity
|
46
|
+
|
47
|
+
Liquidity is a combination of TAO and Alpha depending on the price of the subnet at the moment.
|
48
|
+
"""
|
49
|
+
sqrt_price_low = math.sqrt(self.price_low)
|
50
|
+
sqrt_price_high = math.sqrt(self.price_high)
|
51
|
+
sqrt_current_subnet_price = math.sqrt(current_subnet_price)
|
52
|
+
|
53
|
+
if sqrt_current_subnet_price < sqrt_price_low:
|
54
|
+
amount_alpha = self.liquidity * (1 / sqrt_price_low - 1 / sqrt_price_high)
|
55
|
+
amount_tao = 0
|
56
|
+
elif sqrt_current_subnet_price > sqrt_price_high:
|
57
|
+
amount_alpha = 0
|
58
|
+
amount_tao = self.liquidity * (sqrt_price_high - sqrt_price_low)
|
59
|
+
else:
|
60
|
+
amount_alpha = self.liquidity * (
|
61
|
+
1 / sqrt_current_subnet_price - 1 / sqrt_price_high
|
62
|
+
)
|
63
|
+
amount_tao = self.liquidity * (sqrt_current_subnet_price - sqrt_price_low)
|
64
|
+
return Balance.from_rao(int(amount_alpha)).set_unit(
|
65
|
+
self.netuid
|
66
|
+
), Balance.from_rao(int(amount_tao))
|
67
|
+
|
68
|
+
|
69
|
+
def price_to_tick(price: float) -> int:
|
70
|
+
"""Converts a float price to the nearest Uniswap V3 tick index."""
|
71
|
+
if price <= 0:
|
72
|
+
raise ValueError(f"Price must be positive, got `{price}`.")
|
73
|
+
|
74
|
+
tick = int(math.log(price) / math.log(PRICE_STEP))
|
75
|
+
|
76
|
+
if not (MIN_TICK <= tick <= MAX_TICK):
|
77
|
+
raise ValueError(
|
78
|
+
f"Resulting tick {tick} is out of allowed range ({MIN_TICK} to {MAX_TICK})"
|
79
|
+
)
|
80
|
+
return tick
|
81
|
+
|
82
|
+
|
83
|
+
def tick_to_price(tick: int) -> float:
|
84
|
+
"""Convert an integer Uniswap V3 tick index to float price."""
|
85
|
+
if not (MIN_TICK <= tick <= MAX_TICK):
|
86
|
+
raise ValueError("Tick is out of allowed range")
|
87
|
+
return PRICE_STEP**tick
|
88
|
+
|
89
|
+
|
90
|
+
def get_fees(
|
91
|
+
current_tick: int,
|
92
|
+
tick: dict,
|
93
|
+
tick_index: int,
|
94
|
+
quote: bool,
|
95
|
+
global_fees_tao: float,
|
96
|
+
global_fees_alpha: float,
|
97
|
+
above: bool,
|
98
|
+
) -> float:
|
99
|
+
"""Returns the liquidity fee."""
|
100
|
+
tick_fee_key = "fees_out_tao" if quote else "fees_out_alpha"
|
101
|
+
tick_fee_value = fixed_to_float(tick.get(tick_fee_key))
|
102
|
+
global_fee_value = global_fees_tao if quote else global_fees_alpha
|
103
|
+
|
104
|
+
if above:
|
105
|
+
return (
|
106
|
+
global_fee_value - tick_fee_value
|
107
|
+
if tick_index <= current_tick
|
108
|
+
else tick_fee_value
|
109
|
+
)
|
110
|
+
return (
|
111
|
+
tick_fee_value
|
112
|
+
if tick_index <= current_tick
|
113
|
+
else global_fee_value - tick_fee_value
|
114
|
+
)
|
115
|
+
|
116
|
+
|
117
|
+
def get_fees_in_range(
|
118
|
+
quote: bool,
|
119
|
+
global_fees_tao: float,
|
120
|
+
global_fees_alpha: float,
|
121
|
+
fees_below_low: float,
|
122
|
+
fees_above_high: float,
|
123
|
+
) -> float:
|
124
|
+
"""Returns the liquidity fee value in a range."""
|
125
|
+
global_fees = global_fees_tao if quote else global_fees_alpha
|
126
|
+
return global_fees - fees_below_low - fees_above_high
|
127
|
+
|
128
|
+
|
129
|
+
# Calculate fees for a position
|
130
|
+
def calculate_fees(
|
131
|
+
position: dict[str, Any],
|
132
|
+
global_fees_tao: float,
|
133
|
+
global_fees_alpha: float,
|
134
|
+
tao_fees_below_low: float,
|
135
|
+
tao_fees_above_high: float,
|
136
|
+
alpha_fees_below_low: float,
|
137
|
+
alpha_fees_above_high: float,
|
138
|
+
netuid: int,
|
139
|
+
) -> tuple[Balance, Balance]:
|
140
|
+
fee_tao_agg = get_fees_in_range(
|
141
|
+
quote=True,
|
142
|
+
global_fees_tao=global_fees_tao,
|
143
|
+
global_fees_alpha=global_fees_alpha,
|
144
|
+
fees_below_low=tao_fees_below_low,
|
145
|
+
fees_above_high=tao_fees_above_high,
|
146
|
+
)
|
147
|
+
|
148
|
+
fee_alpha_agg = get_fees_in_range(
|
149
|
+
quote=False,
|
150
|
+
global_fees_tao=global_fees_tao,
|
151
|
+
global_fees_alpha=global_fees_alpha,
|
152
|
+
fees_below_low=alpha_fees_below_low,
|
153
|
+
fees_above_high=alpha_fees_above_high,
|
154
|
+
)
|
155
|
+
|
156
|
+
fee_tao = fee_tao_agg - fixed_to_float(position["fees_tao"])
|
157
|
+
fee_alpha = fee_alpha_agg - fixed_to_float(position["fees_alpha"])
|
158
|
+
liquidity_frac = position["liquidity"]
|
159
|
+
|
160
|
+
fee_tao = liquidity_frac * fee_tao
|
161
|
+
fee_alpha = liquidity_frac * fee_alpha
|
162
|
+
|
163
|
+
return Balance.from_rao(int(fee_tao)), Balance.from_rao(int(fee_alpha)).set_unit(
|
164
|
+
netuid
|
165
|
+
)
|
166
|
+
|
167
|
+
|
168
|
+
def prompt_liquidity(prompt: str, negative_allowed: bool = False) -> Balance:
|
169
|
+
"""Prompt the user for the amount of liquidity.
|
170
|
+
|
171
|
+
Arguments:
|
172
|
+
prompt: Prompt to display to the user.
|
173
|
+
negative_allowed: Whether negative amounts are allowed.
|
174
|
+
|
175
|
+
Returns:
|
176
|
+
Balance converted from input to TAO.
|
177
|
+
"""
|
178
|
+
while True:
|
179
|
+
amount = FloatPrompt.ask(prompt)
|
180
|
+
try:
|
181
|
+
if amount <= 0 and not negative_allowed:
|
182
|
+
console.print("[red]Amount must be greater than 0[/red].")
|
183
|
+
continue
|
184
|
+
return Balance.from_tao(amount)
|
185
|
+
except ValueError:
|
186
|
+
console.print("[red]Please enter a valid number[/red].")
|
187
|
+
|
188
|
+
|
189
|
+
def prompt_position_id() -> int:
|
190
|
+
"""Ask the user for the ID of the liquidity position to remove."""
|
191
|
+
while True:
|
192
|
+
position_id = IntPrompt.ask("Enter the [blue]liquidity position ID[/blue]")
|
193
|
+
|
194
|
+
try:
|
195
|
+
if position_id <= 1:
|
196
|
+
console.print("[red]Position ID must be greater than 1[/red].")
|
197
|
+
continue
|
198
|
+
return position_id
|
199
|
+
except ValueError:
|
200
|
+
console.print("[red]Please enter a valid number[/red].")
|
@@ -245,12 +245,12 @@ async def stake_add(
|
|
245
245
|
# Get subnet data and stake information for coldkey
|
246
246
|
chain_head = await subtensor.substrate.get_chain_head()
|
247
247
|
_all_subnets, _stake_info, current_wallet_balance = await asyncio.gather(
|
248
|
-
subtensor.all_subnets(),
|
248
|
+
subtensor.all_subnets(block_hash=chain_head),
|
249
249
|
subtensor.get_stake_for_coldkey(
|
250
250
|
coldkey_ss58=wallet.coldkeypub.ss58_address,
|
251
251
|
block_hash=chain_head,
|
252
252
|
),
|
253
|
-
subtensor.get_balance(wallet.coldkeypub.ss58_address),
|
253
|
+
subtensor.get_balance(wallet.coldkeypub.ss58_address, block_hash=chain_head),
|
254
254
|
)
|
255
255
|
all_subnets = {di.netuid: di for di in _all_subnets}
|
256
256
|
|
@@ -307,6 +307,7 @@ async def stake_add(
|
|
307
307
|
return False
|
308
308
|
remaining_wallet_balance -= amount_to_stake
|
309
309
|
|
310
|
+
# TODO this should be asyncio gathered before the for loop
|
310
311
|
stake_fee = await subtensor.get_stake_fee(
|
311
312
|
origin_hotkey_ss58=None,
|
312
313
|
origin_netuid=None,
|
@@ -318,14 +319,20 @@ async def stake_add(
|
|
318
319
|
)
|
319
320
|
|
320
321
|
# Calculate slippage
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
322
|
+
# TODO: Update for V3, slippage calculation is significantly different in v3
|
323
|
+
# try:
|
324
|
+
# received_amount, slippage_pct, slippage_pct_float, rate = (
|
325
|
+
# _calculate_slippage(subnet_info, amount_to_stake, stake_fee)
|
326
|
+
# )
|
327
|
+
# except ValueError:
|
328
|
+
# return False
|
329
|
+
#
|
330
|
+
# max_slippage = max(slippage_pct_float, max_slippage)
|
331
|
+
|
332
|
+
# Temporary workaround - calculations without slippage
|
333
|
+
current_price_float = float(subnet_info.price.tao)
|
334
|
+
rate = 1.0 / current_price_float
|
335
|
+
received_amount = rate * amount_to_stake
|
329
336
|
|
330
337
|
# Add rows for the table
|
331
338
|
base_row = [
|
@@ -336,20 +343,20 @@ async def stake_add(
|
|
336
343
|
+ f" {Balance.get_unit(netuid)}/{Balance.get_unit(0)} ", # rate
|
337
344
|
str(received_amount.set_unit(netuid)), # received
|
338
345
|
str(stake_fee), # fee
|
339
|
-
str(slippage_pct), # slippage
|
346
|
+
# str(slippage_pct), # slippage
|
340
347
|
]
|
341
348
|
|
342
349
|
# If we are staking safe, add price tolerance
|
343
350
|
if safe_staking:
|
344
351
|
if subnet_info.is_dynamic:
|
345
|
-
|
346
|
-
_rate_with_tolerance =
|
347
|
-
1
|
352
|
+
price_with_tolerance = current_price_float * (1 + rate_tolerance)
|
353
|
+
_rate_with_tolerance = (
|
354
|
+
1.0 / price_with_tolerance
|
348
355
|
) # Rate only for display
|
349
356
|
rate_with_tolerance = f"{_rate_with_tolerance:.4f}"
|
350
|
-
price_with_tolerance =
|
351
|
-
|
352
|
-
) # Actual price to pass to extrinsic
|
357
|
+
price_with_tolerance = Balance.from_tao(
|
358
|
+
price_with_tolerance
|
359
|
+
).rao # Actual price to pass to extrinsic
|
353
360
|
else:
|
354
361
|
rate_with_tolerance = "1"
|
355
362
|
price_with_tolerance = Balance.from_rao(1)
|
@@ -581,9 +588,10 @@ def _define_stake_table(
|
|
581
588
|
justify="center",
|
582
589
|
style=COLOR_PALETTE["STAKE"]["STAKE_AMOUNT"],
|
583
590
|
)
|
584
|
-
|
585
|
-
|
586
|
-
|
591
|
+
# TODO: Uncomment when slippage is reimplemented for v3
|
592
|
+
# table.add_column(
|
593
|
+
# "Slippage", justify="center", style=COLOR_PALETTE["STAKE"]["SLIPPAGE_PERCENT"]
|
594
|
+
# )
|
587
595
|
|
588
596
|
if safe_staking:
|
589
597
|
table.add_column(
|
@@ -628,8 +636,8 @@ The columns are as follows:
|
|
628
636
|
- [bold white]Hotkey[/bold white]: The ss58 address of the hotkey you are staking to.
|
629
637
|
- [bold white]Amount[/bold white]: The TAO you are staking into this subnet onto this hotkey.
|
630
638
|
- [bold white]Rate[/bold white]: The rate of exchange between your TAO and the subnet's stake.
|
631
|
-
- [bold white]Received[/bold white]: The amount of stake you will receive on this subnet after slippage.
|
632
|
-
- [bold white]Slippage[/bold white]: The slippage percentage of the stake operation. (0% if the subnet is not dynamic i.e. root)."""
|
639
|
+
- [bold white]Received[/bold white]: The amount of stake you will receive on this subnet after slippage."""
|
640
|
+
# - [bold white]Slippage[/bold white]: The slippage percentage of the stake operation. (0% if the subnet is not dynamic i.e. root)."""
|
633
641
|
|
634
642
|
safe_staking_description = """
|
635
643
|
- [bold white]Rate Tolerance[/bold white]: Maximum acceptable alpha rate. If the rate exceeds this tolerance, the transaction will be limited or rejected.
|
@@ -654,6 +662,9 @@ def _calculate_slippage(
|
|
654
662
|
- slippage_str: Formatted slippage percentage string
|
655
663
|
- slippage_float: Raw slippage percentage value
|
656
664
|
- rate: Exchange rate string
|
665
|
+
|
666
|
+
TODO: Update to v3. This method only works for protocol-liquidity-only
|
667
|
+
mode (user liquidity disabled)
|
657
668
|
"""
|
658
669
|
amount_after_fee = amount - stake_fee
|
659
670
|
|
@@ -670,6 +681,7 @@ def _calculate_slippage(
|
|
670
681
|
slippage_str = f"{slippage_pct_float:.4f} %"
|
671
682
|
rate = f"{(1 / subnet_info.price.tao or 1):.4f}"
|
672
683
|
else:
|
684
|
+
# TODO: Fix this. Slippage is always zero for static networks.
|
673
685
|
slippage_pct_float = (
|
674
686
|
100 * float(stake_fee.tao) / float(amount.tao) if amount.tao != 0 else 0
|
675
687
|
)
|
@@ -111,15 +111,15 @@ async def stake_list(
|
|
111
111
|
style=COLOR_PALETTE["POOLS"]["RATE"],
|
112
112
|
justify="center",
|
113
113
|
)
|
114
|
-
defined_table.add_column(
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
)
|
114
|
+
# defined_table.add_column(
|
115
|
+
# f"[white]Swap ({Balance.get_unit(1)} -> {Balance.unit})",
|
116
|
+
# footer_style="overline white",
|
117
|
+
# style=COLOR_PALETTE["STAKE"]["STAKE_SWAP"],
|
118
|
+
# justify="right",
|
119
|
+
# footer=f"τ {millify_tao(total_swapped_tao_value_.tao)}"
|
120
|
+
# if not verbose
|
121
|
+
# else f"{total_swapped_tao_value_}",
|
122
|
+
# )
|
123
123
|
defined_table.add_column(
|
124
124
|
"[white]Registered",
|
125
125
|
style=COLOR_PALETTE["STAKE"]["STAKE_ALPHA"],
|
@@ -168,25 +168,17 @@ async def stake_list(
|
|
168
168
|
tao_value_ = pool.alpha_to_tao(alpha_value)
|
169
169
|
total_tao_value_ += tao_value_
|
170
170
|
|
171
|
-
#
|
172
|
-
|
173
|
-
|
174
|
-
)
|
175
|
-
total_swapped_tao_value_ += swapped_tao_value_
|
176
|
-
|
177
|
-
# Slippage percentage cell
|
178
|
-
if pool.is_dynamic:
|
179
|
-
slippage_percentage = f"[{COLOR_PALETTE['STAKE']['SLIPPAGE_PERCENT']}]{slippage_percentage_:.3f}%[/{COLOR_PALETTE['STAKE']['SLIPPAGE_PERCENT']}]"
|
180
|
-
else:
|
181
|
-
slippage_percentage = f"[{COLOR_PALETTE['STAKE']['SLIPPAGE_PERCENT']}]0.000%[/{COLOR_PALETTE['STAKE']['SLIPPAGE_PERCENT']}]"
|
171
|
+
# TAO value cell
|
172
|
+
tao_value_ = pool.alpha_to_tao(substake_.stake)
|
173
|
+
total_swapped_tao_value_ += tao_value_
|
182
174
|
|
183
175
|
if netuid == 0:
|
184
|
-
swap_value = f"[{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]N/A[/{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]
|
176
|
+
swap_value = f"[{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]N/A[/{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]"
|
185
177
|
else:
|
186
178
|
swap_value = (
|
187
|
-
f"τ {millify_tao(
|
179
|
+
f"τ {millify_tao(tao_value_.tao)}"
|
188
180
|
if not verbose
|
189
|
-
else f"{
|
181
|
+
else f"{tao_value_}"
|
190
182
|
)
|
191
183
|
|
192
184
|
# Per block emission cell
|
@@ -214,7 +206,7 @@ async def stake_list(
|
|
214
206
|
else f"{symbol} {stake_value}", # Stake (a)
|
215
207
|
f"{pool.price.tao:.4f} τ/{symbol}", # Rate (t/a)
|
216
208
|
# f"τ {millify_tao(tao_ownership.tao)}" if not verbose else f"{tao_ownership}", # TAO equiv
|
217
|
-
swap_value, # Swap(α) -> τ
|
209
|
+
# swap_value, # Swap(α) -> τ
|
218
210
|
"YES"
|
219
211
|
if substake_.is_registered
|
220
212
|
else f"[{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]NO", # Registered
|
@@ -232,7 +224,7 @@ async def stake_list(
|
|
232
224
|
"value": tao_value_.tao,
|
233
225
|
"stake_value": substake_.stake.tao,
|
234
226
|
"rate": pool.price.tao,
|
235
|
-
"swap_value": swap_value,
|
227
|
+
# "swap_value": swap_value,
|
236
228
|
"registered": True if substake_.is_registered else False,
|
237
229
|
"emission": {
|
238
230
|
"alpha": per_block_emission,
|
@@ -317,9 +309,7 @@ async def stake_list(
|
|
317
309
|
alpha_value = Balance.from_rao(int(substake_.stake.rao)).set_unit(netuid)
|
318
310
|
tao_value_ = pool.alpha_to_tao(alpha_value)
|
319
311
|
total_tao_value_ += tao_value_
|
320
|
-
swapped_tao_value_
|
321
|
-
pool.alpha_to_tao_with_slippage(substake_.stake)
|
322
|
-
)
|
312
|
+
swapped_tao_value_ = pool.alpha_to_tao(substake_.stake)
|
323
313
|
total_swapped_tao_value_ += swapped_tao_value_
|
324
314
|
|
325
315
|
# Store current values for future delta tracking
|
@@ -364,19 +354,16 @@ async def stake_list(
|
|
364
354
|
)
|
365
355
|
|
366
356
|
if netuid != 0:
|
367
|
-
swap_cell = (
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
millify=True if not verbose else False,
|
375
|
-
)
|
376
|
-
+ f" ({slippage_pct:.2f}%)"
|
357
|
+
swap_cell = format_cell(
|
358
|
+
swapped_tao_value_.tao,
|
359
|
+
prev.get("swapped_value"),
|
360
|
+
unit="τ",
|
361
|
+
unit_first_=True,
|
362
|
+
precision=4,
|
363
|
+
millify=True if not verbose else False,
|
377
364
|
)
|
378
365
|
else:
|
379
|
-
swap_cell = f"[{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]N/A[/{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]
|
366
|
+
swap_cell = f"[{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]N/A[/{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]"
|
380
367
|
|
381
368
|
emission_value = substake_.emission.tao / (pool.tempo or 1)
|
382
369
|
emission_cell = format_cell(
|
@@ -408,7 +395,7 @@ async def stake_list(
|
|
408
395
|
exchange_cell, # Exchange value
|
409
396
|
stake_cell, # Stake amount
|
410
397
|
rate_cell, # Rate
|
411
|
-
swap_cell, # Swap value
|
398
|
+
# swap_cell, # Swap value
|
412
399
|
"YES"
|
413
400
|
if substake_.is_registered
|
414
401
|
else f"[{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]NO", # Registration status
|
@@ -591,12 +578,12 @@ async def stake_list(
|
|
591
578
|
f"Wallet:\n"
|
592
579
|
f" Coldkey SS58: [{COLOR_PALETTE['GENERAL']['COLDKEY']}]{coldkey_address}[/{COLOR_PALETTE['GENERAL']['COLDKEY']}]\n"
|
593
580
|
f" Free Balance: [{COLOR_PALETTE['GENERAL']['BALANCE']}]{balance}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]\n"
|
594
|
-
f" Total TAO Value ({Balance.unit}): [{COLOR_PALETTE['GENERAL']['BALANCE']}]{total_tao_value}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]
|
595
|
-
f" Total TAO Swapped Value ({Balance.unit}): [{COLOR_PALETTE['GENERAL']['BALANCE']}]{total_swapped_tao_value}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]"
|
581
|
+
f" Total TAO Value ({Balance.unit}): [{COLOR_PALETTE['GENERAL']['BALANCE']}]{total_tao_value}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]"
|
582
|
+
# f"\n Total TAO Swapped Value ({Balance.unit}): [{COLOR_PALETTE['GENERAL']['BALANCE']}]{total_swapped_tao_value}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]"
|
596
583
|
)
|
597
584
|
dict_output["free_balance"] = balance.tao
|
598
585
|
dict_output["total_tao_value"] = all_hks_tao_value.tao
|
599
|
-
dict_output["total_swapped_tao_value"] = all_hks_swapped_tao_value.tao
|
586
|
+
# dict_output["total_swapped_tao_value"] = all_hks_swapped_tao_value.tao
|
600
587
|
if json_output:
|
601
588
|
json_console.print(json.dumps(dict_output))
|
602
589
|
if not sub_stakes:
|
@@ -658,12 +645,12 @@ async def stake_list(
|
|
658
645
|
),
|
659
646
|
(
|
660
647
|
"[bold tan]Exchange Value (α x τ/α)[/bold tan]",
|
661
|
-
"This is the potential τ you will receive
|
662
|
-
),
|
663
|
-
(
|
664
|
-
"[bold tan]Swap (α → τ)[/bold tan]",
|
665
|
-
"This is the actual τ you will receive, after factoring in the slippage charge, if you unstake from this hotkey now on this subnet. The slippage is calculated as 1 - (Swap(α → τ)/Exchange Value(α x τ/α)), and is displayed in brackets. This can change every block. \nFor more, see [blue]https://docs.bittensor.com/dynamic-tao/dtao-guide#swap-%CE%B1--%CF%84[/blue].",
|
648
|
+
"This is the potential τ you will receive if you unstake from this hotkey now on this subnet. Note: The TAO Equiv(τ_in x α/α_out) indicates validator stake weight while this Exchange Value shows τ you will receive if you unstake now. This can change every block. \nFor more, see [blue]https://docs.bittensor.com/dynamic-tao/dtao-guide#exchange-value-%CE%B1-x-%CF%84%CE%B1[/blue].",
|
666
649
|
),
|
650
|
+
# (
|
651
|
+
# "[bold tan]Swap (α → τ)[/bold tan]",
|
652
|
+
# "This is the τ you will receive if you unstake from this hotkey now on this subnet. This can change every block. \nFor more, see [blue]https://docs.bittensor.com/dynamic-tao/dtao-guide#swap-%CE%B1--%CF%84[/blue].",
|
653
|
+
# ),
|
667
654
|
(
|
668
655
|
"[bold tan]Registered[/bold tan]",
|
669
656
|
"Indicates if the hotkey is registered in this subnet or not. \nFor more, see [blue]https://docs.bittensor.com/learn/anatomy-of-incentive-mechanism#tempo[/blue].",
|
@@ -33,8 +33,8 @@ async def display_stake_movement_cross_subnets(
|
|
33
33
|
destination_hotkey: str,
|
34
34
|
amount_to_move: Balance,
|
35
35
|
stake_fee: Balance,
|
36
|
-
) -> tuple[Balance,
|
37
|
-
"""Calculate and display
|
36
|
+
) -> tuple[Balance, str]:
|
37
|
+
"""Calculate and display stake movement information"""
|
38
38
|
|
39
39
|
if origin_netuid == destination_netuid:
|
40
40
|
subnet = await subtensor.subnet(origin_netuid)
|
@@ -46,45 +46,32 @@ async def display_stake_movement_cross_subnets(
|
|
46
46
|
raise ValueError
|
47
47
|
|
48
48
|
received_amount = subnet.tao_to_alpha(received_amount_tao)
|
49
|
-
|
50
|
-
100 * float(stake_fee) / float(stake_fee + received_amount_tao)
|
51
|
-
if received_amount_tao != 0
|
52
|
-
else 0
|
53
|
-
)
|
54
|
-
slippage_pct = f"{slippage_pct_float:.4f}%"
|
55
|
-
price = Balance.from_tao(1).set_unit(origin_netuid)
|
49
|
+
price = subnet.price.tao
|
56
50
|
price_str = (
|
57
|
-
str(float(price
|
58
|
-
+ f"{Balance.get_unit(
|
51
|
+
str(float(price))
|
52
|
+
+ f"({Balance.get_unit(0)}/{Balance.get_unit(origin_netuid)})"
|
59
53
|
)
|
60
54
|
else:
|
61
55
|
dynamic_origin, dynamic_destination = await asyncio.gather(
|
62
56
|
subtensor.subnet(origin_netuid),
|
63
57
|
subtensor.subnet(destination_netuid),
|
64
58
|
)
|
65
|
-
|
66
|
-
|
67
|
-
)
|
68
|
-
|
69
|
-
|
70
|
-
)
|
59
|
+
price_origin = dynamic_origin.price.tao
|
60
|
+
price_destination = dynamic_destination.price.tao
|
61
|
+
rate = price_origin / (price_destination or 1)
|
62
|
+
|
63
|
+
received_amount_tao = dynamic_origin.alpha_to_tao(amount_to_move)
|
71
64
|
received_amount_tao -= stake_fee
|
72
|
-
received_amount
|
73
|
-
received_amount_tao
|
74
|
-
)
|
65
|
+
received_amount = dynamic_destination.tao_to_alpha(received_amount_tao)
|
75
66
|
received_amount.set_unit(destination_netuid)
|
76
67
|
|
77
68
|
if received_amount < Balance.from_tao(0):
|
78
69
|
print_error("Not enough Alpha to pay the transaction fee.")
|
79
70
|
raise ValueError
|
80
71
|
|
81
|
-
ideal_amount = amount_to_move * price
|
82
|
-
total_slippage = ideal_amount - received_amount
|
83
|
-
slippage_pct_float = 100 * (total_slippage.tao / ideal_amount.tao)
|
84
|
-
slippage_pct = f"{slippage_pct_float:.4f} %"
|
85
72
|
price_str = (
|
86
|
-
f"{
|
87
|
-
+ f"{Balance.get_unit(destination_netuid)}/{Balance.get_unit(origin_netuid)}"
|
73
|
+
f"{rate:.5f}"
|
74
|
+
+ f"({Balance.get_unit(destination_netuid)}/{Balance.get_unit(origin_netuid)})"
|
88
75
|
)
|
89
76
|
|
90
77
|
# Create and display table
|
@@ -141,11 +128,6 @@ async def display_stake_movement_cross_subnets(
|
|
141
128
|
justify="center",
|
142
129
|
style=COLOR_PALETTE["STAKE"]["STAKE_AMOUNT"],
|
143
130
|
)
|
144
|
-
table.add_column(
|
145
|
-
"slippage",
|
146
|
-
justify="center",
|
147
|
-
style=COLOR_PALETTE["STAKE"]["SLIPPAGE_PERCENT"],
|
148
|
-
)
|
149
131
|
|
150
132
|
table.add_row(
|
151
133
|
f"{Balance.get_unit(origin_netuid)}({origin_netuid})",
|
@@ -156,19 +138,11 @@ async def display_stake_movement_cross_subnets(
|
|
156
138
|
price_str,
|
157
139
|
str(received_amount),
|
158
140
|
str(stake_fee),
|
159
|
-
str(slippage_pct),
|
160
141
|
)
|
161
142
|
|
162
143
|
console.print(table)
|
163
144
|
|
164
|
-
|
165
|
-
if slippage_pct_float > 5:
|
166
|
-
message = f"[{COLOR_PALETTE['STAKE']['SLIPPAGE_TEXT']}]-------------------------------------------------------------------------------------------------------------------\n"
|
167
|
-
message += f"[bold]WARNING:\tSlippage is high: [{COLOR_PALETTE['STAKE']['SLIPPAGE_PERCENT']}]{slippage_pct}[/{COLOR_PALETTE['STAKE']['SLIPPAGE_PERCENT']}], this may result in a loss of funds.[/bold] \n"
|
168
|
-
message += "-------------------------------------------------------------------------------------------------------------------\n"
|
169
|
-
console.print(message)
|
170
|
-
|
171
|
-
return received_amount, slippage_pct_float, slippage_pct, price_str
|
145
|
+
return received_amount, price_str
|
172
146
|
|
173
147
|
|
174
148
|
def prompt_stake_amount(
|
@@ -414,7 +388,7 @@ async def stake_swap_selection(
|
|
414
388
|
origin_stake = hotkey_stakes[origin_netuid]["stake"]
|
415
389
|
|
416
390
|
# Ask for amount to swap
|
417
|
-
amount,
|
391
|
+
amount, _ = prompt_stake_amount(origin_stake, origin_netuid, "swap")
|
418
392
|
|
419
393
|
all_netuids = sorted(await subtensor.get_all_subnet_netuids())
|
420
394
|
destination_choices = [
|
@@ -530,7 +504,7 @@ async def move_stake(
|
|
530
504
|
amount=amount_to_move_as_balance.rao,
|
531
505
|
)
|
532
506
|
|
533
|
-
#
|
507
|
+
# Display stake movement details
|
534
508
|
if prompt:
|
535
509
|
try:
|
536
510
|
await display_stake_movement_cross_subnets(
|
@@ -714,7 +688,7 @@ async def transfer_stake(
|
|
714
688
|
amount=amount_to_transfer.rao,
|
715
689
|
)
|
716
690
|
|
717
|
-
#
|
691
|
+
# Display stake movement details
|
718
692
|
if prompt:
|
719
693
|
try:
|
720
694
|
await display_stake_movement_cross_subnets(
|
@@ -883,7 +857,7 @@ async def swap_stake(
|
|
883
857
|
amount=amount_to_swap.rao,
|
884
858
|
)
|
885
859
|
|
886
|
-
#
|
860
|
+
# Display stake movement details
|
887
861
|
if prompt:
|
888
862
|
try:
|
889
863
|
await display_stake_movement_cross_subnets(
|