prediction-market-agent-tooling 0.69.11.dev1122__py3-none-any.whl → 0.69.17.dev1149__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ [
2
+ {
3
+ "constant": true,
4
+ "inputs": [],
5
+ "name": "processor",
6
+ "outputs": [
7
+ {
8
+ "name": "impl",
9
+ "type": "address"
10
+ }
11
+ ],
12
+ "payable": false,
13
+ "stateMutability": "view",
14
+ "type": "function"
15
+ }
16
+ ]
@@ -33,7 +33,7 @@ VerifiedChecksumAddress: TypeAlias = Annotated[
33
33
  ]
34
34
  VerifiedChecksumAddressOrNone: TypeAlias = Annotated[
35
35
  ChecksumAddress | None,
36
- BeforeValidator(lambda x: Web3.to_checksum_address(x) if x is not None else None),
36
+ BeforeValidator(lambda x: Web3.to_checksum_address(x) if x else None),
37
37
  ]
38
38
 
39
39
 
@@ -60,6 +60,10 @@ class _GenericValue(
60
60
  cls.parser = parser
61
61
 
62
62
  def __init__(self, value: InputValueType) -> None:
63
+ if isinstance(value, str) and (
64
+ value.startswith("0x") or value.startswith("-0x")
65
+ ):
66
+ value = int(value, 16) # type: ignore[assignment] # mypy is confused but if `parser` below can process it, it should be fine, and if it cannot, it should be catched by mypy earlier than here.
63
67
  self.value: InternalValueType = self.parser(value)
64
68
  super().__init__({"value": self.value, "type": self.__class__.__name__})
65
69
 
@@ -187,9 +191,11 @@ class _GenericValue(
187
191
  raise TypeError("Cannot compare different types")
188
192
  return bool(self.value >= other.value)
189
193
 
190
- def __eq__(self: GenericValueType, other: GenericValueType | t.Literal[0]) -> bool: # type: ignore
194
+ def __eq__(self: GenericValueType, other: GenericValueType | t.Literal[0] | None) -> bool: # type: ignore
191
195
  if other == 0:
192
196
  other = self.zero()
197
+ if other is None:
198
+ return False
193
199
  if not isinstance(other, _GenericValue):
194
200
  raise TypeError("Cannot compare different types")
195
201
  if type(self) is not type(other):
@@ -28,7 +28,10 @@ from sqlmodel import Field, SQLModel, desc, select
28
28
  from prediction_market_agent_tooling.config import APIKeys
29
29
  from prediction_market_agent_tooling.loggers import logger
30
30
  from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC
31
- from prediction_market_agent_tooling.tools.db.db_manager import DBManager
31
+ from prediction_market_agent_tooling.tools.db.db_manager import (
32
+ DBManager,
33
+ EnsureTableManager,
34
+ )
32
35
  from prediction_market_agent_tooling.tools.utils import utcnow
33
36
 
34
37
  DB_CACHE_LOG_PREFIX = "[db-cache]"
@@ -49,6 +52,10 @@ class FunctionCache(SQLModel, table=True):
49
52
  created_at: DatetimeUTC = Field(default_factory=utcnow, index=True)
50
53
 
51
54
 
55
+ # Global instance of the table manager for FunctionCache
56
+ _table_manager = EnsureTableManager([FunctionCache])
57
+
58
+
52
59
  @overload
53
60
  def db_cache(
54
61
  func: None = None,
@@ -113,10 +120,8 @@ def db_cache(
113
120
  if not api_keys.ENABLE_CACHE:
114
121
  return await func(*args, **kwargs)
115
122
 
116
- # Run blocking database operations in thread pool
117
-
118
- # Ensure tables in thread pool
119
- await asyncio.to_thread(_ensure_tables, api_keys)
123
+ # Ensure tables are created before accessing cache
124
+ await _table_manager.ensure_tables_async(api_keys)
120
125
 
121
126
  ctx = _build_context(func, args, kwargs, ignore_args, ignore_arg_types)
122
127
 
@@ -155,7 +160,8 @@ def db_cache(
155
160
  if not api_keys.ENABLE_CACHE:
156
161
  return func(*args, **kwargs)
157
162
 
158
- _ensure_tables(api_keys)
163
+ # Ensure tables are created before accessing cache
164
+ _table_manager.ensure_tables_sync(api_keys)
159
165
 
160
166
  ctx = _build_context(func, args, kwargs, ignore_args, ignore_arg_types)
161
167
  lookup = _fetch_cached(api_keys, ctx, max_age)
@@ -200,12 +206,6 @@ class CacheLookup:
200
206
  value: Any | None = None
201
207
 
202
208
 
203
- def _ensure_tables(api_keys: APIKeys) -> None:
204
- DBManager(api_keys.sqlalchemy_db_url.get_secret_value()).create_tables(
205
- [FunctionCache]
206
- )
207
-
208
-
209
209
  def _build_context(
210
210
  func: Callable[..., Any],
211
211
  args: tuple[Any, ...],
@@ -363,8 +363,8 @@ def convert_cached_output_to_pydantic(return_type: Any, data: Any) -> Any:
363
363
  if origin is None:
364
364
  if inspect.isclass(return_type) and issubclass(return_type, BaseModel):
365
365
  # Convert the dictionary to a Pydantic model
366
- return return_type(
367
- **{
366
+ return return_type.model_validate(
367
+ {
368
368
  k: convert_cached_output_to_pydantic(
369
369
  getattr(return_type, k, None), v
370
370
  )
@@ -29,7 +29,10 @@ def json_serializer_default_fn(
29
29
  elif isinstance(y, HexBytes):
30
30
  return f"HexBytes::{y.to_0x_hex()}"
31
31
  elif isinstance(y, BaseModel):
32
- return y.model_dump()
32
+ # For some reason, Pydantic by default serializes using the field names (not alias),
33
+ # but also by default, deserializes only using the aliased names.
34
+ # `by_alias=True` here to work by default with models that have some fields with aliased names.
35
+ return y.model_dump(by_alias=True)
33
36
  raise TypeError(
34
37
  f"Unsupported type for the default json serialize function, value is {y}."
35
38
  )
@@ -5,11 +5,14 @@ import typing as t
5
5
  from contextlib import contextmanager
6
6
 
7
7
  import eth_abi
8
+ import tenacity
8
9
  from eth_abi.exceptions import DecodingError
9
10
  from pydantic import BaseModel, field_validator
10
11
  from web3 import Web3
11
12
  from web3.constants import CHECKSUM_ADDRESSS_ZERO, HASH_ZERO
12
13
  from web3.contract.contract import Contract as Web3Contract
14
+ from web3.exceptions import ContractCustomError, ContractLogicError
15
+ from web3.types import BlockIdentifier
13
16
 
14
17
  from prediction_market_agent_tooling.chains import POLYGON_CHAIN_ID
15
18
  from prediction_market_agent_tooling.config import APIKeys, RPCConfig
@@ -95,6 +98,7 @@ class ContractBaseClass(BaseModel):
95
98
  function_name: str,
96
99
  function_params: t.Optional[list[t.Any] | dict[str, t.Any]] = None,
97
100
  web3: Web3 | None = None,
101
+ block_identifier: BlockIdentifier | None = None,
98
102
  ) -> t.Any:
99
103
  """
100
104
  Used for reading from the contract.
@@ -106,6 +110,7 @@ class ContractBaseClass(BaseModel):
106
110
  contract_abi=self.abi,
107
111
  function_name=function_name,
108
112
  function_params=function_params,
113
+ block_identifier=block_identifier,
109
114
  )
110
115
 
111
116
  def send(
@@ -194,6 +199,22 @@ class ContractProxyBaseClass(ContractBaseClass):
194
199
  return Web3.to_checksum_address(address)
195
200
 
196
201
 
202
+ class ContractProcessorBaseClass(ContractBaseClass):
203
+ """
204
+ Contract base class for processor contracts.
205
+ """
206
+
207
+ abi: ABI = abi_field_validator(
208
+ os.path.join(
209
+ os.path.dirname(os.path.realpath(__file__)), "../abis/processor.abi.json"
210
+ )
211
+ )
212
+
213
+ def processor(self, web3: Web3 | None = None) -> ChecksumAddress:
214
+ address = self.call("processor", web3=web3)
215
+ return Web3.to_checksum_address(address)
216
+
217
+
197
218
  class ContractERC20BaseClass(ContractBaseClass):
198
219
  """
199
220
  Contract base class extended by ERC-20 standard methods.
@@ -205,10 +226,18 @@ class ContractERC20BaseClass(ContractBaseClass):
205
226
  )
206
227
  )
207
228
 
229
+ def name(self, web3: Web3 | None = None) -> str:
230
+ name: str = self.call("name", web3=web3)
231
+ return name
232
+
208
233
  def symbol(self, web3: Web3 | None = None) -> str:
209
234
  symbol: str = self.call("symbol", web3=web3)
210
235
  return symbol
211
236
 
237
+ def decimals(self, web3: Web3 | None = None) -> int:
238
+ decimals = int(self.call("decimals", web3=web3))
239
+ return decimals
240
+
212
241
  def symbol_cached(self, web3: Web3 | None = None) -> str:
213
242
  web3 = web3 or self.get_web3()
214
243
  cache_key = create_contract_method_cache_key(self.symbol, web3)
@@ -264,8 +293,17 @@ class ContractERC20BaseClass(ContractBaseClass):
264
293
  web3=web3,
265
294
  )
266
295
 
267
- def balanceOf(self, for_address: ChecksumAddress, web3: Web3 | None = None) -> Wei:
268
- balance = Wei(self.call("balanceOf", [for_address], web3=web3))
296
+ def balanceOf(
297
+ self,
298
+ for_address: ChecksumAddress,
299
+ web3: Web3 | None = None,
300
+ block_identifier: BlockIdentifier | None = None,
301
+ ) -> Wei:
302
+ balance = Wei(
303
+ self.call(
304
+ "balanceOf", [for_address], web3=web3, block_identifier=block_identifier
305
+ )
306
+ )
269
307
  return balance
270
308
 
271
309
  def balance_of_in_tokens(
@@ -938,8 +976,11 @@ def uni_implementation_address(
938
976
  # TODO: Fix the above, and afterwards assert that only 1 imp address is returned from this function. Or prove that this could indeed happen (although we are very pretty sure it shouldn't).
939
977
  addresses = [
940
978
  implementation_proxy_address(contract_address, web3),
979
+ processor_proxy_address(contract_address, web3),
941
980
  minimal_proxy_address(contract_address, web3),
942
981
  seer_minimal_proxy_address(contract_address, web3),
982
+ eip_1967_proxy_address(contract_address, web3),
983
+ zeppelinos_unstructured_storage_proxy_address(contract_address, web3),
943
984
  ]
944
985
  return [addr for addr in addresses if addr is not None]
945
986
 
@@ -951,7 +992,43 @@ def implementation_proxy_address(
951
992
  contract_address, "implementation", web3, look_for_proxy_contract=False
952
993
  ):
953
994
  return None
954
- return ContractProxyOnGnosisChain(address=contract_address).implementation(web3)
995
+ try:
996
+ return ContractProxyOnGnosisChain(address=contract_address).implementation(web3)
997
+ except (ContractCustomError, ContractLogicError, tenacity.RetryError) as e:
998
+ if isinstance(e, tenacity.RetryError) and not isinstance(
999
+ e.last_attempt.exception(), (ContractCustomError, ContractLogicError)
1000
+ ):
1001
+ raise
1002
+
1003
+ # For example https://gnosisscan.io/address/0x3221a28ed2b2e955da64d1d299956f277562c95c#code,
1004
+ # it has the implementation method, but it's only for admins.
1005
+ logger.warning(
1006
+ f"Failed to get implementation for {contract_address=} even though it has the method: {e}"
1007
+ )
1008
+ return None
1009
+
1010
+
1011
+ def processor_proxy_address(
1012
+ contract_address: ChecksumAddress, web3: Web3
1013
+ ) -> ChecksumAddress | None:
1014
+ if not contract_implements_function(
1015
+ contract_address, "processor", web3, look_for_proxy_contract=False
1016
+ ):
1017
+ return None
1018
+ try:
1019
+ return ContractProcessorBaseClass(address=contract_address).processor(web3)
1020
+ except (ContractCustomError, ContractLogicError, tenacity.RetryError) as e:
1021
+ if isinstance(e, tenacity.RetryError) and not isinstance(
1022
+ e.last_attempt.exception(), (ContractCustomError, ContractLogicError)
1023
+ ):
1024
+ raise
1025
+
1026
+ # For example https://gnosisscan.io/address/0x3221a28ed2b2e955da64d1d299956f277562c95c#code,
1027
+ # it has the processor method, but it's only for admins.
1028
+ logger.warning(
1029
+ f"Failed to get processor for {contract_address=} even though it has the method: {e}"
1030
+ )
1031
+ return None
955
1032
 
956
1033
 
957
1034
  def minimal_proxy_address(
@@ -982,6 +1059,34 @@ def seer_minimal_proxy_address(
982
1059
  return None
983
1060
 
984
1061
 
1062
+ def eip_1967_proxy_address(
1063
+ contract_address: ChecksumAddress, web3: Web3
1064
+ ) -> ChecksumAddress | None:
1065
+ try:
1066
+ slot = HexBytes(Web3.keccak(text="eip1967.proxy.implementation")).as_int() - 1
1067
+ raw_slot = web3.eth.get_storage_at(contract_address, slot)
1068
+ address = eth_abi.decode(["address"], raw_slot)[0]
1069
+ return Web3.to_checksum_address(address)
1070
+ except DecodingError:
1071
+ logger.info("Error decoding contract address for eip 1967 proxy")
1072
+ return None
1073
+
1074
+
1075
+ def zeppelinos_unstructured_storage_proxy_address(
1076
+ contract_address: ChecksumAddress, web3: Web3
1077
+ ) -> ChecksumAddress | None:
1078
+ try:
1079
+ slot = HexBytes(
1080
+ Web3.keccak(text="org.zeppelinos.proxy.implementation")
1081
+ ).as_int()
1082
+ raw_slot = web3.eth.get_storage_at(contract_address, slot)
1083
+ address = eth_abi.decode(["address"], raw_slot)[0]
1084
+ return Web3.to_checksum_address(address)
1085
+ except DecodingError:
1086
+ logger.info("Error decoding contract address for zeppelinos proxy")
1087
+ return None
1088
+
1089
+
985
1090
  def init_collateral_token_contract(
986
1091
  address: ChecksumAddress, web3: Web3 | None
987
1092
  ) -> ContractERC20BaseClass:
@@ -1,5 +1,5 @@
1
1
  from enum import Enum
2
- from typing import Optional
2
+ from typing import Optional, TypeAlias
3
3
 
4
4
  from pydantic import BaseModel, ConfigDict
5
5
  from sqlmodel import Field, SQLModel
@@ -74,10 +74,13 @@ class OrderStatus(str, Enum):
74
74
  expired = "expired"
75
75
 
76
76
 
77
+ CowOrderUID: TypeAlias = HexBytes
78
+
79
+
77
80
  class Order(BaseModel):
78
81
  model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
79
82
 
80
- uid: str
83
+ uid: CowOrderUID
81
84
  quoteId: int | None = None
82
85
  validTo: int
83
86
  sellAmount: Wei
@@ -1,7 +1,10 @@
1
+ import asyncio
1
2
  import hashlib
3
+ import threading
2
4
  from contextlib import contextmanager
3
5
  from typing import Generator, Sequence
4
6
 
7
+ from pydantic import SecretStr
5
8
  from sqlalchemy import Connection
6
9
  from sqlmodel import Session, SQLModel, create_engine
7
10
 
@@ -79,3 +82,59 @@ class DBManager:
79
82
  if tables_to_create:
80
83
  for table in tables_to_create:
81
84
  self.cache_table_initialized[table.name] = True
85
+
86
+
87
+ class EnsureTableManager:
88
+ """
89
+ Manages database table initialization with thread-safe and async-safe locking.
90
+ Ensures tables are created only once per database URL.
91
+ """
92
+
93
+ def __init__(self, tables: Sequence[type[SQLModel]]) -> None:
94
+ """
95
+ Initialize the table manager with the tables to manage.
96
+
97
+ Args:
98
+ tables: Sequence of SQLModel table classes to ensure in the database.
99
+ """
100
+ # Ensure tables only once, as it's a time costly operation.
101
+ self._tables = tables
102
+ self._lock_thread = threading.Lock()
103
+ self._lock_async = asyncio.Lock()
104
+ self._ensured: dict[SecretStr, bool] = {}
105
+
106
+ def is_ensured(self, db_url: SecretStr) -> bool:
107
+ """Check if tables have been ensured for the given database URL."""
108
+ return self._ensured.get(db_url, False)
109
+
110
+ def mark_ensured(self, db_url: SecretStr) -> None:
111
+ """Mark tables as ensured for the given database URL."""
112
+ self._ensured[db_url] = True
113
+
114
+ def ensure_tables_sync(self, api_keys: APIKeys) -> None:
115
+ """
116
+ Ensure tables exist for the given API keys (synchronous version).
117
+ Thread-safe with double-checked locking pattern.
118
+ """
119
+ if not self.is_ensured(api_keys.sqlalchemy_db_url):
120
+ with self._lock_thread:
121
+ if not self.is_ensured(api_keys.sqlalchemy_db_url):
122
+ self._create_tables(api_keys)
123
+ self.mark_ensured(api_keys.sqlalchemy_db_url)
124
+
125
+ async def ensure_tables_async(self, api_keys: APIKeys) -> None:
126
+ """
127
+ Ensure tables exist for the given API keys (asynchronous version).
128
+ Async-safe with double-checked locking pattern.
129
+ """
130
+ if not self.is_ensured(api_keys.sqlalchemy_db_url):
131
+ async with self._lock_async:
132
+ if not self.is_ensured(api_keys.sqlalchemy_db_url):
133
+ await asyncio.to_thread(self._create_tables, api_keys)
134
+ self.mark_ensured(api_keys.sqlalchemy_db_url)
135
+
136
+ def _create_tables(self, api_keys: APIKeys) -> None:
137
+ """Create the database tables."""
138
+ DBManager(api_keys.sqlalchemy_db_url.get_secret_value()).create_tables(
139
+ list(self._tables)
140
+ )
@@ -16,7 +16,14 @@ from safe_eth.safe.safe import SafeV141
16
16
  from web3 import Web3
17
17
  from web3.constants import HASH_ZERO
18
18
  from web3.contract.contract import ContractFunction as Web3ContractFunction
19
- from web3.types import AccessList, AccessListEntry, Nonce, TxParams, TxReceipt
19
+ from web3.types import (
20
+ AccessList,
21
+ AccessListEntry,
22
+ BlockIdentifier,
23
+ Nonce,
24
+ TxParams,
25
+ TxReceipt,
26
+ )
20
27
 
21
28
  from prediction_market_agent_tooling.gtypes import (
22
29
  ABI,
@@ -106,11 +113,12 @@ def call_function_on_contract(
106
113
  contract_abi: ABI,
107
114
  function_name: str,
108
115
  function_params: Optional[list[Any] | dict[str, Any]] = None,
116
+ block_identifier: Optional[BlockIdentifier] = None,
109
117
  ) -> Any:
110
118
  contract = web3.eth.contract(address=contract_address, abi=contract_abi)
111
119
  output = contract.functions[function_name](
112
120
  *parse_function_params(function_params)
113
- ).call()
121
+ ).call(block_identifier=block_identifier)
114
122
  return output
115
123
 
116
124
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.69.11.dev1122
3
+ Version: 0.69.17.dev1149
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  License-File: LICENSE
6
6
  Author: Gnosis
@@ -16,6 +16,7 @@ prediction_market_agent_tooling/abis/omen_realitio.abi.json,sha256=7HmFkBF_rq83U
16
16
  prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json,sha256=u1-3B8FB3Ys9KVJCH-lw9ArkicdxbNMf34dV-VEGMMU,930
17
17
  prediction_market_agent_tooling/abis/ownable.abi.json,sha256=DeTy_7VmsMhFl7jwI8MIlmjy2jORauYxrGm7wC_Alxw,1528
18
18
  prediction_market_agent_tooling/abis/ownable_erc721.abi.json,sha256=9sxm588MAQmqCV_S0D3eYC7l9grbeALsd0Da_AHxdEI,8506
19
+ prediction_market_agent_tooling/abis/processor.abi.json,sha256=VGMyBblTPO3I6AoKQFMgTylgJLl6-6FquUbejICDEAw,242
19
20
  prediction_market_agent_tooling/abis/proxy.abi.json,sha256=h24GXZ6Q0bSZlwh7zOv0EiDvbqUz_PHtWfKHTyPJ1w4,644
20
21
  prediction_market_agent_tooling/abis/seer_gnosis_router.abi.json,sha256=DyADzOXhy9MDS31ReVrG7ibpWbw1jVy19nExZ80xfRY,6839
21
22
  prediction_market_agent_tooling/abis/seer_market_factory.abi.json,sha256=g7RVxZVUWlTXIgTV2W6kO4twQM909Qv58zAr7Dk4XIc,13553
@@ -36,7 +37,7 @@ prediction_market_agent_tooling/deploy/gcp/deploy.py,sha256=CYUgnfy-9XVk04kkxA_5
36
37
  prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py,sha256=OsPboCFGiZKsvGyntGZHwdqPlLTthITkNF5rJFvGgU8,2582
37
38
  prediction_market_agent_tooling/deploy/gcp/utils.py,sha256=WI2ycX1X-IlTRoNoG4ggFlRwPL28kwM9VGDFD2fePLo,5699
38
39
  prediction_market_agent_tooling/deploy/trade_interval.py,sha256=Xk9j45alQ_vrasGvsNyuW70XHIQ7wfvjoxNR3F6HYCw,1155
39
- prediction_market_agent_tooling/gtypes.py,sha256=tHXMBjh0iAEJEcBywFvwzwPqDkBUpjEyeb7ynh7fOKc,6469
40
+ prediction_market_agent_tooling/gtypes.py,sha256=Uf6nvnsZnpXCESRrEdwT3Q8h9bt19XP-jn2rt-kqGJg,6457
40
41
  prediction_market_agent_tooling/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
42
  prediction_market_agent_tooling/jobs/jobs_models.py,sha256=4KZ0iaKZx5zEZBBiEo9CHk0OpX3bKjoYA0wmptR0Wyk,2455
42
43
  prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=CojpgghRs0lFEf5wl-oWhGaQozG616YD0cXdlmFO-U0,5116
@@ -84,23 +85,23 @@ prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py,sha256=nme
84
85
  prediction_market_agent_tooling/markets/seer/subgraph_data_models.py,sha256=96v41jdNNxBqTCp5g8SLMSrIgeeITVx5IsBjVgm-qdo,2920
85
86
  prediction_market_agent_tooling/markets/seer/swap_pool_handler.py,sha256=24RVIppztXXFkZp0df7GR_GUSslwR42XsPJhDZ-jphs,2612
86
87
  prediction_market_agent_tooling/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
- prediction_market_agent_tooling/tools/_generic_value.py,sha256=L9SH_-JwD6RQeKoeTxvNWbkY6CxWIz-VjZEURXoZleg,10617
88
+ prediction_market_agent_tooling/tools/_generic_value.py,sha256=7F-hzWkBhySEseczJZTZKTpyPHWWLENu908Ude1fGiQ,10993
88
89
  prediction_market_agent_tooling/tools/balances.py,sha256=Osab21btfJDw2Y-jT_TV-KHGrseCRxcsYeW6WcOMB8E,1050
89
90
  prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py,sha256=o5ba633gKiDqV4t_C2d9FWwH-HkRAOZd8FcZTYvbj6g,14451
90
91
  prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py,sha256=THMXwFlskvzbjnX_OiYtDSzI8XVFyULWfP2525_9UGc,429
91
92
  prediction_market_agent_tooling/tools/betting_strategies/utils.py,sha256=MpS3FOMn0C7nbmbQRUT9QwSh3UzzsgGczP91iSMr9wo,261
92
- prediction_market_agent_tooling/tools/caches/db_cache.py,sha256=V6o6UdesjkKzSJMhqkUtD76cJGPaNhuwA4OL2chIYSI,13801
93
+ prediction_market_agent_tooling/tools/caches/db_cache.py,sha256=NT6pOv7UXretZtebcuVQSfoN6GWxDOqBFGvD1apitQY,13840
93
94
  prediction_market_agent_tooling/tools/caches/inmemory_cache.py,sha256=ZW5iI5rmjqeAebu5T7ftRnlkxiL02IC-MxCfDB80x7w,1506
94
- prediction_market_agent_tooling/tools/caches/serializers.py,sha256=fwyIHUsL7u9NY7ZihTcUdqsvl2psatcbTfgWHTSez3U,2427
95
- prediction_market_agent_tooling/tools/contract.py,sha256=BzpAFcbKl_KqwgAlaXx63Fg8jzr0EO3qEeOs1K11CPA,33905
95
+ prediction_market_agent_tooling/tools/caches/serializers.py,sha256=pa0LpQjtv6TRBobbSgRIfh14T1CqwfzoIXdmEk4BSOA,2711
96
+ prediction_market_agent_tooling/tools/contract.py,sha256=XbdegY4dVdiJkNbtXLKtR2GsqGLMYbvc5lTpIIOcWLw,37785
96
97
  prediction_market_agent_tooling/tools/contract_utils.py,sha256=9X9raICUZkPDShilt02aYzS_ILZ62u0vG5081uWLdqk,2152
97
98
  prediction_market_agent_tooling/tools/costs.py,sha256=EaAJ7v9laD4VEV3d8B44M4u3_oEO_H16jRVCdoZ93Uw,954
98
99
  prediction_market_agent_tooling/tools/cow/cow_order.py,sha256=DN_8cPrr4jWVpXdS4D0j1QB19nB8fxDoSheo2BFMc8M,14523
99
- prediction_market_agent_tooling/tools/cow/models.py,sha256=EpCziNs4sGmN7ZvPKpqdqjhVd_-zPZHsJVeVfFu4Y60,3005
100
+ prediction_market_agent_tooling/tools/cow/models.py,sha256=t91mG-ZN-KxWt3qZbWfu0lS8iKdWoRToH3GiZ0q2YdI,3060
100
101
  prediction_market_agent_tooling/tools/cow/semaphore.py,sha256=LPB-4wNQf7El7dgBD4Tmol6vr5j1CP9qMeDm8dcs6RI,3741
101
102
  prediction_market_agent_tooling/tools/custom_exceptions.py,sha256=Fh8z1fbwONvP4-j7AmV_PuEcoqb6-QXa9PJ9m7guMcM,93
102
103
  prediction_market_agent_tooling/tools/datetime_utc.py,sha256=_oO6mMc28C9aSmQfrG-S7UQy5uMHVEQqia8arnscVCk,3213
103
- prediction_market_agent_tooling/tools/db/db_manager.py,sha256=GtzHH1NLl8HwqC8Z7s6eTlIQXuV0blxfaV2PeQrBnfQ,3013
104
+ prediction_market_agent_tooling/tools/db/db_manager.py,sha256=dSahH8yTgGnFMfdNKKyyPlwNP5dntUpU_8vCH6JpeII,5337
104
105
  prediction_market_agent_tooling/tools/google_utils.py,sha256=D-6FB2HRtmxaKZJ_Za-qj6VZCp5XU18rF4wLMMrqEUg,2557
105
106
  prediction_market_agent_tooling/tools/hexbytes_custom.py,sha256=0Y1n8MChjWJmE4w6kgIJPiqbrGULui0m3TQzUBgZDHs,2206
106
107
  prediction_market_agent_tooling/tools/httpx_cached_client.py,sha256=1mqOWC2-Ch2ibT63GAk0npsVR-4bR1T9WN9eU_SEhkE,634
@@ -136,9 +137,9 @@ prediction_market_agent_tooling/tools/tokens/token_utils.py,sha256=fhs-FH9m9IbzG
136
137
  prediction_market_agent_tooling/tools/tokens/usd.py,sha256=DPO-4HBTy1-TZHKL_9CnHQ8p9W7ivPfcRlUkRO0nKJ8,3259
137
138
  prediction_market_agent_tooling/tools/transaction_cache.py,sha256=K5YKNL2_tR10Iw2TD9fuP-CTGpBbZtNdgbd0B_R7pjg,1814
138
139
  prediction_market_agent_tooling/tools/utils.py,sha256=ruq6P5TFs8CBHxeBLj1Plpx7kuNFPpDgMsJGQgDiRNs,8785
139
- prediction_market_agent_tooling/tools/web3_utils.py,sha256=CDbaidlLeQ4VHzSg150L7QNfHfGveljSePGuDVFEYqc,13963
140
- prediction_market_agent_tooling-0.69.11.dev1122.dist-info/METADATA,sha256=--DwjAkzPXoeCKFir_GnmfydDWkx3NObybMpINRJrKE,8899
141
- prediction_market_agent_tooling-0.69.11.dev1122.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
142
- prediction_market_agent_tooling-0.69.11.dev1122.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
143
- prediction_market_agent_tooling-0.69.11.dev1122.dist-info/licenses/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
144
- prediction_market_agent_tooling-0.69.11.dev1122.dist-info/RECORD,,
140
+ prediction_market_agent_tooling/tools/web3_utils.py,sha256=1G8uu33p4zNhGKSiyyueROtMau4YoMR3N1QDRFQ3TjE,14098
141
+ prediction_market_agent_tooling-0.69.17.dev1149.dist-info/METADATA,sha256=AFE3Z25DPyWW_T5sgdAwS13pNY02p1BzPtmm9kTSogQ,8899
142
+ prediction_market_agent_tooling-0.69.17.dev1149.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
143
+ prediction_market_agent_tooling-0.69.17.dev1149.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
144
+ prediction_market_agent_tooling-0.69.17.dev1149.dist-info/licenses/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
145
+ prediction_market_agent_tooling-0.69.17.dev1149.dist-info/RECORD,,