|
1 |
| -from typing import Optional, TYPE_CHECKING |
2 |
| - |
3 |
| -import rich.prompt |
4 |
| -from rich.table import Table |
5 |
| - |
6 |
| -from bittensor_cli.src.bittensor.chain_data import DelegateInfoLite |
7 |
| -from bittensor_cli.src.bittensor.utils import console |
8 |
| - |
9 |
| -if TYPE_CHECKING: |
10 |
| - from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface |
11 |
| - |
12 |
| - |
13 |
| -async def select_delegate(subtensor: "SubtensorInterface", netuid: int): |
14 |
| - # Get a list of delegates and sort them by total stake in descending order |
15 |
| - delegates: list[DelegateInfoLite] = ( |
16 |
| - await subtensor.get_delegates_by_netuid_light(netuid) |
17 |
| - ).sort(key=lambda x: x.total_stake, reverse=True) |
18 |
| - |
19 |
| - # Get registered delegates details. |
20 |
| - registered_delegate_info = await subtensor.get_delegate_identities() |
21 |
| - |
22 |
| - # Create a table to display delegate information |
23 |
| - table = Table( |
24 |
| - show_header=True, |
25 |
| - header_style="bold", |
26 |
| - border_style="rgb(7,54,66)", |
27 |
| - style="rgb(0,43,54)", |
28 |
| - ) |
29 |
| - |
30 |
| - # Add columns to the table with specific styles |
31 |
| - table.add_column("Index", style="rgb(253,246,227)", no_wrap=True) |
32 |
| - table.add_column("Delegate Name", no_wrap=True) |
33 |
| - table.add_column("Hotkey SS58", style="rgb(211,54,130)", no_wrap=True) |
34 |
| - table.add_column("Owner SS58", style="rgb(133,153,0)", no_wrap=True) |
35 |
| - table.add_column("Take", style="rgb(181,137,0)", no_wrap=True) |
36 |
| - table.add_column( |
37 |
| - "Total Stake", style="rgb(38,139,210)", no_wrap=True, justify="right" |
38 |
| - ) |
39 |
| - table.add_column( |
40 |
| - "Owner Stake", style="rgb(220,50,47)", no_wrap=True, justify="right" |
41 |
| - ) |
42 |
| - # table.add_column("Return per 1000", style="rgb(108,113,196)", no_wrap=True, justify="right") |
43 |
| - # table.add_column("Total Daily Return", style="rgb(42,161,152)", no_wrap=True, justify="right") |
44 |
| - |
45 |
| - # List to store visible delegates |
46 |
| - visible_delegates = [] |
47 |
| - |
48 |
| - def get_user_input() -> str: |
49 |
| - return rich.prompt.Prompt.ask( |
50 |
| - 'Press Enter to scroll, enter a number (1-N) to select, or type "h" for help: ', |
51 |
| - choices=["", "h"] + [str(x) for x in range(1, len(delegates) - 1)], |
52 |
| - show_choices=True, |
53 |
| - ) |
54 |
| - |
55 |
| - # TODO: Add pagination to handle large number of delegates more efficiently |
56 |
| - # Iterate through delegates and display their information |
57 |
| - |
58 |
| - def loop_selections() -> Optional[int]: |
59 |
| - idx = 0 |
60 |
| - selected_idx = None |
61 |
| - while idx < len(delegates): |
62 |
| - if idx < len(delegates): |
63 |
| - delegate = delegates[idx] |
64 |
| - |
65 |
| - # Add delegate to visible list |
66 |
| - visible_delegates.append(delegate) |
67 |
| - |
68 |
| - # Add a row to the table with delegate information |
69 |
| - table.add_row( |
70 |
| - str(idx), |
71 |
| - registered_delegate_info[delegate.hotkey_ss58].name |
72 |
| - if delegate.hotkey_ss58 in registered_delegate_info |
73 |
| - else "", |
74 |
| - delegate.hotkey_ss58[:5] |
75 |
| - + "..." |
76 |
| - + delegate.hotkey_ss58[-5:], # Show truncated hotkey |
77 |
| - delegate.owner_ss58[:5] |
78 |
| - + "..." |
79 |
| - + delegate.owner_ss58[-5:], # Show truncated owner address |
80 |
| - f"{delegate.take:.6f}", |
81 |
| - f"τ{delegate.total_stake.tao:,.4f}", |
82 |
| - f"τ{delegate.owner_stake.tao:,.4f}", |
83 |
| - # f"τ{delegate.return_per_1000.tao:,.4f}", |
84 |
| - # f"τ{delegate.total_daily_return.tao:,.4f}", |
85 |
| - ) |
86 |
| - |
87 |
| - # Clear console and print updated table |
88 |
| - console.clear() |
89 |
| - console.print(table) |
90 |
| - |
91 |
| - # Prompt user for input |
92 |
| - user_input: str = get_user_input() |
93 |
| - |
94 |
| - # Add a help option to display information about each column |
95 |
| - if user_input == "h": |
96 |
| - console.print("\nColumn Information:") |
97 |
| - console.print( |
98 |
| - "[rgb(253,246,227)]Index:[/rgb(253,246,227)] Position in the list of delegates" |
99 |
| - ) |
100 |
| - console.print( |
101 |
| - "[rgb(211,54,130)]Hotkey SS58:[/rgb(211,54,130)] Truncated public key of the delegate's hotkey" |
102 |
| - ) |
103 |
| - console.print( |
104 |
| - "[rgb(133,153,0)]Owner SS58:[/rgb(133,153,0)] Truncated public key of the delegate's owner" |
105 |
| - ) |
106 |
| - console.print( |
107 |
| - "[rgb(181,137,0)]Take:[/rgb(181,137,0)] Percentage of rewards the delegate takes" |
108 |
| - ) |
109 |
| - console.print( |
110 |
| - "[rgb(38,139,210)]Total Stake:[/rgb(38,139,210)] Total amount staked to this delegate" |
111 |
| - ) |
112 |
| - console.print( |
113 |
| - "[rgb(220,50,47)]Owner Stake:[/rgb(220,50,47)] Amount staked by the delegate owner" |
114 |
| - ) |
115 |
| - console.print( |
116 |
| - "[rgb(108,113,196)]Return per 1000:[/rgb(108,113,196)] Estimated return for 1000 Tao staked" |
117 |
| - ) |
118 |
| - console.print( |
119 |
| - "[rgb(42,161,152)]Total Daily Return:[/rgb(42,161,152)] Estimated total daily return for all stake" |
120 |
| - ) |
121 |
| - user_input = get_user_input() |
122 |
| - |
123 |
| - # If user presses Enter, continue to next delegate |
124 |
| - if user_input and user_input != "h": |
125 |
| - selected_idx = int(user_input) |
126 |
| - break |
127 |
| - |
128 |
| - if idx < len(delegates): |
129 |
| - idx += 1 |
130 |
| - |
131 |
| - return selected_idx |
132 |
| - |
133 |
| - # TODO( const ): uncomment for check |
134 |
| - # Add a confirmation step before returning the selected delegate |
135 |
| - # console.print(f"\nSelected delegate: [rgb(211,54,130)]{visible_delegates[selected_idx].hotkey_ss58}[/rgb(211,54,130)]") |
136 |
| - # console.print(f"Take: [rgb(181,137,0)]{visible_delegates[selected_idx].take:.6f}[/rgb(181,137,0)]") |
137 |
| - # console.print(f"Total Stake: [rgb(38,139,210)]{visible_delegates[selected_idx].total_stake}[/rgb(38,139,210)]") |
138 |
| - |
139 |
| - # confirmation = Prompt.ask("Do you want to proceed with this delegate? (y/n)") |
140 |
| - # if confirmation.lower() != 'yes' and confirmation.lower() != 'y': |
141 |
| - # return select_delegate( subtensor, netuid ) |
142 |
| - |
143 |
| - # Return the selected delegate |
144 |
| - while True: |
145 |
| - selected_idx_ = loop_selections() |
146 |
| - if selected_idx_ is None: |
147 |
| - if not rich.prompt.Confirm.ask( |
148 |
| - "You've reached the end of the list. You must make a selection. Loop through again?" |
149 |
| - ): |
150 |
| - raise IndexError |
151 |
| - else: |
152 |
| - continue |
153 |
| - else: |
154 |
| - return delegates[selected_idx_] |
0 commit comments