Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Cleanup #381

Merged
merged 5 commits into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bittensor_cli/src/bittensor/chain_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,9 @@ def tao_to_alpha(self, tao: Balance) -> Balance:
def alpha_to_tao(self, alpha: Balance) -> Balance:
return Balance.from_tao(alpha.tao * self.price.tao)

def tao_to_alpha_with_slippage(self, tao: Balance) -> tuple[Balance, Balance]:
def tao_to_alpha_with_slippage(
self, tao: Balance
) -> tuple[Balance, Balance, float]:
"""
Returns an estimate of how much Alpha would a staker receive if they stake their tao using the current pool state.
Args:
Expand Down
4 changes: 1 addition & 3 deletions bittensor_cli/src/bittensor/subtensor_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ async def get_stake_for_coldkey(

if result is None:
return []
stakes = StakeInfo.list_from_any(result)
stakes: list[StakeInfo] = StakeInfo.list_from_any(result)
return [stake for stake in stakes if stake.stake > 0]

async def get_stake_for_coldkey_and_hotkey(
Expand Down Expand Up @@ -352,14 +352,12 @@ async def get_total_stake_for_coldkey(
self,
*ss58_addresses,
block_hash: Optional[str] = None,
reuse_block: bool = False,
) -> dict[str, tuple[Balance, Balance]]:
"""
Returns the total stake held on a coldkey.

:param ss58_addresses: The SS58 address(es) of the coldkey(s)
:param block_hash: The hash of the block number to retrieve the stake from.
:param reuse_block: Whether to reuse the last-used block hash when retrieving info.

:return: {address: Balance objects}
"""
Expand Down
5 changes: 2 additions & 3 deletions bittensor_cli/src/bittensor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import sqlite3
import platform
import webbrowser
import sys
from pathlib import Path
from typing import TYPE_CHECKING, Any, Collection, Optional, Union, Callable
from urllib.parse import urlparse
Expand Down Expand Up @@ -73,8 +72,8 @@ def coldkeypub(self):
return self._coldkeypub


def print_console(message: str, colour: str, title: str, console: Console):
console.print(
def print_console(message: str, colour: str, title: str, console_: Console):
console_.print(
f"[bold {colour}][{title}]:[/bold {colour}] [{colour}]{message}[/{colour}]\n"
)

Expand Down
154 changes: 0 additions & 154 deletions bittensor_cli/src/commands/stake/__init__.py
Original file line number Diff line number Diff line change
@@ -1,154 +0,0 @@
from typing import Optional, TYPE_CHECKING

import rich.prompt
from rich.table import Table

from bittensor_cli.src.bittensor.chain_data import DelegateInfoLite
from bittensor_cli.src.bittensor.utils import console

if TYPE_CHECKING:
from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface


async def select_delegate(subtensor: "SubtensorInterface", netuid: int):
# Get a list of delegates and sort them by total stake in descending order
delegates: list[DelegateInfoLite] = (
await subtensor.get_delegates_by_netuid_light(netuid)
).sort(key=lambda x: x.total_stake, reverse=True)

# Get registered delegates details.
registered_delegate_info = await subtensor.get_delegate_identities()

# Create a table to display delegate information
table = Table(
show_header=True,
header_style="bold",
border_style="rgb(7,54,66)",
style="rgb(0,43,54)",
)

# Add columns to the table with specific styles
table.add_column("Index", style="rgb(253,246,227)", no_wrap=True)
table.add_column("Delegate Name", no_wrap=True)
table.add_column("Hotkey SS58", style="rgb(211,54,130)", no_wrap=True)
table.add_column("Owner SS58", style="rgb(133,153,0)", no_wrap=True)
table.add_column("Take", style="rgb(181,137,0)", no_wrap=True)
table.add_column(
"Total Stake", style="rgb(38,139,210)", no_wrap=True, justify="right"
)
table.add_column(
"Owner Stake", style="rgb(220,50,47)", no_wrap=True, justify="right"
)
# table.add_column("Return per 1000", style="rgb(108,113,196)", no_wrap=True, justify="right")
# table.add_column("Total Daily Return", style="rgb(42,161,152)", no_wrap=True, justify="right")

# List to store visible delegates
visible_delegates = []

def get_user_input() -> str:
return rich.prompt.Prompt.ask(
'Press Enter to scroll, enter a number (1-N) to select, or type "h" for help: ',
choices=["", "h"] + [str(x) for x in range(1, len(delegates) - 1)],
show_choices=True,
)

# TODO: Add pagination to handle large number of delegates more efficiently
# Iterate through delegates and display their information

def loop_selections() -> Optional[int]:
idx = 0
selected_idx = None
while idx < len(delegates):
if idx < len(delegates):
delegate = delegates[idx]

# Add delegate to visible list
visible_delegates.append(delegate)

# Add a row to the table with delegate information
table.add_row(
str(idx),
registered_delegate_info[delegate.hotkey_ss58].name
if delegate.hotkey_ss58 in registered_delegate_info
else "",
delegate.hotkey_ss58[:5]
+ "..."
+ delegate.hotkey_ss58[-5:], # Show truncated hotkey
delegate.owner_ss58[:5]
+ "..."
+ delegate.owner_ss58[-5:], # Show truncated owner address
f"{delegate.take:.6f}",
f"τ{delegate.total_stake.tao:,.4f}",
f"τ{delegate.owner_stake.tao:,.4f}",
# f"τ{delegate.return_per_1000.tao:,.4f}",
# f"τ{delegate.total_daily_return.tao:,.4f}",
)

# Clear console and print updated table
console.clear()
console.print(table)

# Prompt user for input
user_input: str = get_user_input()

# Add a help option to display information about each column
if user_input == "h":
console.print("\nColumn Information:")
console.print(
"[rgb(253,246,227)]Index:[/rgb(253,246,227)] Position in the list of delegates"
)
console.print(
"[rgb(211,54,130)]Hotkey SS58:[/rgb(211,54,130)] Truncated public key of the delegate's hotkey"
)
console.print(
"[rgb(133,153,0)]Owner SS58:[/rgb(133,153,0)] Truncated public key of the delegate's owner"
)
console.print(
"[rgb(181,137,0)]Take:[/rgb(181,137,0)] Percentage of rewards the delegate takes"
)
console.print(
"[rgb(38,139,210)]Total Stake:[/rgb(38,139,210)] Total amount staked to this delegate"
)
console.print(
"[rgb(220,50,47)]Owner Stake:[/rgb(220,50,47)] Amount staked by the delegate owner"
)
console.print(
"[rgb(108,113,196)]Return per 1000:[/rgb(108,113,196)] Estimated return for 1000 Tao staked"
)
console.print(
"[rgb(42,161,152)]Total Daily Return:[/rgb(42,161,152)] Estimated total daily return for all stake"
)
user_input = get_user_input()

# If user presses Enter, continue to next delegate
if user_input and user_input != "h":
selected_idx = int(user_input)
break

if idx < len(delegates):
idx += 1

return selected_idx

# TODO( const ): uncomment for check
# Add a confirmation step before returning the selected delegate
# console.print(f"\nSelected delegate: [rgb(211,54,130)]{visible_delegates[selected_idx].hotkey_ss58}[/rgb(211,54,130)]")
# console.print(f"Take: [rgb(181,137,0)]{visible_delegates[selected_idx].take:.6f}[/rgb(181,137,0)]")
# console.print(f"Total Stake: [rgb(38,139,210)]{visible_delegates[selected_idx].total_stake}[/rgb(38,139,210)]")

# confirmation = Prompt.ask("Do you want to proceed with this delegate? (y/n)")
# if confirmation.lower() != 'yes' and confirmation.lower() != 'y':
# return select_delegate( subtensor, netuid )

# Return the selected delegate
while True:
selected_idx_ = loop_selections()
if selected_idx_ is None:
if not rich.prompt.Confirm.ask(
"You've reached the end of the list. You must make a selection. Loop through again?"
):
raise IndexError
else:
continue
else:
return delegates[selected_idx_]
42 changes: 19 additions & 23 deletions bittensor_cli/src/commands/stake/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ async def stake_add(
netuid: the netuid to stake to (None indicates all subnets)
stake_all: whether to stake all available balance
amount: specified amount of balance to stake
delegate: whether to delegate stake, currently unused
prompt: whether to prompt the user
max_stake: maximum amount to stake (used in combination with stake_all), currently unused
all_hotkeys: whether to stake all hotkeys
include_hotkeys: list of hotkeys to include in staking process (if not specifying `--all`)
exclude_hotkeys: list of hotkeys to exclude in staking (if specifying `--all`)
Expand All @@ -61,18 +59,16 @@ async def stake_add(
"""

async def safe_stake_extrinsic(
netuid: int,
amount: Balance,
netuid_: int,
amount_: Balance,
current_stake: Balance,
hotkey_ss58: str,
hotkey_ss58_: str,
price_limit: Balance,
wallet: Wallet,
subtensor: "SubtensorInterface",
status=None,
) -> None:
err_out = partial(print_error, status=status)
failure_prelude = (
f":cross_mark: [red]Failed[/red] to stake {amount} on Netuid {netuid}"
f":cross_mark: [red]Failed[/red] to stake {amount_} on Netuid {netuid_}"
)
current_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
next_nonce = await subtensor.substrate.get_account_next_index(
Expand All @@ -82,9 +78,9 @@ async def safe_stake_extrinsic(
call_module="SubtensorModule",
call_function="add_stake_limit",
call_params={
"hotkey": hotkey_ss58,
"netuid": netuid,
"amount_staked": amount.rao,
"hotkey": hotkey_ss58_,
"netuid": netuid_,
"amount_staked": amount_.rao,
"limit_price": price_limit,
"allow_partial": allow_partial_stake,
},
Expand Down Expand Up @@ -119,30 +115,30 @@ async def safe_stake_extrinsic(
new_balance, new_stake = await asyncio.gather(
subtensor.get_balance(wallet.coldkeypub.ss58_address, block_hash),
subtensor.get_stake(
hotkey_ss58=hotkey_ss58,
hotkey_ss58=hotkey_ss58_,
coldkey_ss58=wallet.coldkeypub.ss58_address,
netuid=netuid,
netuid=netuid_,
block_hash=block_hash,
),
)
console.print(
f":white_heavy_check_mark: [dark_sea_green3]Finalized. Stake added to netuid: {netuid}[/dark_sea_green3]"
f":white_heavy_check_mark: [dark_sea_green3]Finalized. Stake added to netuid: {netuid_}[/dark_sea_green3]"
)
console.print(
f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
)

amount_staked = current_balance - new_balance
if allow_partial_stake and (amount_staked != amount):
if allow_partial_stake and (amount_staked != amount_):
console.print(
"Partial stake transaction. Staked:\n"
f" [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{amount_staked}[/{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}] "
f"instead of "
f"[blue]{amount}[/blue]"
f"[blue]{amount_}[/blue]"
)

console.print(
f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid_}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
f"Stake:\n"
f" [blue]{current_stake}[/blue] "
f":arrow_right: "
Expand Down Expand Up @@ -361,13 +357,11 @@ async def stake_extrinsic(
else:
stake_coroutines.append(
safe_stake_extrinsic(
netuid=ni,
amount=am,
netuid_=ni,
amount_=am,
current_stake=curr,
hotkey_ss58=staking_address,
hotkey_ss58_=staking_address,
price_limit=price_with_tolerance,
wallet=wallet,
subtensor=subtensor,
)
)
else:
Expand Down Expand Up @@ -590,7 +584,9 @@ def _print_table_and_slippage(table: Table, max_slippage: float, safe_staking: b
console.print(base_description + (safe_staking_description if safe_staking else ""))


def _calculate_slippage(subnet_info, amount: Balance) -> tuple[Balance, str, float]:
def _calculate_slippage(
subnet_info, amount: Balance
) -> tuple[Balance, str, float, str]:
"""Calculate slippage when adding stake.

Args:
Expand Down
Loading
Loading