Skip to content

Commit 40127cd

Browse files
committed
Adds safe to stake swap
1 parent 945355c commit 40127cd

File tree

1 file changed

+49
-13
lines changed

1 file changed

+49
-13
lines changed

bittensor/core/extrinsics/move_stake.py

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ def swap_stake_extrinsic(
157157
amount: Optional[Balance] = None,
158158
wait_for_inclusion: bool = True,
159159
wait_for_finalization: bool = False,
160+
safe_staking: bool = False,
161+
allow_partial_stake: bool = False,
162+
rate_threshold: float = 0.005,
160163
) -> bool:
161164
"""
162165
Moves stake between subnets while keeping the same coldkey-hotkey pair ownership.
@@ -170,6 +173,9 @@ def swap_stake_extrinsic(
170173
amount (Union[Balance, float]): Amount to swap.
171174
wait_for_inclusion (bool): If true, waits for inclusion before returning.
172175
wait_for_finalization (bool): If true, waits for finalization before returning.
176+
safe_staking (bool): If true, enables price safety checks to protect against price impact.
177+
allow_partial_stake (bool): If true, allows partial stake swaps when the full amount would exceed the price threshold.
178+
rate_threshold (float): Maximum allowed increase in price ratio (0.005 = 0.5%).
173179
174180
Returns:
175181
success (bool): True if the swap was successful.
@@ -203,20 +209,45 @@ def swap_stake_extrinsic(
203209
return False
204210

205211
try:
206-
logging.info(
207-
f"Swapping stake for hotkey [blue]{hotkey_ss58}[/blue]\n"
208-
f"Amount: [green]{amount}[/green] from netuid [yellow]{origin_netuid}[/yellow] to netuid "
209-
f"[yellow]{destination_netuid}[/yellow]"
210-
)
212+
call_params = {
213+
"hotkey": hotkey_ss58,
214+
"origin_netuid": origin_netuid,
215+
"destination_netuid": destination_netuid,
216+
"alpha_amount": amount.rao,
217+
}
218+
219+
if safe_staking:
220+
origin_pool = subtensor.subnet(netuid=origin_netuid)
221+
destination_pool = subtensor.subnet(netuid=destination_netuid)
222+
swap_rate_ratio = origin_pool.price.rao / destination_pool.price.rao
223+
swap_rate_ratio_with_tolerance = swap_rate_ratio * (1 + rate_threshold)
224+
225+
logging.info(
226+
f"Swapping stake with safety for hotkey [blue]{hotkey_ss58}[/blue]\n"
227+
f"Amount: [green]{amount}[/green] from netuid [yellow]{origin_netuid}[/yellow] to netuid "
228+
f"[yellow]{destination_netuid}[/yellow]\n"
229+
f"Current price ratio: [green]{swap_rate_ratio:.4f}[/green], "
230+
f"Ratio with tolerance: [yellow]{swap_rate_ratio_with_tolerance:.4f}[/yellow]"
231+
)
232+
call_params.update(
233+
{
234+
"limit_price": swap_rate_ratio_with_tolerance,
235+
"allow_partial": allow_partial_stake,
236+
}
237+
)
238+
call_function = "swap_stake_limit"
239+
else:
240+
logging.info(
241+
f"Swapping stake for hotkey [blue]{hotkey_ss58}[/blue]\n"
242+
f"Amount: [green]{amount}[/green] from netuid [yellow]{origin_netuid}[/yellow] to netuid "
243+
f"[yellow]{destination_netuid}[/yellow]"
244+
)
245+
call_function = "swap_stake"
246+
211247
call = subtensor.substrate.compose_call(
212248
call_module="SubtensorModule",
213-
call_function="swap_stake",
214-
call_params={
215-
"hotkey": hotkey_ss58,
216-
"origin_netuid": origin_netuid,
217-
"destination_netuid": destination_netuid,
218-
"alpha_amount": amount.rao,
219-
},
249+
call_function=call_function,
250+
call_params=call_params,
220251
)
221252

222253
success, err_msg = subtensor.sign_and_send_extrinsic(
@@ -251,7 +282,12 @@ def swap_stake_extrinsic(
251282

252283
return True
253284
else:
254-
logging.error(f":cross_mark: [red]Failed[/red]: {err_msg}")
285+
if safe_staking and "Custom error: 8" in err_msg:
286+
logging.error(
287+
":cross_mark: [red]Failed[/red]: Price ratio exceeded tolerance limit. Either increase price tolerance or enable partial staking."
288+
)
289+
else:
290+
logging.error(f":cross_mark: [red]Failed[/red]: {err_msg}")
255291
return False
256292

257293
except Exception as e:

0 commit comments

Comments
 (0)