Skip to content

Commit

Permalink
make transaction awaiter more robust
Browse files Browse the repository at this point in the history
  • Loading branch information
popenta committed Sep 10, 2024
1 parent 985db9b commit f4a00e3
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 13 deletions.
9 changes: 7 additions & 2 deletions multiversx_sdk/network_providers/api_network_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
ContractQueryRequest
from multiversx_sdk.network_providers.contract_query_response import \
ContractQueryResponse
from multiversx_sdk.network_providers.errors import GenericError
from multiversx_sdk.network_providers.errors import (GenericError,
TransactionFetchingError)
from multiversx_sdk.network_providers.interface import (IAddress,
IContractQuery,
IPagination)
Expand Down Expand Up @@ -129,7 +130,11 @@ def query_contract(self, query: IContractQuery) -> ContractQueryResponse:
return ContractQueryResponse.from_http_response(response)

def get_transaction(self, tx_hash: str) -> TransactionOnNetwork:
response = self.do_get_generic(f'transactions/{tx_hash}')
try:
response = self.do_get_generic(f'transactions/{tx_hash}')
except GenericError as ge:
raise TransactionFetchingError(ge.url, ge.data)

transaction = TransactionOnNetwork.from_api_http_response(tx_hash, response)
return transaction

Expand Down
3 changes: 0 additions & 3 deletions multiversx_sdk/network_providers/api_network_provider_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import base64
import time

import pytest

Expand Down Expand Up @@ -231,7 +230,6 @@ def test_send_and_await_for_completed_transaction(self):
transaction.signature = alice.secret_key.sign(tx_computer.compute_bytes_for_signing(transaction))

hash = self.api.send_transaction(transaction)
time.sleep(1)

tx_on_network = self.api.await_transaction_completed(hash)
assert tx_on_network.status.is_executed()
Expand All @@ -250,7 +248,6 @@ def condition(tx: TransactionOnNetwork) -> bool:
return tx.status.is_failed()

hash = self.api.send_transaction(transaction)
time.sleep(1)

tx_on_network = self.api.await_transaction_on_condition(
tx_hash=hash,
Expand Down
5 changes: 5 additions & 0 deletions multiversx_sdk/network_providers/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ def __init__(self) -> None:
class IsCompletedFieldMissingOnTransaction(Exception):
def __init__(self) -> None:
super().__init__("The transaction awaiter requires the `is_completed` property to be defined on the transaction object. Perhaps you've used `ProxyNetworkProvider.get_transaction()` and in that case you should also pass `with_process_status=True`")


class TransactionFetchingError(Exception):
def __init__(self, url: str, error: Any):
super().__init__(f"Couldn't fetch transaction on url = [{url}], error = [{error}]")
8 changes: 5 additions & 3 deletions multiversx_sdk/network_providers/proxy_network_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
ContractQueryRequest
from multiversx_sdk.network_providers.contract_query_response import \
ContractQueryResponse
from multiversx_sdk.network_providers.errors import GenericError
from multiversx_sdk.network_providers.errors import (GenericError,
TransactionFetchingError)
from multiversx_sdk.network_providers.interface import IAddress, IContractQuery
from multiversx_sdk.network_providers.network_config import NetworkConfig
from multiversx_sdk.network_providers.network_status import NetworkStatus
Expand Down Expand Up @@ -117,10 +118,11 @@ def get_tx() -> Dict[str, Any]:

process_status = status_task.result(timeout=5) if status_task else None
tx = tx_task.result(timeout=5)

except TimeoutError:
raise TimeoutError("Fetching transaction or process status timed out")
except Exception as e:
raise Exception(f"An error occured: {str(e)}")
except GenericError as ge:
raise TransactionFetchingError(ge.url, ge.data)

return TransactionOnNetwork.from_proxy_http_response(tx_hash, tx, process_status)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import time

import pytest

from multiversx_sdk.core.address import Address
Expand Down Expand Up @@ -254,7 +252,6 @@ def test_send_and_await_for_completed_transaction(self):
transaction.signature = alice.secret_key.sign(tx_computer.compute_bytes_for_signing(transaction))

hash = self.proxy.send_transaction(transaction)
time.sleep(1)

tx_on_network = self.proxy.await_transaction_completed(hash)
assert tx_on_network.status.is_executed()
Expand All @@ -273,7 +270,6 @@ def condition(tx: TransactionOnNetwork) -> bool:
return tx.status.is_failed()

hash = self.proxy.send_transaction(transaction)
time.sleep(1)

tx_on_network = self.proxy.await_transaction_on_condition(
tx_hash=hash,
Expand Down
8 changes: 7 additions & 1 deletion multiversx_sdk/network_providers/transaction_awaiter.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import logging
import time
from typing import Callable, Optional, Protocol, Union

from multiversx_sdk.network_providers.constants import (
DEFALT_PATIENCE_IN_MILLISECONDS, DEFAULT_POLLING_INTERVAL_IN_MILLISECONDS,
DEFAULT_TIMEOUT_IN_MILLISECONDS)
from multiversx_sdk.network_providers.errors import (
ExpectedTransactionStatusNotReached, IsCompletedFieldMissingOnTransaction)
ExpectedTransactionStatusNotReached, IsCompletedFieldMissingOnTransaction,
TransactionFetchingError)
from multiversx_sdk.network_providers.transactions import TransactionOnNetwork

ONE_SECOND_IN_MILLISECONDS = 1000

logger = logging.getLogger("transaction_awaiter")


class ITransactionFetcher(Protocol):
def get_transaction(self, tx_hash: str) -> TransactionOnNetwork:
Expand Down Expand Up @@ -92,6 +96,8 @@ def _await_conditionally(self,

if is_condition_satisfied:
break
except TransactionFetchingError:
logger.warning("Couldn't fetch transaction. Retrying...")
except Exception as ex:
raise ex

Expand Down

0 comments on commit f4a00e3

Please sign in to comment.