bittensor-cli 9.2.0__py3-none-any.whl → 9.4.0__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.
@@ -1,4 +1,6 @@
1
1
  import asyncio
2
+ import json
3
+ from collections import defaultdict
2
4
  from functools import partial
3
5
 
4
6
  from typing import TYPE_CHECKING, Optional
@@ -17,6 +19,7 @@ from bittensor_cli.src.bittensor.utils import (
17
19
  print_error,
18
20
  print_verbose,
19
21
  unlock_key,
22
+ json_console,
20
23
  )
21
24
  from bittensor_wallet import Wallet
22
25
 
@@ -38,6 +41,8 @@ async def stake_add(
38
41
  safe_staking: bool,
39
42
  rate_tolerance: float,
40
43
  allow_partial_stake: bool,
44
+ json_output: bool,
45
+ era: int,
41
46
  ):
42
47
  """
43
48
  Args:
@@ -53,6 +58,8 @@ async def stake_add(
53
58
  safe_staking: whether to use safe staking
54
59
  rate_tolerance: rate tolerance percentage for stake operations
55
60
  allow_partial_stake: whether to allow partial stake
61
+ json_output: whether to output stake info in JSON format
62
+ era: Blocks for which the transaction should be valid.
56
63
 
57
64
  Returns:
58
65
  bool: True if stake operation is successful, False otherwise
@@ -65,28 +72,31 @@ async def stake_add(
65
72
  hotkey_ss58_: str,
66
73
  price_limit: Balance,
67
74
  status=None,
68
- ) -> None:
75
+ ) -> bool:
69
76
  err_out = partial(print_error, status=status)
70
77
  failure_prelude = (
71
78
  f":cross_mark: [red]Failed[/red] to stake {amount_} on Netuid {netuid_}"
72
79
  )
73
- current_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
74
- next_nonce = await subtensor.substrate.get_account_next_index(
75
- wallet.coldkeypub.ss58_address
76
- )
77
- call = await subtensor.substrate.compose_call(
78
- call_module="SubtensorModule",
79
- call_function="add_stake_limit",
80
- call_params={
81
- "hotkey": hotkey_ss58_,
82
- "netuid": netuid_,
83
- "amount_staked": amount_.rao,
84
- "limit_price": price_limit,
85
- "allow_partial": allow_partial_stake,
86
- },
80
+ current_balance, next_nonce, call = await asyncio.gather(
81
+ subtensor.get_balance(wallet.coldkeypub.ss58_address),
82
+ subtensor.substrate.get_account_next_index(wallet.coldkeypub.ss58_address),
83
+ subtensor.substrate.compose_call(
84
+ call_module="SubtensorModule",
85
+ call_function="add_stake_limit",
86
+ call_params={
87
+ "hotkey": hotkey_ss58_,
88
+ "netuid": netuid_,
89
+ "amount_staked": amount_.rao,
90
+ "limit_price": price_limit,
91
+ "allow_partial": allow_partial_stake,
92
+ },
93
+ ),
87
94
  )
88
95
  extrinsic = await subtensor.substrate.create_signed_extrinsic(
89
- call=call, keypair=wallet.coldkey, nonce=next_nonce
96
+ call=call,
97
+ keypair=wallet.coldkey,
98
+ nonce=next_nonce,
99
+ era={"period": era},
90
100
  )
91
101
  try:
92
102
  response = await subtensor.substrate.submit_extrinsic(
@@ -100,73 +110,80 @@ async def stake_add(
100
110
  f"Either increase price tolerance or enable partial staking.",
101
111
  status=status,
102
112
  )
103
- return
113
+ return False
104
114
  else:
105
115
  err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
106
- return
116
+ return False
117
+ if not await response.is_success:
118
+ err_out(
119
+ f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
120
+ )
121
+ return False
107
122
  else:
108
- await response.process_events()
109
- if not await response.is_success:
110
- err_out(
111
- f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
112
- )
113
- else:
114
- block_hash = await subtensor.substrate.get_chain_head()
115
- new_balance, new_stake = await asyncio.gather(
116
- subtensor.get_balance(wallet.coldkeypub.ss58_address, block_hash),
117
- subtensor.get_stake(
118
- hotkey_ss58=hotkey_ss58_,
119
- coldkey_ss58=wallet.coldkeypub.ss58_address,
120
- netuid=netuid_,
121
- block_hash=block_hash,
122
- ),
123
- )
124
- console.print(
125
- f":white_heavy_check_mark: [dark_sea_green3]Finalized. Stake added to netuid: {netuid_}[/dark_sea_green3]"
126
- )
127
- console.print(
128
- f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
129
- )
130
-
131
- amount_staked = current_balance - new_balance
132
- if allow_partial_stake and (amount_staked != amount_):
133
- console.print(
134
- "Partial stake transaction. Staked:\n"
135
- f" [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{amount_staked}[/{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}] "
136
- f"instead of "
137
- f"[blue]{amount_}[/blue]"
138
- )
123
+ if json_output:
124
+ # the rest of this checking is not necessary if using json_output
125
+ return True
126
+ block_hash = await subtensor.substrate.get_chain_head()
127
+ new_balance, new_stake = await asyncio.gather(
128
+ subtensor.get_balance(wallet.coldkeypub.ss58_address, block_hash),
129
+ subtensor.get_stake(
130
+ hotkey_ss58=hotkey_ss58_,
131
+ coldkey_ss58=wallet.coldkeypub.ss58_address,
132
+ netuid=netuid_,
133
+ block_hash=block_hash,
134
+ ),
135
+ )
136
+ console.print(
137
+ f":white_heavy_check_mark: [dark_sea_green3]Finalized. "
138
+ f"Stake added to netuid: {netuid_}[/dark_sea_green3]"
139
+ )
140
+ console.print(
141
+ f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: "
142
+ f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
143
+ )
139
144
 
145
+ amount_staked = current_balance - new_balance
146
+ if allow_partial_stake and (amount_staked != amount_):
140
147
  console.print(
141
- f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid_}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
142
- f"Stake:\n"
143
- f" [blue]{current_stake}[/blue] "
144
- f":arrow_right: "
145
- f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_stake}\n"
148
+ "Partial stake transaction. Staked:\n"
149
+ f" [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{amount_staked}"
150
+ f"[/{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}] "
151
+ f"instead of "
152
+ f"[blue]{amount_}[/blue]"
146
153
  )
147
154
 
155
+ console.print(
156
+ f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]"
157
+ f"{netuid_}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
158
+ f"Stake:\n"
159
+ f" [blue]{current_stake}[/blue] "
160
+ f":arrow_right: "
161
+ f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_stake}\n"
162
+ )
163
+ return True
164
+
148
165
  async def stake_extrinsic(
149
166
  netuid_i, amount_, current, staking_address_ss58, status=None
150
- ):
167
+ ) -> bool:
151
168
  err_out = partial(print_error, status=status)
152
- current_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
169
+ current_balance, next_nonce, call = await asyncio.gather(
170
+ subtensor.get_balance(wallet.coldkeypub.ss58_address),
171
+ subtensor.substrate.get_account_next_index(wallet.coldkeypub.ss58_address),
172
+ subtensor.substrate.compose_call(
173
+ call_module="SubtensorModule",
174
+ call_function="add_stake",
175
+ call_params={
176
+ "hotkey": staking_address_ss58,
177
+ "netuid": netuid_i,
178
+ "amount_staked": amount_.rao,
179
+ },
180
+ ),
181
+ )
153
182
  failure_prelude = (
154
183
  f":cross_mark: [red]Failed[/red] to stake {amount} on Netuid {netuid_i}"
155
184
  )
156
- next_nonce = await subtensor.substrate.get_account_next_index(
157
- wallet.coldkeypub.ss58_address
158
- )
159
- call = await subtensor.substrate.compose_call(
160
- call_module="SubtensorModule",
161
- call_function="add_stake",
162
- call_params={
163
- "hotkey": staking_address_ss58,
164
- "netuid": netuid_i,
165
- "amount_staked": amount_.rao,
166
- },
167
- )
168
185
  extrinsic = await subtensor.substrate.create_signed_extrinsic(
169
- call=call, keypair=wallet.coldkey, nonce=next_nonce
186
+ call=call, keypair=wallet.coldkey, nonce=next_nonce, era={"period": era}
170
187
  )
171
188
  try:
172
189
  response = await subtensor.substrate.submit_extrinsic(
@@ -174,35 +191,46 @@ async def stake_add(
174
191
  )
175
192
  except SubstrateRequestException as e:
176
193
  err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
177
- return
194
+ return False
178
195
  else:
179
- await response.process_events()
180
196
  if not await response.is_success:
181
197
  err_out(
182
198
  f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
183
199
  )
200
+ return False
184
201
  else:
202
+ if json_output:
203
+ # the rest of this is not necessary if using json_output
204
+ return True
205
+ new_block_hash = await subtensor.substrate.get_chain_head()
185
206
  new_balance, new_stake = await asyncio.gather(
186
- subtensor.get_balance(wallet.coldkeypub.ss58_address),
207
+ subtensor.get_balance(
208
+ wallet.coldkeypub.ss58_address, block_hash=new_block_hash
209
+ ),
187
210
  subtensor.get_stake(
188
211
  hotkey_ss58=staking_address_ss58,
189
212
  coldkey_ss58=wallet.coldkeypub.ss58_address,
190
213
  netuid=netuid_i,
214
+ block_hash=new_block_hash,
191
215
  ),
192
216
  )
193
217
  console.print(
194
- f":white_heavy_check_mark: [dark_sea_green3]Finalized. Stake added to netuid: {netuid_i}[/dark_sea_green3]"
218
+ f":white_heavy_check_mark: "
219
+ f"[dark_sea_green3]Finalized. Stake added to netuid: {netuid_i}[/dark_sea_green3]"
195
220
  )
196
221
  console.print(
197
- f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
222
+ f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: "
223
+ f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
198
224
  )
199
225
  console.print(
200
- f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid_i}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
226
+ f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]"
227
+ f"{netuid_i}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
201
228
  f"Stake:\n"
202
229
  f" [blue]{current}[/blue] "
203
230
  f":arrow_right: "
204
231
  f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_stake}\n"
205
232
  )
233
+ return True
206
234
 
207
235
  netuids = (
208
236
  [int(netuid)]
@@ -333,7 +361,9 @@ async def stake_add(
333
361
  base_row.extend(
334
362
  [
335
363
  f"{rate_with_tolerance} {Balance.get_unit(netuid)}/{Balance.get_unit(0)} ",
336
- f"[{'dark_sea_green3' if allow_partial_stake else 'red'}]{allow_partial_stake}[/{'dark_sea_green3' if allow_partial_stake else 'red'}]", # safe staking
364
+ f"[{'dark_sea_green3' if allow_partial_stake else 'red'}]"
365
+ # safe staking
366
+ f"{allow_partial_stake}[/{'dark_sea_green3' if allow_partial_stake else 'red'}]",
337
367
  ]
338
368
  )
339
369
 
@@ -352,7 +382,7 @@ async def stake_add(
352
382
  return False
353
383
 
354
384
  if safe_staking:
355
- stake_coroutines = []
385
+ stake_coroutines = {}
356
386
  for i, (ni, am, curr, price_with_tolerance) in enumerate(
357
387
  zip(
358
388
  netuids, amounts_to_stake, current_stake_balances, prices_with_tolerance
@@ -361,27 +391,23 @@ async def stake_add(
361
391
  for _, staking_address in hotkeys_to_stake_to:
362
392
  # Regular extrinsic for root subnet
363
393
  if ni == 0:
364
- stake_coroutines.append(
365
- stake_extrinsic(
366
- netuid_i=ni,
367
- amount_=am,
368
- current=curr,
369
- staking_address_ss58=staking_address,
370
- )
394
+ stake_coroutines[(ni, staking_address)] = stake_extrinsic(
395
+ netuid_i=ni,
396
+ amount_=am,
397
+ current=curr,
398
+ staking_address_ss58=staking_address,
371
399
  )
372
400
  else:
373
- stake_coroutines.append(
374
- safe_stake_extrinsic(
375
- netuid_=ni,
376
- amount_=am,
377
- current_stake=curr,
378
- hotkey_ss58_=staking_address,
379
- price_limit=price_with_tolerance,
380
- )
401
+ stake_coroutines[(ni, staking_address)] = safe_stake_extrinsic(
402
+ netuid_=ni,
403
+ amount_=am,
404
+ current_stake=curr,
405
+ hotkey_ss58_=staking_address,
406
+ price_limit=price_with_tolerance,
381
407
  )
382
408
  else:
383
- stake_coroutines = [
384
- stake_extrinsic(
409
+ stake_coroutines = {
410
+ (ni, staking_address): stake_extrinsic(
385
411
  netuid_i=ni,
386
412
  amount_=am,
387
413
  current=curr,
@@ -391,12 +417,15 @@ async def stake_add(
391
417
  zip(netuids, amounts_to_stake, current_stake_balances)
392
418
  )
393
419
  for _, staking_address in hotkeys_to_stake_to
394
- ]
395
-
420
+ }
421
+ successes = defaultdict(dict)
396
422
  with console.status(f"\n:satellite: Staking on netuid(s): {netuids} ..."):
397
423
  # We can gather them all at once but balance reporting will be in race-condition.
398
- for coroutine in stake_coroutines:
399
- await coroutine
424
+ for (ni, staking_address), coroutine in stake_coroutines.items():
425
+ success = await coroutine
426
+ successes[ni][staking_address] = success
427
+ if json_output:
428
+ json_console.print(json.dumps({"staking_success": successes}))
400
429
 
401
430
 
402
431
  # Helper functions