Skip to content

Commit f6f067a

Browse files
authored
Merge pull request #564 from opentensor/feat/thewhaleking/add-extrinsic-fees
Add extrinsic fees
2 parents e4732d8 + 96a3813 commit f6f067a

File tree

4 files changed

+311
-115
lines changed

4 files changed

+311
-115
lines changed

bittensor_cli/src/bittensor/subtensor_interface.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import aiohttp
66
from async_substrate_interface.utils.storage import StorageKey
77
from bittensor_wallet import Wallet
8+
from bittensor_wallet.bittensor_wallet import Keypair
89
from bittensor_wallet.utils import SS58_FORMAT
910
from scalecodec import GenericCall
1011
from async_substrate_interface.errors import SubstrateRequestException
@@ -1488,6 +1489,19 @@ async def get_owned_hotkeys(
14881489

14891490
return [decode_account_id(hotkey[0]) for hotkey in owned_hotkeys or []]
14901491

1492+
async def get_extrinsic_fee(self, call: GenericCall, keypair: Keypair) -> Balance:
1493+
"""
1494+
Determines the fee for the extrinsic call.
1495+
Args:
1496+
call: Created extrinsic call
1497+
keypair: The keypair that would sign the extrinsic (usually you would just want to use the *pub for this)
1498+
1499+
Returns:
1500+
Balance object representing the fee for this extrinsic.
1501+
"""
1502+
fee_dict = await self.substrate.get_payment_info(call, keypair)
1503+
return Balance.from_rao(fee_dict["partial_fee"])
1504+
14911505
async def get_stake_fee(
14921506
self,
14931507
origin_hotkey_ss58: Optional[str],

bittensor_cli/src/commands/stake/add.py

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,45 @@ async def stake_add(
6565
bool: True if stake operation is successful, False otherwise
6666
"""
6767

68+
async def get_stake_extrinsic_fee(
69+
netuid_: int,
70+
amount_: Balance,
71+
staking_address_: str,
72+
safe_staking_: bool,
73+
price_limit: Optional[Balance] = None,
74+
):
75+
"""
76+
Quick method to get the extrinsic fee for adding stake depending on the args supplied.
77+
Args:
78+
netuid_: The netuid where the stake will be added
79+
amount_: the amount of stake to add
80+
staking_address_: the hotkey ss58 to stake to
81+
safe_staking_: whether to use safe staking
82+
price_limit: rate with tolerance
83+
84+
Returns:
85+
Balance object representing the extrinsic fee for adding stake.
86+
"""
87+
call_fn = "add_stake" if not safe_staking_ else "add_stake_limit"
88+
call_params = {
89+
"hotkey": staking_address_,
90+
"netuid": netuid_,
91+
"amount_staked": amount_.rao,
92+
}
93+
if safe_staking_:
94+
call_params.update(
95+
{
96+
"limit_price": price_limit,
97+
"allow_partial": allow_partial_stake,
98+
}
99+
)
100+
call = await subtensor.substrate.compose_call(
101+
call_module="SubtensorModule",
102+
call_function=call_fn,
103+
call_params=call_params,
104+
)
105+
return await subtensor.get_extrinsic_fee(call, wallet.coldkeypub)
106+
68107
async def safe_stake_extrinsic(
69108
netuid_: int,
70109
amount_: Balance,
@@ -87,7 +126,7 @@ async def safe_stake_extrinsic(
87126
"hotkey": hotkey_ss58_,
88127
"netuid": netuid_,
89128
"amount_staked": amount_.rao,
90-
"limit_price": price_limit,
129+
"limit_price": price_limit.rao,
91130
"allow_partial": allow_partial_stake,
92131
},
93132
),
@@ -332,19 +371,6 @@ async def stake_extrinsic(
332371
# Temporary workaround - calculations without slippage
333372
current_price_float = float(subnet_info.price.tao)
334373
rate = 1.0 / current_price_float
335-
received_amount = rate * amount_to_stake
336-
337-
# Add rows for the table
338-
base_row = [
339-
str(netuid), # netuid
340-
f"{hotkey[1]}", # hotkey
341-
str(amount_to_stake), # amount
342-
str(rate)
343-
+ f" {Balance.get_unit(netuid)}/{Balance.get_unit(0)} ", # rate
344-
str(received_amount.set_unit(netuid)), # received
345-
str(stake_fee), # fee
346-
# str(slippage_pct), # slippage
347-
]
348374

349375
# If we are staking safe, add price tolerance
350376
if safe_staking:
@@ -356,21 +382,45 @@ async def stake_extrinsic(
356382
rate_with_tolerance = f"{_rate_with_tolerance:.4f}"
357383
price_with_tolerance = Balance.from_tao(
358384
price_with_tolerance
359-
).rao # Actual price to pass to extrinsic
385+
) # Actual price to pass to extrinsic
360386
else:
361387
rate_with_tolerance = "1"
362388
price_with_tolerance = Balance.from_rao(1)
389+
extrinsic_fee = await get_stake_extrinsic_fee(
390+
netuid_=netuid,
391+
amount_=amount_to_stake,
392+
staking_address_=hotkey[1],
393+
safe_staking_=safe_staking,
394+
price_limit=price_with_tolerance,
395+
)
363396
prices_with_tolerance.append(price_with_tolerance)
364-
365-
base_row.extend(
366-
[
367-
f"{rate_with_tolerance} {Balance.get_unit(netuid)}/{Balance.get_unit(0)} ",
368-
f"[{'dark_sea_green3' if allow_partial_stake else 'red'}]"
369-
# safe staking
370-
f"{allow_partial_stake}[/{'dark_sea_green3' if allow_partial_stake else 'red'}]",
371-
]
397+
row_extension = [
398+
f"{rate_with_tolerance} {Balance.get_unit(netuid)}/{Balance.get_unit(0)} ",
399+
f"[{'dark_sea_green3' if allow_partial_stake else 'red'}]"
400+
# safe staking
401+
f"{allow_partial_stake}[/{'dark_sea_green3' if allow_partial_stake else 'red'}]",
402+
]
403+
else:
404+
extrinsic_fee = await get_stake_extrinsic_fee(
405+
netuid_=netuid,
406+
amount_=amount_to_stake,
407+
staking_address_=hotkey[1],
408+
safe_staking_=safe_staking,
372409
)
373-
410+
row_extension = []
411+
received_amount = rate * (amount_to_stake - stake_fee - extrinsic_fee)
412+
# Add rows for the table
413+
base_row = [
414+
str(netuid), # netuid
415+
f"{hotkey[1]}", # hotkey
416+
str(amount_to_stake), # amount
417+
str(rate)
418+
+ f" {Balance.get_unit(netuid)}/{Balance.get_unit(0)} ", # rate
419+
str(received_amount.set_unit(netuid)), # received
420+
str(stake_fee), # fee
421+
str(extrinsic_fee),
422+
# str(slippage_pct), # slippage
423+
] + row_extension
374424
rows.append(tuple(base_row))
375425

376426
# Define and print stake table + slippage warning
@@ -569,17 +619,17 @@ def _define_stake_table(
569619
"Hotkey", justify="center", style=COLOR_PALETTE["GENERAL"]["HOTKEY"]
570620
)
571621
table.add_column(
572-
f"Amount ({Balance.get_unit(0)})",
622+
"Amount (τ)",
573623
justify="center",
574624
style=COLOR_PALETTE["POOLS"]["TAO"],
575625
)
576626
table.add_column(
577-
f"Rate (per {Balance.get_unit(0)})",
627+
"Rate (per τ)",
578628
justify="center",
579629
style=COLOR_PALETTE["POOLS"]["RATE"],
580630
)
581631
table.add_column(
582-
"Received",
632+
"Est. Received",
583633
justify="center",
584634
style=COLOR_PALETTE["POOLS"]["TAO_EQUIV"],
585635
)
@@ -588,6 +638,11 @@ def _define_stake_table(
588638
justify="center",
589639
style=COLOR_PALETTE["STAKE"]["STAKE_AMOUNT"],
590640
)
641+
table.add_column(
642+
"Extrinsic Fee (τ)",
643+
justify="center",
644+
style=COLOR_PALETTE.STAKE.TAO,
645+
)
591646
# TODO: Uncomment when slippage is reimplemented for v3
592647
# table.add_column(
593648
# "Slippage", justify="center", style=COLOR_PALETTE["STAKE"]["SLIPPAGE_PERCENT"]

0 commit comments

Comments
 (0)