diff --git a/async_substrate_interface/async_substrate.py b/async_substrate_interface/async_substrate.py index c555c7b..25b6791 100644 --- a/async_substrate_interface/async_substrate.py +++ b/async_substrate_interface/async_substrate.py @@ -3987,6 +3987,32 @@ async def result_handler(message: dict, subscription_id) -> tuple[dict, bool]: message_result = { k.lower(): v for k, v in message["params"]["result"].items() } + # check for any subscription indicators of failure + failure_message = None + if "usurped" in message_result: + failure_message = ( + f"Subscription {subscription_id} usurped: {message_result}" + ) + if "retracted" in message_result: + failure_message = ( + f"Subscription {subscription_id} retracted: {message_result}" + ) + if "finalitytimeout" in message_result: + failure_message = f"Subscription {subscription_id} finalityTimeout: {message_result}" + if "dropped" in message_result: + failure_message = ( + f"Subscription {subscription_id} dropped: {message_result}" + ) + if "invalid" in message_result: + failure_message = ( + f"Subscription {subscription_id} invalid: {message_result}" + ) + + if failure_message is not None: + async with self.ws as ws: + await ws.unsubscribe(subscription_id) + logger.error(failure_message) + raise SubstrateRequestException(failure_message) if "finalized" in message_result and wait_for_finalization: logger.debug("Extrinsic finalized. Unsubscribing.") @@ -3998,7 +4024,7 @@ async def result_handler(message: dict, subscription_id) -> tuple[dict, bool]: "finalized": True, }, True elif ( - any(x in message_result for x in ["inblock", "inBlock"]) + "inblock" in message_result and wait_for_inclusion and not wait_for_finalization ): diff --git a/async_substrate_interface/sync_substrate.py b/async_substrate_interface/sync_substrate.py index c175c1f..a6c0be0 100644 --- a/async_substrate_interface/sync_substrate.py +++ b/async_substrate_interface/sync_substrate.py @@ -3170,6 +3170,32 @@ def result_handler(message: dict, subscription_id) -> tuple[dict, bool]: k.lower(): v for k, v in message["params"]["result"].items() } + # check for any subscription indicators of failure + failure_message = None + if "usurped" in message_result: + failure_message = ( + f"Subscription {subscription_id} usurped: {message_result}" + ) + if "retracted" in message_result: + failure_message = ( + f"Subscription {subscription_id} retracted: {message_result}" + ) + if "finalitytimeout" in message_result: + failure_message = f"Subscription {subscription_id} finalityTimeout: {message_result}" + if "dropped" in message_result: + failure_message = ( + f"Subscription {subscription_id} dropped: {message_result}" + ) + if "invalid" in message_result: + failure_message = ( + f"Subscription {subscription_id} invalid: {message_result}" + ) + + if failure_message is not None: + self.rpc_request("author_unwatchExtrinsic", [subscription_id]) + logger.error(failure_message) + raise SubstrateRequestException(failure_message) + if "finalized" in message_result and wait_for_finalization: # Created as a task because we don't actually care about the result # TODO change this logic