Skip to content

Commit

Permalink
Retry always except for reverted messages (#360)
Browse files Browse the repository at this point in the history
  • Loading branch information
kongzii authored Aug 27, 2024
1 parent 0b0e295 commit ae17b59
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ def tavily_search(
return response_parsed


@tenacity.retry(
stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1), reraise=True
)
@tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1))
def _tavily_search(
query: str,
search_depth: t.Literal["basic", "advanced"],
Expand Down
15 changes: 5 additions & 10 deletions prediction_market_agent_tooling/tools/web3_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
ONE_NONCE = Nonce(1)
ONE_XDAI = xdai_type(1)
ZERO_BYTES = HexBytes(HASH_ZERO)
NOT_REVERTED_ICASE_REGEX_PATTERN = "(?i)(?!.*reverted.*)"


def private_key_to_public_key(private_key: SecretStr) -> ChecksumAddress:
Expand Down Expand Up @@ -154,11 +155,8 @@ def _prepare_tx_params(


@tenacity.retry(
# Retry only for the transaction errors that match the given patterns,
# add other retrieable errors gradually to be safe.
retry=tenacity.retry_if_exception_message(
match="(.*wrong transaction nonce.*)|(.*Invalid.*)|(.*OldNonce.*)"
),
# Don't retry on `reverted` messages, as they would always fail again.
retry=tenacity.retry_if_exception_message(match=NOT_REVERTED_ICASE_REGEX_PATTERN),
wait=tenacity.wait_chain(*[tenacity.wait_fixed(n) for n in range(1, 10)]),
stop=tenacity.stop_after_attempt(9),
after=lambda x: logger.debug(
Expand Down Expand Up @@ -194,11 +192,8 @@ def send_function_on_contract_tx(


@tenacity.retry(
# Retry only for the transaction errors that match the given patterns,
# add other retrieable errors gradually to be safe.
retry=tenacity.retry_if_exception_message(
match="(.*wrong transaction nonce.*)|(.*Invalid.*)|(.*OldNonce.*)"
),
# Don't retry on `reverted` messages, as they would always fail again.
retry=tenacity.retry_if_exception_message(match=NOT_REVERTED_ICASE_REGEX_PATTERN),
wait=tenacity.wait_chain(*[tenacity.wait_fixed(n) for n in range(1, 10)]),
stop=tenacity.stop_after_attempt(9),
after=lambda x: logger.debug(
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "prediction-market-agent-tooling"
version = "0.48.4"
version = "0.48.5"
description = "Tools to benchmark, deploy and monitor prediction market agents."
authors = ["Gnosis"]
readme = "README.md"
Expand Down
19 changes: 19 additions & 0 deletions tests/tools/test_web3_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import re

import pytest
from pydantic.types import SecretStr

from prediction_market_agent_tooling.gtypes import IPFSCIDVersion0
from prediction_market_agent_tooling.tools.web3_utils import (
NOT_REVERTED_ICASE_REGEX_PATTERN,
byte32_to_ipfscidv0,
ipfscidv0_to_byte32,
private_key_to_public_key,
Expand All @@ -27,3 +31,18 @@ def test_ipfs_hash_conversion() -> None:

as_ipfs = byte32_to_ipfscidv0(as_bytes32)
assert as_ipfs == ipfs, "The IPFS hash should be the same after conversion back"


@pytest.mark.parametrize(
"string, matched",
[
("blah blah", True),
("blah blah reverted", False),
("reverted blah blah", False),
("reveRted", False),
("", True),
],
)
def test_not_reverted_regex(string: str, matched: bool) -> None:
p = re.compile(NOT_REVERTED_ICASE_REGEX_PATTERN)
assert bool(p.match(string)) == matched
29 changes: 28 additions & 1 deletion tests_integration_with_local_chain/markets/omen/test_contract.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import time

import pytest
from ape_test import TestAccount
from web3 import Web3

from prediction_market_agent_tooling.gtypes import ChecksumAddress
from prediction_market_agent_tooling.config import APIKeys
from prediction_market_agent_tooling.gtypes import ChecksumAddress, xDai
from prediction_market_agent_tooling.markets.omen.omen_contracts import (
WrappedxDaiContract,
sDaiContract,
Expand All @@ -13,6 +17,7 @@
contract_implements_function,
init_collateral_token_contract,
)
from prediction_market_agent_tooling.tools.web3_utils import xdai_to_wei


def test_init_erc4626_erc20_contract_return_erc4626_instance(local_web3: Web3) -> None:
Expand Down Expand Up @@ -95,3 +100,25 @@ def test_contract_implements_function(
)
== expected
)


def test_wont_retry(local_web3: Web3, accounts: list[TestAccount]) -> None:
value = xdai_to_wei(xDai(10))
from_account = accounts[0]
to_account = accounts[1]

start_time = time.time()
with pytest.raises(Exception) as e:
WrappedxDaiContract().transferFrom(
api_keys=APIKeys(BET_FROM_PRIVATE_KEY=from_account.private_key),
sender=Web3.to_checksum_address(from_account.address),
recipient=Web3.to_checksum_address(to_account.address),
amount_wei=value,
web3=local_web3,
)
end_time = time.time()

assert "reverted" in str(e)
assert (
end_time - start_time < 1
), "Should not retry --> should take less then 1 second to execute."
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from ape_test import TestAccount
from eth_account import Account
from numpy import isclose
from pydantic import SecretStr
from web3 import Web3
from web3.types import Wei

from prediction_market_agent_tooling.config import APIKeys
from prediction_market_agent_tooling.gtypes import PrivateKey, xDai, xdai_type
from prediction_market_agent_tooling.gtypes import private_key_type, xDai, xdai_type
from prediction_market_agent_tooling.markets.omen.omen import (
is_minimum_required_balance,
)
Expand All @@ -31,7 +30,7 @@ def test_send_xdai(local_web3: Web3, accounts: list[TestAccount]) -> None:

send_xdai_to(
web3=local_web3,
from_private_key=PrivateKey(SecretStr(from_account.private_key)),
from_private_key=private_key_type(from_account.private_key),
to_address=to_account.address,
value=value,
)
Expand All @@ -57,7 +56,7 @@ def test_send_xdai_from_locked_account(
# we fund the random account for later sending
send_xdai_to(
web3=local_web3,
from_private_key=PrivateKey(SecretStr(from_account.key.hex())),
from_private_key=private_key_type(from_account.key.hex()),
to_address=random_locked_account.address,
value=fund_value,
)
Expand All @@ -66,7 +65,7 @@ def test_send_xdai_from_locked_account(
assert xdai_to_wei(balance_random.xdai) == fund_value
send_xdai_to(
web3=local_web3,
from_private_key=PrivateKey(SecretStr(random_locked_account.key.hex())),
from_private_key=private_key_type(random_locked_account.key.hex()),
to_address=from_account.address,
value=transfer_back_value,
)
Expand Down

0 comments on commit ae17b59

Please sign in to comment.