Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 18 additions & 39 deletions bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7344,11 +7344,6 @@ def liquidity_add(
wallet_path: str = Options.wallet_path,
wallet_hotkey: str = Options.wallet_hotkey,
netuid: Optional[int] = Options.netuid,
liquidity_: Optional[float] = typer.Option(
None,
"--liquidity",
help="Amount of liquidity to add to the subnet.",
),
price_low: Optional[float] = typer.Option(
None,
"--price-low",
Expand All @@ -7365,67 +7360,51 @@ def liquidity_add(
"--liquidity_price_high",
help="High price for the adding liquidity position.",
),
tao_amount: Optional[float] = typer.Option(
None,
"--tao-amount",
"--tao_amount",
help="Amount of TAO to provide (for mixed range positions).",
),
alpha_amount: Optional[float] = typer.Option(
None,
"--alpha-amount",
"--alpha_amount",
help="Amount of Alpha to provide (for mixed range positions).",
),
prompt: bool = Options.prompt,
quiet: bool = Options.quiet,
verbose: bool = Options.verbose,
json_output: bool = Options.json_output,
):
"""Add liquidity to the swap (as a combination of TAO + Alpha)."""
self.verbosity_handler(quiet, verbose, json_output)

# Step 1: Ask for netuid
if not netuid:
netuid = Prompt.ask(
f"Enter the [{COLORS.G.SUBHEAD_MAIN}]netuid[/{COLORS.G.SUBHEAD_MAIN}] to use",
default=None,
show_default=False,
)

wallet, hotkey = self.wallet_ask(
wallet = self.wallet_ask(
wallet_name=wallet_name,
wallet_path=wallet_path,
wallet_hotkey=wallet_hotkey,
ask_for=[WO.NAME, WO.HOTKEY, WO.PATH],
validate=WV.WALLET,
return_wallet_and_hotkey=True,
)
# Determine the liquidity amount.
if liquidity_:
liquidity_ = Balance.from_tao(liquidity_)
else:
liquidity_ = prompt_liquidity("Enter the amount of liquidity")

# Determine price range
if price_low:
price_low = Balance.from_tao(price_low)
else:
price_low = prompt_liquidity("Enter liquidity position low price")

if price_high:
price_high = Balance.from_tao(price_high)
else:
price_high = prompt_liquidity(
"Enter liquidity position high price (must be greater than low price)"
)

if price_low >= price_high:
err_console.print("The low price must be lower than the high price.")
return False
logger.debug(
f"args:\n"
f"hotkey: {hotkey}\n"
f"netuid: {netuid}\n"
f"liquidity: {liquidity_}\n"
f"price_low: {price_low}\n"
f"price_high: {price_high}\n"
)
return self._run_command(
liquidity.add_liquidity(
liquidity.add_liquidity_interactive(
subtensor=self.initialize_chain(network),
wallet=wallet,
hotkey_ss58=hotkey,
netuid=netuid,
liquidity=liquidity_,
price_low=price_low,
price_high=price_high,
tao_amount=tao_amount,
alpha_amount=alpha_amount,
prompt=prompt,
json_output=json_output,
)
Expand Down
211 changes: 211 additions & 0 deletions bittensor_cli/src/bittensor/extrinsics/liquidity.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still no respect for --no-prompt

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think extrinsic function doesn't accept prompt, let me know if I am wrong

async def add_liquidity_extrinsic(
subtensor: "SubtensorInterface",

Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
from typing import TYPE_CHECKING, Optional

from async_substrate_interface import AsyncExtrinsicReceipt

from bittensor_cli.src.bittensor.utils import unlock_key
from bittensor_cli.src.bittensor.balances import Balance
from bittensor_cli.src.commands.liquidity.utils import price_to_tick

if TYPE_CHECKING:
from bittensor_wallet import Wallet
from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface


async def add_liquidity_extrinsic(
subtensor: "SubtensorInterface",
wallet: "Wallet",
hotkey_ss58: str,
netuid: int,
liquidity: Balance,
price_low: Balance,
price_high: Balance,
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
) -> tuple[bool, str, Optional[AsyncExtrinsicReceipt]]:
"""
Adds liquidity to the specified price range.

Arguments:
subtensor: The Subtensor client instance used for blockchain interaction.
wallet: The wallet used to sign the extrinsic (must be unlocked).
hotkey_ss58: the SS58 of the hotkey to use for this transaction.
netuid: The UID of the target subnet for which the call is being initiated.
liquidity: The amount of liquidity to be added.
price_low: The lower bound of the price tick range.
price_high: The upper bound of the price tick range.
wait_for_inclusion: Whether to wait for the extrinsic to be included in a block. Defaults to True.
wait_for_finalization: Whether to wait for finalization of the extrinsic. Defaults to False.

Returns:
Tuple[bool, str]:
- True and a success message if the extrinsic is successfully submitted or processed.
- False and an error message if the submission fails or the wallet cannot be unlocked.

Note: Adding is allowed even when user liquidity is enabled in specified subnet. Call
`toggle_user_liquidity_extrinsic` to enable/disable user liquidity.
"""
if not (unlock := unlock_key(wallet)).success:
return False, unlock.message, None

tick_low = price_to_tick(price_low.tao)
tick_high = price_to_tick(price_high.tao)

call = await subtensor.substrate.compose_call(
call_module="Swap",
call_function="add_liquidity",
call_params={
"hotkey": hotkey_ss58,
"netuid": netuid,
"tick_low": tick_low,
"tick_high": tick_high,
"liquidity": liquidity.rao,
},
)

return await subtensor.sign_and_send_extrinsic(
call=call,
wallet=wallet,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)


async def modify_liquidity_extrinsic(
subtensor: "SubtensorInterface",
wallet: "Wallet",
hotkey_ss58: str,
netuid: int,
position_id: int,
liquidity_delta: Balance,
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
) -> tuple[bool, str, Optional[AsyncExtrinsicReceipt]]:
"""Modifies liquidity in liquidity position by adding or removing liquidity from it.

Arguments:
subtensor: The Subtensor client instance used for blockchain interaction.
wallet: The wallet used to sign the extrinsic (must be unlocked).
hotkey_ss58: the SS58 of the hotkey to use for this transaction.
netuid: The UID of the target subnet for which the call is being initiated.
position_id: The id of the position record in the pool.
liquidity_delta: The amount of liquidity to be added or removed (add if positive or remove if negative).
wait_for_inclusion: Whether to wait for the extrinsic to be included in a block. Defaults to True.
wait_for_finalization: Whether to wait for finalization of the extrinsic. Defaults to False.

Returns:
Tuple[bool, str]:
- True and a success message if the extrinsic is successfully submitted or processed.
- False and an error message if the submission fails or the wallet cannot be unlocked.

Note: Modifying is allowed even when user liquidity is enabled in specified subnet.
Call `toggle_user_liquidity_extrinsic` to enable/disable user liquidity.
"""
if not (unlock := unlock_key(wallet)).success:
return False, unlock.message, None

call = await subtensor.substrate.compose_call(
call_module="Swap",
call_function="modify_position",
call_params={
"hotkey": hotkey_ss58,
"netuid": netuid,
"position_id": position_id,
"liquidity_delta": liquidity_delta.rao,
},
)

return await subtensor.sign_and_send_extrinsic(
call=call,
wallet=wallet,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)


async def remove_liquidity_extrinsic(
subtensor: "SubtensorInterface",
wallet: "Wallet",
hotkey_ss58: str,
netuid: int,
position_id: int,
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
) -> tuple[bool, str, Optional[AsyncExtrinsicReceipt]]:
"""Remove liquidity and credit balances back to wallet's hotkey stake.

Arguments:
subtensor: The Subtensor client instance used for blockchain interaction.
wallet: The wallet used to sign the extrinsic (must be unlocked).
hotkey_ss58: the SS58 of the hotkey to use for this transaction.
netuid: The UID of the target subnet for which the call is being initiated.
position_id: The id of the position record in the pool.
wait_for_inclusion: Whether to wait for the extrinsic to be included in a block. Defaults to True.
wait_for_finalization: Whether to wait for finalization of the extrinsic. Defaults to False.

Returns:
Tuple[bool, str]:
- True and a success message if the extrinsic is successfully submitted or processed.
- False and an error message if the submission fails or the wallet cannot be unlocked.

Note: Adding is allowed even when user liquidity is enabled in specified subnet.
Call `toggle_user_liquidity_extrinsic` to enable/disable user liquidity.
"""
if not (unlock := unlock_key(wallet)).success:
return False, unlock.message, None

call = await subtensor.substrate.compose_call(
call_module="Swap",
call_function="remove_liquidity",
call_params={
"hotkey": hotkey_ss58,
"netuid": netuid,
"position_id": position_id,
},
)

return await subtensor.sign_and_send_extrinsic(
call=call,
wallet=wallet,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)


async def toggle_user_liquidity_extrinsic(
subtensor: "SubtensorInterface",
wallet: "Wallet",
netuid: int,
enable: bool,
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
) -> tuple[bool, str, Optional[AsyncExtrinsicReceipt]]:
"""Allow to toggle user liquidity for specified subnet.

Arguments:
subtensor: The Subtensor client instance used for blockchain interaction.
wallet: The wallet used to sign the extrinsic (must be unlocked).
netuid: The UID of the target subnet for which the call is being initiated.
enable: Boolean indicating whether to enable user liquidity.
wait_for_inclusion: Whether to wait for the extrinsic to be included in a block. Defaults to True.
wait_for_finalization: Whether to wait for finalization of the extrinsic. Defaults to False.

Returns:
Tuple[bool, str]:
- True and a success message if the extrinsic is successfully submitted or processed.
- False and an error message if the submission fails or the wallet cannot be unlocked.
"""
if not (unlock := unlock_key(wallet)).success:
return False, unlock.message, None

call = await subtensor.substrate.compose_call(
call_module="Swap",
call_function="toggle_user_liquidity",
call_params={"netuid": netuid, "enable": enable},
)

return await subtensor.sign_and_send_extrinsic(
call=call,
wallet=wallet,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)
Loading