diff --git a/substrateinterface/__init__.py b/substrateinterface/__init__.py index c5b24d1..aa2468d 100644 --- a/substrateinterface/__init__.py +++ b/substrateinterface/__init__.py @@ -1117,18 +1117,18 @@ def create_signed_extrinsic(self, call, keypair: Keypair, era=None, nonce=None, raise TypeError("'call' must be of type Call") # Retrieve nonce - if not nonce: + if nonce is None: nonce = self.get_account_nonce(keypair.public_key) or 0 # Process era - if not era: + if era is None: era = '00' else: if isinstance(era, dict) and 'current' not in era and 'phase' not in era: # Retrieve current block id era['current'] = self.get_block_number(self.get_chain_finalised_head()) - if signature: + if signature is not None: signature = signature.replace('0x', '') @@ -1237,6 +1237,49 @@ def result_handler(result): return response + def get_payment_info(self, call, keypair): + """ + Retrieves fee estimation via RPC for given extrinsic + + Parameters + ---------- + 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 + + Returns + ------- + Dict with payment info + + E.g. {'class': 'normal', 'partialFee': 151000000, 'weight': 217238000} + + """ + + # Check requirements + if not isinstance(call, GenericCall): + raise TypeError("'call' must be of type Call") + + if not isinstance(keypair, Keypair): + raise TypeError("'keypair' must be of type Keypair") + + # No valid signature is required for fee estimation + signature = '0x' + '00' * 64 + + # Create extrinsic + extrinsic = self.create_signed_extrinsic( + call=call, + keypair=keypair, + signature=signature + ) + + payment_info = self.rpc_request('payment_queryInfo', [str(extrinsic.data)]) + + # convert partialFee to int + if 'result' in payment_info: + payment_info['result']['partialFee'] = int(payment_info['result']['partialFee']) + return payment_info['result'] + else: + raise SubstrateRequestException(payment_info['error']['message']) + def process_metadata_typestring(self, type_string): """ Process how given type_string is decoded with active runtime and type registry diff --git a/test/test_create_extrinsics.py b/test/test_create_extrinsics.py index da218b7..dc31849 100644 --- a/test/test_create_extrinsics.py +++ b/test/test_create_extrinsics.py @@ -129,6 +129,25 @@ def test_create_unsigned_extrinsic(self): extrinsic = self.kusama_substrate.create_unsigned_extrinsic(call) self.assertEqual(str(extrinsic.data), '0x280402000ba09cc0317501') + def test_payment_info(self): + keypair = Keypair(ss58_address="EaG2CRhJWPb7qmdcJvy3LiWdh26Jreu9Dx6R1rXxPmYXoDk") + + call = self.kusama_substrate.compose_call( + call_module='Balances', + call_function='transfer', + call_params={ + 'dest': 'EaG2CRhJWPb7qmdcJvy3LiWdh26Jreu9Dx6R1rXxPmYXoDk', + 'value': 2 * 10 ** 3 + } + ) + payment_info = self.kusama_substrate.get_payment_info(call=call, keypair=keypair) + + self.assertIn('class', payment_info) + self.assertIn('partialFee', payment_info) + self.assertIn('weight', payment_info) + + self.assertGreater(payment_info['partialFee'], 0) + if __name__ == '__main__': unittest.main()