Skip to content
Merged
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
21 changes: 19 additions & 2 deletions async_substrate_interface/async_substrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3500,7 +3500,13 @@ async def get_constant(
return None

async def get_payment_info(
self, call: GenericCall, keypair: Keypair
self,
call: GenericCall,
keypair: Keypair,
era: Optional[Union[dict, str]] = None,
nonce: Optional[int] = None,
tip: int = 0,
tip_asset_id: Optional[int] = None,
) -> dict[str, Any]:
"""
Retrieves fee estimation via RPC for given extrinsic
Expand All @@ -3509,6 +3515,11 @@ async def get_payment_info(
call: Call object to estimate fees for
keypair: Keypair of the sender, does not have to include private key because no valid signature is
required
era: Specify mortality in blocks in follow format:
{'period': [amount_blocks]} If omitted the extrinsic is immortal
nonce: nonce to include in extrinsics, if omitted the current nonce is retrieved on-chain
tip: The tip for the block author to gain priority during network congestion
tip_asset_id: Optional asset ID with which to pay the tip

Returns:
Dict with payment info
Expand All @@ -3528,7 +3539,13 @@ async def get_payment_info(

# Create extrinsic
extrinsic = await self.create_signed_extrinsic(
call=call, keypair=keypair, signature=signature
call=call,
keypair=keypair,
era=era,
nonce=nonce,
tip=tip,
tip_asset_id=tip_asset_id,
signature=signature,
)
extrinsic_len = len(extrinsic.data)

Expand Down
23 changes: 21 additions & 2 deletions async_substrate_interface/sync_substrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2779,14 +2779,27 @@ def get_constant(
else:
return None

def get_payment_info(self, call: GenericCall, keypair: Keypair) -> dict[str, Any]:
def get_payment_info(
self,
call: GenericCall,
keypair: Keypair,
era: Optional[Union[dict, str]] = None,
nonce: Optional[int] = None,
tip: int = 0,
tip_asset_id: Optional[int] = None,
) -> dict[str, Any]:
"""
Retrieves fee estimation via RPC for given extrinsic

Args:
call: Call object to estimate fees for
keypair: Keypair of the sender, does not have to include private key because no valid signature is
required
era: Specify mortality in blocks in follow format:
{'period': [amount_blocks]} If omitted the extrinsic is immortal
nonce: nonce to include in extrinsics, if omitted the current nonce is retrieved on-chain
tip: The tip for the block author to gain priority during network congestion
tip_asset_id: Optional asset ID with which to pay the tip

Returns:
Dict with payment info
Expand All @@ -2806,7 +2819,13 @@ def get_payment_info(self, call: GenericCall, keypair: Keypair) -> dict[str, Any

# Create extrinsic
extrinsic = self.create_signed_extrinsic(
call=call, keypair=keypair, signature=signature
call=call,
keypair=keypair,
era=era,
nonce=nonce,
tip=tip,
tip_asset_id=tip_asset_id,
signature=signature,
)
extrinsic_len = len(extrinsic.data)

Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ dev = [
"pytest-split==0.10.0",
"pytest-xdist==3.6.1",
"pytest-rerunfailures==10.2",
"substrate-interface"
"substrate-interface",
"bittensor-wallet>=4.0.0"
]
40 changes: 40 additions & 0 deletions tests/integration_tests/test_async_substrate_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import time
import threading

import bittensor_wallet
import pytest
from scalecodec import ss58_encode

Expand Down Expand Up @@ -235,3 +236,42 @@ async def test_improved_reconnection():
shutdown_thread.start()
shutdown_thread.join(timeout=5)
server_thread.join(timeout=5)


@pytest.mark.asyncio
async def test_get_payment_info():
alice_coldkey = bittensor_wallet.Keypair.create_from_uri("//Alice")
bob_coldkey = bittensor_wallet.Keypair.create_from_uri("//Bob")
async with AsyncSubstrateInterface(
LATENT_LITE_ENTRYPOINT, ss58_format=42, chain_name="Bittensor"
) as substrate:
block_hash = await substrate.get_chain_head()
call = await substrate.compose_call(
"Balances",
"transfer_keep_alive",
{"dest": bob_coldkey.ss58_address, "value": 100_000},
block_hash,
)
payment_info = await substrate.get_payment_info(
call=call,
keypair=alice_coldkey,
)
partial_fee_no_era = payment_info["partial_fee"]
assert partial_fee_no_era > 0
payment_info_era = await substrate.get_payment_info(
call=call, keypair=alice_coldkey, era={"period": 64}
)
partial_fee_era = payment_info_era["partial_fee"]
assert partial_fee_era > partial_fee_no_era

payment_info_all_options = await substrate.get_payment_info(
call=call,
keypair=alice_coldkey,
era={"period": 64},
nonce=await substrate.get_account_nonce(alice_coldkey.ss58_address),
tip=5_000_000,
tip_asset_id=64,
)
partial_fee_all_options = payment_info_all_options["partial_fee"]
assert partial_fee_all_options > partial_fee_no_era
assert partial_fee_all_options > partial_fee_era
39 changes: 39 additions & 0 deletions tests/integration_tests/test_substrate_interface.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import bittensor_wallet
from scalecodec import ss58_encode

from async_substrate_interface.sync_substrate import SubstrateInterface
Expand Down Expand Up @@ -112,3 +113,41 @@ def test_query_map_with_odd_number_of_params():
first_record = qm.records[0]
assert len(first_record) == 2
assert len(first_record[0]) == 4


def test_get_payment_info():
alice_coldkey = bittensor_wallet.Keypair.create_from_uri("//Alice")
bob_coldkey = bittensor_wallet.Keypair.create_from_uri("//Bob")
with SubstrateInterface(
LATENT_LITE_ENTRYPOINT, ss58_format=42, chain_name="Bittensor"
) as substrate:
block_hash = substrate.get_chain_head()
call = substrate.compose_call(
"Balances",
"transfer_keep_alive",
{"dest": bob_coldkey.ss58_address, "value": 100_000},
block_hash,
)
payment_info = substrate.get_payment_info(
call=call,
keypair=alice_coldkey,
)
partial_fee_no_era = payment_info["partial_fee"]
assert partial_fee_no_era > 0
payment_info_era = substrate.get_payment_info(
call=call, keypair=alice_coldkey, era={"period": 64}
)
partial_fee_era = payment_info_era["partial_fee"]
assert partial_fee_era > partial_fee_no_era

payment_info_all_options = substrate.get_payment_info(
call=call,
keypair=alice_coldkey,
era={"period": 64},
nonce=substrate.get_account_nonce(alice_coldkey.ss58_address),
tip=5_000_000,
tip_asset_id=64,
)
partial_fee_all_options = payment_info_all_options["partial_fee"]
assert partial_fee_all_options > partial_fee_no_era
assert partial_fee_all_options > partial_fee_era
Loading