Skip to content

Commit

Permalink
stake commands (#4)
Browse files Browse the repository at this point in the history
* `root list` working

* Fixed help output

* Fixed help output

* Fixed the way config for network/chain is handled.

* [WIP] Check-in. Pausing on setting weights until I determine whether we're doing the metagraph approach still.

* Root get-weights

* Circular import temp fix.

* Added root boost command. Not finished as I need to confirm the use of metagraph on it.

* Ruff

* Root boost and root set-weights.

* Code cleanup.

* Code cleanup.

* Feedback from PR #1

* Feedback from PR #1. Docstrings mostly.

* Final PR #1 suggestions I will be implementing.

* In the arena, trying things.

* Boost and Slash created with new logic to parse old weights. Confirming this logic is correct in Discord.

* Senate vote added

* Added `root senate` command.

* Root register command.

* Root proposals

* Root `set-take`

* Root `set-delegate`

* Root `undelegate-stake`

* Docstring.

* [WIP] Check-in

* [WIP] Check-in

* Root `my-delegates`

* Root `list-delegates`

* Root `nominate`, made extrinsics more general for signing and such.

* Ruff and Mypy

* Ruff and Mypy

* [WIP] Initial Commit for stake commands.

* `stake show` command working.

* Root commands (#3)

* `root list` working

* Fixed help output

* Fixed help output

* Fixed the way config for network/chain is handled.

* [WIP] Check-in. Pausing on setting weights until I determine whether we're doing the metagraph approach still.

* Root get-weights

* Circular import temp fix.

* Added root boost command. Not finished as I need to confirm the use of metagraph on it.

* Ruff

* Root boost and root set-weights.

* Code cleanup.

* Code cleanup.

* Feedback from PR #1

* Feedback from PR #1. Docstrings mostly.

* Final PR #1 suggestions I will be implementing.

* In the arena, trying things.

* Boost and Slash created with new logic to parse old weights. Confirming this logic is correct in Discord.

* Senate vote added

* Added `root senate` command.

* Root register command.

* Root proposals

* Root `set-take`

* Root `set-delegate`

* Root `undelegate-stake`

* Docstring.

* [WIP] Check-in

* [WIP] Check-in

* Root `my-delegates`

* Root `list-delegates`

* Root `nominate`, made extrinsics more general for signing and such.

* Ruff and Mypy

* Ruff and Mypy

* Corrected type registry change.

* `stake show` command working.

* `stake get-children` command

* `stake set-children` command

* Added commands to stake_app

* Exception handling and printing.

* Close subtensor.

* Added TODOs

* Fixed the list options in CLI. Began adding stake command.

* Update requirements.txt to use SSH instead of HTTPS for easier cloning

* Fixed interactive prompting and mypy issues.

* Fixed interactive prompting and mypy issues.

* Removed _take_extrinsic logic to the subtensor.sign_and_send_extrinsic method. Added the actual logic for doing the `root set-weights` command to its respective CLI command.

* Mypy

* `stake add` command

* Fixed vecu8

* `stake show` command

* PR Feedback — added docstrings.
  • Loading branch information
thewhaleking authored Aug 13, 2024
1 parent 0f27e30 commit a0e02ec
Show file tree
Hide file tree
Showing 8 changed files with 2,189 additions and 114 deletions.
515 changes: 473 additions & 42 deletions cli.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
aiohttp~=3.9.5
backoff~=2.2.1
git+https://github.com/opentensor/btwallet # bittensor_wallet
git+ssh://git@github.com/opentensor/btwallet.git # bittensor_wallet
GitPython>=3.0.0
fuzzywuzzy~=0.18.0
netaddr~=1.3.0
Expand Down
6 changes: 4 additions & 2 deletions src/bittensor/async_substrate_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,12 +533,14 @@ async def _preprocess(
metadata_pallet = self.substrate.metadata.get_metadata_pallet(module)

if not metadata_pallet:
raise Exception(f'Pallet "{module}" not found')
raise SubstrateRequestException(f'Pallet "{module}" not found')

storage_item = metadata_pallet.get_storage_function(storage_function)

if not metadata_pallet or not storage_item:
raise Exception(f'Storage function "{module}.{storage_function}" not found')
raise SubstrateRequestException(
f'Storage function "{module}.{storage_function}" not found'
)

# SCALE type string of value
param_types = storage_item.get_params_type_string()
Expand Down
3 changes: 3 additions & 0 deletions src/bittensor/balances.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ def __rich_rao__(self):
def __repr__(self):
return self.__str__()

def __bool__(self):
return self.rao != 0

def __eq__(self, other: Union[int, float, "Balance"]):
if other is None:
return False
Expand Down
99 changes: 40 additions & 59 deletions src/commands/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
err_console,
get_delegates_details_from_github,
convert_weight_uids_and_vals_to_tensor,
format_error_message,
ss58_to_vec_u8,
)
from src import Constants
Expand Down Expand Up @@ -110,7 +109,7 @@ async def _get_senate_members(

async def _get_proposals(
subtensor: SubtensorInterface, block_hash: str
) -> dict[ProposalVoteData, tuple[GenericCall, ProposalVoteData]]:
) -> dict[str, tuple[GenericCall, ProposalVoteData]]:
async def get_proposal_call_data(p_hash: str) -> Optional[GenericCall]:
proposal_data = await subtensor.substrate.query(
module="Triumvirate",
Expand All @@ -132,12 +131,13 @@ async def get_proposal_vote_data(p_hash: str) -> Optional[ProposalVoteData]:
params=None,
block_hash=block_hash,
)
proposal_hashes: Optional[ProposalVoteData] = getattr(
ph, "serialize", lambda: None
)()

if proposal_hashes is None:
return None
try:
proposal_hashes: list[str] = ph.serialize()
except AttributeError:
err_console.print("Unable to retrieve proposal vote data")
raise typer.Exit()

call_data_, vote_data_ = await asyncio.gather(
asyncio.gather(*[get_proposal_call_data(h) for h in proposal_hashes]),
asyncio.gather(*[get_proposal_vote_data(h) for h in proposal_hashes]),
Expand Down Expand Up @@ -250,28 +250,26 @@ async def vote_senate_extrinsic(
call, wallet, wait_for_inclusion, wait_for_finalization
)
if not success:
err_console.print(
f":cross_mark: [red]Failed[/red]: {format_error_message(err_msg)}"
)
err_console.print(f":cross_mark: [red]Failed[/red]: {err_msg}")
await asyncio.sleep(0.5)
return False

# Successful vote, final check for data
else:
vote_data = await _get_vote_data(subtensor, proposal_hash)
has_voted = (
vote_data["ayes"].count(wallet.hotkey.ss58_address) > 0
or vote_data["nays"].count(wallet.hotkey.ss58_address) > 0
)

if has_voted:
console.print(":white_heavy_check_mark: [green]Vote cast.[/green]")
return True
if vote_data := await _get_vote_data(subtensor, proposal_hash):
if (
vote_data["ayes"].count(wallet.hotkey.ss58_address) > 0
or vote_data["nays"].count(wallet.hotkey.ss58_address) > 0
):
console.print(":white_heavy_check_mark: [green]Vote cast.[/green]")
return True
else:
# hotkey not found in ayes/nays
err_console.print(
":cross_mark: [red]Unknown error. Couldn't find vote.[/red]"
)
return False
else:
# hotkey not found in ayes/nays
err_console.print(
":cross_mark: [red]Unknown error. Couldn't find vote.[/red]"
)
return False


Expand Down Expand Up @@ -347,7 +345,7 @@ async def burned_register_extrinsic(
"hotkey": wallet.hotkey.ss58_address,
},
)
success, err_msg = subtensor.sign_and_send_extrinsic(
success, err_msg = await subtensor.sign_and_send_extrinsic(
call, wallet, wait_for_inclusion, wait_for_finalization
)

Expand Down Expand Up @@ -423,25 +421,6 @@ async def _get_delegate_by_hotkey(ss58: str) -> Optional[DelegateInfo]:
else:
return DelegateInfo.from_vec_u8(result)

async def _take_extrinsic(call_) -> tuple[bool, str]:
"""Submits the previously-created extrinsic call to the chain"""
extrinsic = await subtensor.substrate.create_signed_extrinsic(
call=call_, keypair=wallet.coldkey
) # sign with coldkey
response = await subtensor.substrate.submit_extrinsic(
extrinsic,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)
# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
return True, ""
response.process_events()
if response.is_success:
return True, ""
else:
return False, format_error_message(response.error_message)

# Calculate u16 representation of the take
take_u16 = int(take * 0xFFFF)

Expand Down Expand Up @@ -471,7 +450,7 @@ async def _take_extrinsic(call_) -> tuple[bool, str]:
"take": take,
},
)
success, err = await _take_extrinsic(call)
success, err = await subtensor.sign_and_send_extrinsic(call, wallet)

else:
console.print("Current take is higher than the new one. Will use decrease_take")
Expand All @@ -486,7 +465,7 @@ async def _take_extrinsic(call_) -> tuple[bool, str]:
"take": take,
},
)
success, err = await _take_extrinsic(call)
success, err = await subtensor.sign_and_send_extrinsic(call, wallet)

if not success:
err_console.print(err)
Expand All @@ -498,8 +477,8 @@ async def _take_extrinsic(call_) -> tuple[bool, str]:
async def delegate_extrinsic(
subtensor: SubtensorInterface,
wallet: Wallet,
delegate_ss58: Optional[str] = None,
amount: Balance = None,
delegate_ss58: str,
amount: Balance,
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
prompt: bool = False,
Expand Down Expand Up @@ -602,7 +581,7 @@ async def get_stake_for_coldkey_and_hotkey(
# Stake it all.
staking_balance = Balance.from_tao(my_prev_coldkey_balance.tao)
else:
staking_balance = Balance.from_tao(amount)
staking_balance = amount

if delegate:
# Remove existential balance to keep key alive.
Expand Down Expand Up @@ -811,12 +790,12 @@ async def _get_list() -> tuple:
async def set_weights(
wallet: Wallet,
subtensor: SubtensorInterface,
netuids_: list[int],
weights_: list[float],
netuids: list[int],
weights: list[float],
):
"""Set weights for root network."""
netuids_ = np.array(netuids_, dtype=np.int64)
weights_ = np.array(weights_, dtype=np.float32)
netuids_ = np.array(netuids, dtype=np.int64)
weights_ = np.array(weights, dtype=np.float32)

# Run the set weights operation.
with console.status("Setting root weights..."):
Expand All @@ -842,7 +821,7 @@ async def get_weights(subtensor: SubtensorInterface):

await subtensor.substrate.close()

uid_to_weights = {}
uid_to_weights: dict[int, dict] = {}
netuids = set()
for matrix in weights:
[uid, weights_data] = matrix
Expand Down Expand Up @@ -1038,8 +1017,8 @@ async def get_senate(subtensor: SubtensorInterface):
async with subtensor:
senate_members = await _get_senate_members(subtensor)

delegate_info: Optional[
dict[str, DelegatesDetails]
delegate_info: dict[
str, DelegatesDetails
] = await get_delegates_details_from_github(Constants.delegates_detail_url)

await subtensor.substrate.close()
Expand Down Expand Up @@ -1214,7 +1193,7 @@ async def _do_set_take() -> bool:
err_console.print("ERROR: Take value should not exceed 18%")
return False

result: bool = set_take_extrinsic(
result: bool = await set_take_extrinsic(
subtensor=subtensor,
wallet=wallet,
delegate_ss58=wallet.hotkey.ss58_address,
Expand Down Expand Up @@ -1256,7 +1235,7 @@ async def _do_set_take() -> bool:
async def delegate_stake(
wallet: Wallet,
subtensor: SubtensorInterface,
amount: Optional[float],
amount: float,
delegate_ss58key: str,
):
"""Delegates stake to a chain delegate."""
Expand Down Expand Up @@ -1377,7 +1356,7 @@ async def wallet_to_delegates(
await subtensor.substrate.close()

for wall, delegates in wallets_with_delegates:
if not wall:
if not wall or not delegates:
continue

my_delegates_ = {} # hotkey, amount
Expand Down Expand Up @@ -1619,7 +1598,9 @@ async def nominate(wallet: Wallet, subtensor: SubtensorInterface):
return
else:
# Check if we are a delegate.
is_delegate: bool = subtensor.is_hotkey_delegate(wallet.hotkey.ss58_address)
is_delegate: bool = await subtensor.is_hotkey_delegate(
wallet.hotkey.ss58_address
)
if not is_delegate:
err_console.print(
f"Could not became a delegate on [white]{subtensor.network}[/white]"
Expand Down
Loading

0 comments on commit a0e02ec

Please sign in to comment.