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.
@@ -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
- try:
322
- received_amount, slippage_pct, slippage_pct_float, rate = (
323
- _calculate_slippage(subnet_info, amount_to_stake, stake_fee)
324
- )
325
- except ValueError:
326
- return False
327
-
328
- max_slippage = max(slippage_pct_float, max_slippage)
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
- rate = 1 / subnet_info.price.tao or 1
346
- _rate_with_tolerance = rate * (
347
- 1 + rate_tolerance
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 = subnet_info.price.rao * (
351
- 1 + rate_tolerance
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
- table.add_column(
585
- "Slippage", justify="center", style=COLOR_PALETTE["STAKE"]["SLIPPAGE_PERCENT"]
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
- 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
- )
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
- # Swapped TAO value and slippage cell
172
- swapped_tao_value_, _, slippage_percentage_ = (
173
- pool.alpha_to_tao_with_slippage(substake_.stake)
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']}] ({slippage_percentage})"
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(swapped_tao_value_.tao)} ({slippage_percentage})"
179
+ f"τ {millify_tao(tao_value_.tao)}"
188
180
  if not verbose
189
- else f"{swapped_tao_value_} ({slippage_percentage})"
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_, slippage, slippage_pct = (
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
- format_cell(
369
- swapped_tao_value_.tao,
370
- prev.get("swapped_value"),
371
- unit="τ",
372
- unit_first_=True,
373
- precision=4,
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']}] ({slippage_pct}%)"
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 with slippage
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']}]\n"
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, without considering slippage, if you unstake from this hotkey now on this subnet. See Swap(α → τ) column description. 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].",
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, float, str, str]:
37
- """Calculate and display slippage information"""
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
- slippage_pct_float = (
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.tao))
58
- + f"{Balance.get_unit(origin_netuid)}/{Balance.get_unit(origin_netuid)}"
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
- price = (
66
- float(dynamic_origin.price) * 1 / (float(dynamic_destination.price) or 1)
67
- )
68
- received_amount_tao, _, _ = dynamic_origin.alpha_to_tao_with_slippage(
69
- amount_to_move
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, _, _ = dynamic_destination.tao_to_alpha_with_slippage(
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"{price:.5f}"
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
- # Display slippage warning if necessary
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, all_balance = prompt_stake_amount(origin_stake, origin_netuid, "swap")
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
- # Slippage warning
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
- # Slippage warning
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
- # Slippage warning
860
+ # Display stake movement details
887
861
  if prompt:
888
862
  try:
889
863
  await display_stake_movement_cross_subnets(