prediction-market-agent-tooling 0.48.10__py3-none-any.whl → 0.48.11__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.
@@ -1,13 +1,24 @@
1
1
  import typing as t
2
- from datetime import datetime
2
+ from datetime import datetime, timedelta
3
3
 
4
+ import tenacity
4
5
  from loguru import logger
5
6
  from pydantic import BaseModel
6
7
  from sqlalchemy import Column
7
8
  from sqlalchemy.dialects.postgresql import JSONB
8
- from sqlmodel import ARRAY, Field, Session, SQLModel, String, create_engine
9
+ from sqlmodel import (
10
+ ARRAY,
11
+ Field,
12
+ Session,
13
+ SQLModel,
14
+ String,
15
+ create_engine,
16
+ desc,
17
+ select,
18
+ )
9
19
 
10
20
  from prediction_market_agent_tooling.config import APIKeys
21
+ from prediction_market_agent_tooling.tools.utils import utcnow
11
22
 
12
23
 
13
24
  class TavilyResult(BaseModel):
@@ -33,7 +44,7 @@ class TavilyResponseModel(SQLModel, table=True):
33
44
  id: int | None = Field(None, primary_key=True)
34
45
  agent_id: str = Field(index=True, nullable=False)
35
46
  # Parameters used to execute the search
36
- query: str
47
+ query: str = Field(index=True, nullable=False)
37
48
  search_depth: str
38
49
  topic: str
39
50
  max_results: int
@@ -102,6 +113,7 @@ class TavilyStorage:
102
113
  logger.debug(f"tables being added {TavilyResponseModel}")
103
114
  SQLModel.metadata.create_all(self.engine)
104
115
 
116
+ @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1))
105
117
  def save(
106
118
  self,
107
119
  query: str,
@@ -133,3 +145,38 @@ class TavilyStorage:
133
145
  with Session(self.engine) as session:
134
146
  session.add(db_item)
135
147
  session.commit()
148
+
149
+ @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1))
150
+ def find(
151
+ self,
152
+ query: str,
153
+ search_depth: t.Literal["basic", "advanced"],
154
+ topic: t.Literal["general", "news"],
155
+ max_results: int,
156
+ include_domains: t.Sequence[str] | None,
157
+ exclude_domains: t.Sequence[str] | None,
158
+ include_answer: bool,
159
+ include_raw_content: bool,
160
+ include_images: bool,
161
+ use_cache: bool,
162
+ max_age: timedelta = timedelta(days=1),
163
+ ) -> TavilyResponse | None:
164
+ with Session(self.engine) as session:
165
+ sql_query = (
166
+ select(TavilyResponseModel)
167
+ .where(TavilyResponseModel.query == query)
168
+ .where(TavilyResponseModel.search_depth == search_depth)
169
+ .where(TavilyResponseModel.topic == topic)
170
+ .where(TavilyResponseModel.max_results == max_results)
171
+ .where(TavilyResponseModel.include_domains == include_domains)
172
+ .where(TavilyResponseModel.exclude_domains == exclude_domains)
173
+ .where(TavilyResponseModel.include_answer == include_answer)
174
+ .where(TavilyResponseModel.include_raw_content == include_raw_content)
175
+ .where(TavilyResponseModel.include_images == include_images)
176
+ .where(TavilyResponseModel.use_cache == use_cache)
177
+ .where(TavilyResponseModel.datetime_ >= utcnow() - max_age)
178
+ )
179
+ item = session.exec(
180
+ sql_query.order_by(desc(TavilyResponseModel.datetime_))
181
+ ).first()
182
+ return TavilyResponse.model_validate(item.response) if item else None
@@ -29,6 +29,21 @@ def tavily_search(
29
29
 
30
30
  Argument default values are different from the original method, to return everything by default, because it can be handy in the future and it doesn't increase the costs.
31
31
  """
32
+ if tavily_storage and (
33
+ response_parsed := tavily_storage.find(
34
+ query=query,
35
+ search_depth=search_depth,
36
+ topic=topic,
37
+ max_results=max_results,
38
+ include_domains=include_domains,
39
+ exclude_domains=exclude_domains,
40
+ include_answer=include_answer,
41
+ include_raw_content=include_raw_content,
42
+ include_images=include_images,
43
+ use_cache=use_cache,
44
+ )
45
+ ):
46
+ return response_parsed
32
47
  response = _tavily_search(
33
48
  query=query,
34
49
  search_depth=search_depth,
@@ -10,7 +10,7 @@ from gnosis.safe.safe import Safe
10
10
  from pydantic.types import SecretStr
11
11
  from web3 import Web3
12
12
  from web3.constants import HASH_ZERO
13
- from web3.types import Nonce, TxParams, TxReceipt, Wei
13
+ from web3.types import AccessList, AccessListEntry, Nonce, TxParams, TxReceipt, Wei
14
14
 
15
15
  from prediction_market_agent_tooling.gtypes import (
16
16
  ABI,
@@ -118,9 +118,10 @@ def prepare_tx(
118
118
  from_address: ChecksumAddress | None,
119
119
  function_name: str,
120
120
  function_params: Optional[list[Any] | dict[str, Any]] = None,
121
+ access_list: Optional[AccessList] = None,
121
122
  tx_params: Optional[TxParams] = None,
122
123
  ) -> TxParams:
123
- tx_params_new = _prepare_tx_params(web3, from_address, tx_params)
124
+ tx_params_new = _prepare_tx_params(web3, from_address, access_list, tx_params)
124
125
  contract = web3.eth.contract(address=contract_address, abi=contract_abi)
125
126
 
126
127
  # Build the transaction.
@@ -132,6 +133,7 @@ def prepare_tx(
132
133
  def _prepare_tx_params(
133
134
  web3: Web3,
134
135
  from_address: ChecksumAddress | None,
136
+ access_list: Optional[AccessList] = None,
135
137
  tx_params: Optional[TxParams] = None,
136
138
  ) -> TxParams:
137
139
  # Fill in required defaults, if not provided.
@@ -151,6 +153,9 @@ def _prepare_tx_params(
151
153
  from_checksummed = Web3.to_checksum_address(tx_params_new["from"])
152
154
  tx_params_new["nonce"] = web3.eth.get_transaction_count(from_checksummed)
153
155
 
156
+ if access_list is not None:
157
+ tx_params_new["accessList"] = access_list
158
+
154
159
  return tx_params_new
155
160
 
156
161
 
@@ -211,6 +216,36 @@ def send_function_on_contract_tx_using_safe(
211
216
  tx_params: Optional[TxParams] = None,
212
217
  timeout: int = 180,
213
218
  ) -> TxReceipt:
219
+ if not web3.provider.endpoint_uri: # type: ignore
220
+ raise EnvironmentError("RPC_URL not available in web3 object.")
221
+ ethereum_client = EthereumClient(ethereum_node_url=URI(web3.provider.endpoint_uri)) # type: ignore
222
+ s = Safe(safe_address, ethereum_client) # type: ignore
223
+ safe_master_copy_address = s.retrieve_master_copy_address()
224
+ eoa_public_key = private_key_to_public_key(from_private_key)
225
+ # See https://ethereum.stackexchange.com/questions/123750/how-to-implement-eip-2930-access-list for details,
226
+ # required to not go out-of-gas when calling a contract functions using Safe.
227
+ access_list = AccessList(
228
+ [
229
+ AccessListEntry(
230
+ {
231
+ "address": eoa_public_key,
232
+ "storageKeys": [HASH_ZERO],
233
+ }
234
+ ),
235
+ AccessListEntry(
236
+ {
237
+ "address": safe_address,
238
+ "storageKeys": [HASH_ZERO],
239
+ }
240
+ ),
241
+ AccessListEntry(
242
+ {
243
+ "address": safe_master_copy_address,
244
+ "storageKeys": [],
245
+ }
246
+ ),
247
+ ]
248
+ )
214
249
  tx_params = prepare_tx(
215
250
  web3=web3,
216
251
  contract_address=contract_address,
@@ -218,13 +253,9 @@ def send_function_on_contract_tx_using_safe(
218
253
  from_address=safe_address,
219
254
  function_name=function_name,
220
255
  function_params=function_params,
256
+ access_list=access_list,
221
257
  tx_params=tx_params,
222
258
  )
223
-
224
- if not web3.provider.endpoint_uri: # type: ignore
225
- raise EnvironmentError(f"RPC_URL not available in web3 object.")
226
- ethereum_client = EthereumClient(ethereum_node_url=URI(web3.provider.endpoint_uri)) # type: ignore
227
- s = Safe(safe_address, ethereum_client) # type: ignore
228
259
  safe_tx = s.build_multisig_tx(
229
260
  to=Web3.to_checksum_address(tx_params["to"]),
230
261
  data=HexBytes(tx_params["data"]),
@@ -270,7 +301,7 @@ def send_xdai_to(
270
301
  tx_params_new: TxParams = {"value": value, "to": to_address}
271
302
  if tx_params:
272
303
  tx_params_new.update(tx_params)
273
- tx_params_new = _prepare_tx_params(web3, from_address, tx_params_new)
304
+ tx_params_new = _prepare_tx_params(web3, from_address, tx_params=tx_params_new)
274
305
 
275
306
  # We need gas and gasPrice here (and not elsewhere) because we are not calling
276
307
  # contract.functions.myFunction().build_transaction, which autofills some params
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.48.10
3
+ Version: 0.48.11
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -74,12 +74,12 @@ prediction_market_agent_tooling/tools/parallelism.py,sha256=Rz8QdVUWX8KCbr8UZfaC
74
74
  prediction_market_agent_tooling/tools/safe.py,sha256=h0xOO0eNtitClf0fPkn-0oTc6A_bflDTee98V_aiV-A,5195
75
75
  prediction_market_agent_tooling/tools/singleton.py,sha256=CiIELUiI-OeS7U7eeHEt0rnVhtQGzwoUdAgn_7u_GBM,729
76
76
  prediction_market_agent_tooling/tools/streamlit_user_login.py,sha256=NXEqfjT9Lc9QtliwSGRASIz1opjQ7Btme43H4qJbzgE,3010
77
- prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py,sha256=dr-N-G67f4au6s5xLwZPNbKhe4BFaEuYpQTn0KZ4EKg,4377
78
- prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py,sha256=eln3BygdfsDf8WOlSQPL7qH946QnGnThRkazRZKBA8o,3194
77
+ prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py,sha256=Uq2iyDygVRxp6qHAnz9t5c1uTLGV2RPQE15sVJFLds8,6341
78
+ prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py,sha256=xrtQH9v5pXycBRyc5j45pWqkSffkoc9efNIU1_G633Q,3706
79
79
  prediction_market_agent_tooling/tools/utils.py,sha256=JE9YWtPPhnTgLiOyGAZDNG5K8nCwUY9IZEuAlm9UcxA,6611
80
- prediction_market_agent_tooling/tools/web3_utils.py,sha256=euq_MH-LhTowACq42colks2IXxZQjqjuisYl91EYZtU,10440
81
- prediction_market_agent_tooling-0.48.10.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
82
- prediction_market_agent_tooling-0.48.10.dist-info/METADATA,sha256=KCZBnatFqFzYv_MNiRcnAomqicUKMhxjlEaf5gCdKjc,7811
83
- prediction_market_agent_tooling-0.48.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
84
- prediction_market_agent_tooling-0.48.10.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
85
- prediction_market_agent_tooling-0.48.10.dist-info/RECORD,,
80
+ prediction_market_agent_tooling/tools/web3_utils.py,sha256=IZDxHhUJH5RsaRkK9DW6z1RYdk2cz5RqLMZG3T6Gv1U,11602
81
+ prediction_market_agent_tooling-0.48.11.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
82
+ prediction_market_agent_tooling-0.48.11.dist-info/METADATA,sha256=n7UvoWRzs1H7AAlYVSaVQ5zYXaEwUbkrO-j5Uiaev80,7811
83
+ prediction_market_agent_tooling-0.48.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
84
+ prediction_market_agent_tooling-0.48.11.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
85
+ prediction_market_agent_tooling-0.48.11.dist-info/RECORD,,