Skip to content

Commit

Permalink
Merge pull request #313 from opentensor/backmerge-main-to-staging-900
Browse files Browse the repository at this point in the history
Backmerge main to staging 900
  • Loading branch information
ibraheem-opentensor authored Feb 13, 2025
2 parents f2f0bc8 + 3a3edd9 commit dba6c85
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 39 deletions.
51 changes: 46 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,52 @@
# Changelog

## 9.0.0rc4 /2025-02-12
* Adds sort option to metagraph/show
* Updates metagraph/show to use direct dividends instead of relative
* Updates subnets list to use working tao emissions
## 9.0.0 /2025-02-13

## 9.0.0rc3 /2025-02-11
## What's Changed
* Btcli ported to Rao by @ibraheem-opentensor & @thewhaleking in https://github.com/opentensor/btcli/tree/rao-games/pools
* fix netuid from str to int by @roman-opentensor in https://github.com/opentensor/btcli/pull/195
* add runtime apis to reg by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/196
* Updated tables (st list, s list) by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/200
* Modifying descriptions and links in stake and subnets dot py files by @rajkaramchedu in https://github.com/opentensor/btcli/pull/246
* Fixes Identity Lookup (Rao Games Pools) by @thewhaleking in https://github.com/opentensor/btcli/pull/279
* Show encrypted hotkeys in w list by @thewhaleking in https://github.com/opentensor/btcli/pull/288
* Backmerge rao branch to decoding branch by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/290
* Updates identity, sn identity, and other chain stuff by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/292
* Updates Rao to decode using chain by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/286
* Fix/rao remove mention of cost by @camfairchild in https://github.com/opentensor/btcli/pull/293
* Uses uvloop if it's installed by @thewhaleking in https://github.com/opentensor/btcli/pull/294
* Feat: Safe staking by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/299
* Removes stake from w balances by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/301
* Updates docstrings for commands by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/303
* Release/9.0.0rc4 by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/306
* Rao to staging merge (new branch) by @thewhaleking in https://github.com/opentensor/btcli/pull/305
* [WIP] Rao by @thewhaleking in https://github.com/opentensor/btcli/pull/129
* Updates e2e tests for rao by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/307
* Update dividends, adds sort by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/308
* Final cleanups for Rao by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/309

## New Contributors
* @camfairchild made their first contribution in https://github.com/opentensor/btcli/pull/293

**Full Changelog**: https://github.com/opentensor/btcli/compare/v8.4.4...v9.0.0

## 8.4.4 /2025-02-07 - 18:30 PST

## What's Changed
* Proposals info fix (for dtao governance vote) by @ibraheem-opentensor

**Full Changelog**: https://github.com/opentensor/btcli/compare/v8.4.3...v8.4.4

## 8.4.3 /2025-01-23

## What's Changed
* Backmerge main to staging 842 by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/273
* Fix arg order for set-identity by @thewhaleking in https://github.com/opentensor/btcli/pull/282
* Adds updates to btwallet3, adds overwrite flag and updates tests by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/275

**Full Changelog**: https://github.com/opentensor/btcli/compare/v8.4.2...v8.4.3

## 8.4.2 /2024-12-12

## What's Changed
* Removes the `.value` checks as we no longer use SCALE objects. by @thewhaleking in https://github.com/opentensor/btcli/pull/270
Expand Down
2 changes: 1 addition & 1 deletion bittensor_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
from .cli import CLIManager


__version__ = "9.0.0rc4"
__version__ = "9.0.0"

__all__ = ["CLIManager", "__version__"]
6 changes: 4 additions & 2 deletions bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class GitError(Exception):
pass


__version__ = "9.0.0rc4"
__version__ = "9.0.0"


_core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0)
Expand Down Expand Up @@ -4072,7 +4072,9 @@ def sudo_proposals(
[green]$[/green] btcli sudo proposals
"""
self.verbosity_handler(quiet, verbose)
return self._run_command(sudo.proposals(self.initialize_chain(network)))
return self._run_command(
sudo.proposals(self.initialize_chain(network), verbose)
)

def sudo_senate_vote(
self,
Expand Down
29 changes: 29 additions & 0 deletions bittensor_cli/src/bittensor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,3 +1355,32 @@ def hex_to_bytes(hex_str: str) -> bytes:
else:
bytes_result = bytes.fromhex(hex_str)
return bytes_result


def blocks_to_duration(blocks: int) -> str:
"""Convert blocks to human readable duration string using two largest units.
Args:
blocks (int): Number of blocks (12s per block)
Returns:
str: Duration string like '2d 5h', '3h 45m', '2m 10s', or '0s'
"""
if blocks <= 0:
return "0s"

seconds = blocks * 12
intervals = [
("d", 86400), # 60 * 60 * 24
("h", 3600), # 60 * 60
("m", 60),
("s", 1),
]
results = []
for unit, seconds_per_unit in intervals:
unit_count = seconds // seconds_per_unit
seconds %= seconds_per_unit
if unit_count > 0:
results.append(f"{unit_count}{unit}")
# Return only the first two non-zero units
return " ".join(results[:2]) or "0s"
4 changes: 2 additions & 2 deletions bittensor_cli/src/commands/stake/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ async def safe_stake_extrinsic(
return
else:
err_out(
f"\n{failure_prelude} with error: {format_error_message(e, subtensor.substrate)}"
f"\n{failure_prelude} with error: {format_error_message(e)}"
)
return
else:
Expand Down Expand Up @@ -181,7 +181,7 @@ async def stake_extrinsic(
)
except SubstrateRequestException as e:
err_out(
f"\n{failure_prelude} with error: {format_error_message(e, subtensor.substrate)}"
f"\n{failure_prelude} with error: {format_error_message(e)}"
)
return
else:
Expand Down
2 changes: 1 addition & 1 deletion bittensor_cli/src/commands/stake/remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ async def _safe_unstake_extrinsic(
return
else:
err_out(
f"\n{failure_prelude} with error: {format_error_message(e, subtensor.substrate)}"
f"\n{failure_prelude} with error: {format_error_message(e)}"
)
return

Expand Down
69 changes: 52 additions & 17 deletions bittensor_cli/src/commands/sudo.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
print_verbose,
normalize_hyperparameters,
unlock_key,
blocks_to_duration,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -269,14 +270,22 @@ def format_call_data(call_data: dict) -> str:
call_info = call_details[0]
call_function, call_args = next(iter(call_info.items()))

# Extract the argument, handling tuple values
formatted_args = ", ".join(
str(arg[0]) if isinstance(arg, tuple) else str(arg)
for arg in call_args.values()
)
# Format arguments, handle nested/large payloads
formatted_args = []
for arg_name, arg_value in call_args.items():
if isinstance(arg_value, (tuple, list, dict)):
# For large nested, show abbreviated version
content_str = str(arg_value)
if len(content_str) > 20:
formatted_args.append(f"{arg_name}: ... [{len(content_str)}] ...")
else:
formatted_args.append(f"{arg_name}: {arg_value}")
else:
formatted_args.append(f"{arg_name}: {arg_value}")

# Format the final output string
return f"{call_function}({formatted_args})"
args_str = ", ".join(formatted_args)
return f"{module}.{call_function}({args_str})"


def _validate_proposal_hash(proposal_hash: str) -> bool:
Expand Down Expand Up @@ -576,24 +585,30 @@ async def get_senate(subtensor: "SubtensorInterface"):
return console.print(table)


async def proposals(subtensor: "SubtensorInterface"):
async def proposals(subtensor: "SubtensorInterface", verbose: bool):
console.print(
":satellite: Syncing with chain: [white]{}[/white] ...".format(
subtensor.network
)
)
print_verbose("Fetching senate members & proposals")
block_hash = await subtensor.substrate.get_chain_head()
senate_members, all_proposals = await asyncio.gather(
senate_members, all_proposals, current_block = await asyncio.gather(
_get_senate_members(subtensor, block_hash),
_get_proposals(subtensor, block_hash),
subtensor.substrate.get_block_number(block_hash),
)

print_verbose("Fetching member information from Chain")
registered_delegate_info: dict[
str, DelegatesDetails
] = await subtensor.get_delegate_identities()

title = (
f"[bold #4196D6]Bittensor Governance Proposals[/bold #4196D6]\n"
f"[steel_blue3]Current Block:[/steel_blue3] {current_block}\t"
f"[steel_blue3]Network:[/steel_blue3] {subtensor.network}\n\n"
f"[steel_blue3]Active Proposals:[/steel_blue3] {len(all_proposals)}\t"
f"[steel_blue3]Senate Size:[/steel_blue3] {len(senate_members)}\n"
)
table = Table(
Column(
"[white]HASH",
Expand All @@ -608,25 +623,45 @@ async def proposals(subtensor: "SubtensorInterface"):
style="rgb(50,163,219)",
),
Column("[white]END", style="bright_cyan"),
Column("[white]CALLDATA", style="dark_sea_green"),
title=f"\n[dark_orange]Proposals\t\t\nActive Proposals: {len(all_proposals)}\t\tSenate Size: {len(senate_members)}\nNetwork: {subtensor.network}",
Column("[white]CALLDATA", style="dark_sea_green", width=30),
title=title,
show_footer=True,
box=box.SIMPLE_HEAVY,
pad_edge=False,
width=None,
border_style="bright_black",
)
for hash_, (call_data, vote_data) in all_proposals.items():
blocks_remaining = vote_data.end - current_block
if blocks_remaining > 0:
duration_str = blocks_to_duration(blocks_remaining)
vote_end_cell = f"{vote_data.end} [dim](in {duration_str})[/dim]"
else:
vote_end_cell = f"{vote_data.end} [red](expired)[/red]"

ayes_threshold = (
(len(vote_data.ayes) / vote_data.threshold * 100)
if vote_data.threshold > 0
else 0
)
nays_threshold = (
(len(vote_data.nays) / vote_data.threshold * 100)
if vote_data.threshold > 0
else 0
)
table.add_row(
hash_,
hash_ if verbose else f"{hash_[:4]}...{hash_[-4:]}",
str(vote_data.threshold),
str(len(vote_data.ayes)),
str(len(vote_data.nays)),
f"{len(vote_data.ayes)} ({ayes_threshold:.2f}%)",
f"{len(vote_data.nays)} ({nays_threshold:.2f}%)",
display_votes(vote_data, registered_delegate_info),
str(vote_data.end),
vote_end_cell,
format_call_data(call_data),
)
return console.print(table)
console.print(table)
console.print(
"\n[dim]* Both Ayes and Nays percentages are calculated relative to the proposal's threshold.[/dim]"
)


async def senate_vote(
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
wheel
async-property==0.2.2
async-substrate-interface>=1.0.0rc14
async-substrate-interface>=1.0.0
aiohttp~=3.10.2
backoff~=2.2.1
GitPython>=3.0.0
Expand All @@ -16,7 +16,7 @@ rich~=13.7
scalecodec==1.2.11
typer~=0.12
websockets>=14.1
bittensor-wallet>=3.0.2
bittensor-wallet>=3.0.3
plotille
pywry
plotly
21 changes: 12 additions & 9 deletions tests/e2e_tests/test_senate.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ def test_senate(local_chain, wallet_setup):
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
"--verbose",
],
)
proposals_output = proposals.stdout.splitlines()[8].split()
proposals_output = proposals.stdout.splitlines()[9].split()

# Assert the hash is of correct format
assert len(proposals_output[0]) == 66
Expand All @@ -112,7 +113,7 @@ def test_senate(local_chain, wallet_setup):
assert proposals_output[2] == "0"

# 0 Nayes for the proposal
assert proposals_output[3] == "0"
assert proposals_output[4] == "0"

# Assert initial threshold is 3
assert proposals_output[1] == "3"
Expand Down Expand Up @@ -145,19 +146,20 @@ def test_senate(local_chain, wallet_setup):
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
"--verbose",
],
)
proposals_after_aye_output = proposals_after_aye.stdout.splitlines()[8].split()
proposals_after_aye_output = proposals_after_aye.stdout.splitlines()[9].split()

# Assert Bob's vote is shown as aye
assert proposals_after_aye_output[4].strip(":") == wallet_bob.hotkey.ss58_address
assert proposals_after_aye_output[5] == "Aye"
assert proposals_after_aye_output[6].strip(":") == wallet_bob.hotkey.ss58_address
assert proposals_after_aye_output[7] == "Aye"

# Aye votes increased to 1
assert proposals_after_aye_output[2] == "1"

# Nay votes remain 0
assert proposals_after_aye_output[3] == "0"
assert proposals_after_aye_output[4] == "0"

# Register Alice to the root network (0)
# Registering to root automatically makes you a senator if eligible
Expand Down Expand Up @@ -208,18 +210,19 @@ def test_senate(local_chain, wallet_setup):
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
"--verbose",
],
)
proposals_after_nay_output = proposals_after_nay.stdout.splitlines()

# Total Ayes to remain 1
proposals_after_nay_output[8].split()[2] == "1"
proposals_after_nay_output[9].split()[2] == "1"

# Total Nays increased to 1
proposals_after_nay_output[8].split()[3] == "1"
proposals_after_nay_output[9].split()[4] == "1"

# Assert Alice has voted Nay
proposals_after_nay_output[9].split()[0].strip(
proposals_after_nay_output[10].split()[0].strip(
":"
) == wallet_alice.hotkey.ss58_address

Expand Down

0 comments on commit dba6c85

Please sign in to comment.