prediction-market-agent-tooling 0.48.9__tar.gz → 0.48.11__tar.gz

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.
Files changed (84) hide show
  1. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/PKG-INFO +1 -1
  2. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +46 -8
  3. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py +50 -3
  4. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py +15 -0
  5. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/web3_utils.py +39 -8
  6. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/pyproject.toml +1 -1
  7. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/LICENSE +0 -0
  8. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/README.md +0 -0
  9. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  10. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  11. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  12. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  13. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  14. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  15. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  16. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  17. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  18. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  19. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  20. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  21. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  22. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  23. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  24. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  25. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/config.py +0 -0
  26. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/deploy/agent.py +0 -0
  27. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  28. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/deploy/betting_strategy.py +0 -0
  29. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  30. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  31. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  32. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  33. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/gtypes.py +0 -0
  34. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/loggers.py +0 -0
  35. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
  36. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  37. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/data_models.py +0 -0
  38. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  39. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  40. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  41. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  42. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  43. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/markets.py +0 -0
  44. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  45. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
  46. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
  47. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  48. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/omen/data_models.py +0 -0
  49. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/omen/omen.py +0 -0
  50. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
  51. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
  52. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
  53. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  54. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  55. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  56. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  57. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
  58. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -0
  59. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
  60. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
  61. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/monitor/monitor.py +0 -0
  62. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/monitor/monitor_app.py +0 -0
  63. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
  64. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/py.typed +0 -0
  65. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/balances.py +0 -0
  66. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
  67. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
  68. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
  69. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  70. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/cache.py +0 -0
  71. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/contract.py +0 -0
  72. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/costs.py +0 -0
  73. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -0
  74. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/google.py +0 -0
  75. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  76. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  77. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  78. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  79. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  80. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  81. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/safe.py +0 -0
  82. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  83. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  84. {prediction_market_agent_tooling-0.48.9 → prediction_market_agent_tooling-0.48.11}/prediction_market_agent_tooling/tools/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.48.9
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
@@ -608,21 +608,25 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
608
608
  )
609
609
  return [b for b in bets if b.fpmm.is_resolved_with_valid_answer]
610
610
 
611
- def get_questions(
612
- self,
611
+ @staticmethod
612
+ def get_reality_question_filters(
613
613
  user: HexAddress | None = None,
614
614
  claimed: bool | None = None,
615
615
  current_answer_before: datetime | None = None,
616
616
  finalized_before: datetime | None = None,
617
617
  finalized_after: datetime | None = None,
618
618
  id_in: list[str] | None = None,
619
+ question_id: HexBytes | None = None,
619
620
  question_id_in: list[HexBytes] | None = None,
620
- ) -> list[RealityQuestion]:
621
+ ) -> dict[str, t.Any]:
621
622
  where_stms: dict[str, t.Any] = {}
622
623
 
623
624
  if user is not None:
624
625
  where_stms["user"] = user.lower()
625
626
 
627
+ if question_id is not None:
628
+ where_stms["questionId"] = question_id.hex()
629
+
626
630
  if claimed is not None:
627
631
  if claimed:
628
632
  where_stms["historyHash"] = ZERO_BYTES.hex()
@@ -650,6 +654,27 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
650
654
  if question_id_in is not None:
651
655
  where_stms["questionId_in"] = [x.hex() for x in question_id_in]
652
656
 
657
+ return where_stms
658
+
659
+ def get_questions(
660
+ self,
661
+ user: HexAddress | None = None,
662
+ claimed: bool | None = None,
663
+ current_answer_before: datetime | None = None,
664
+ finalized_before: datetime | None = None,
665
+ finalized_after: datetime | None = None,
666
+ id_in: list[str] | None = None,
667
+ question_id_in: list[HexBytes] | None = None,
668
+ ) -> list[RealityQuestion]:
669
+ where_stms: dict[str, t.Any] = self.get_reality_question_filters(
670
+ user=user,
671
+ claimed=claimed,
672
+ finalized_before=finalized_before,
673
+ finalized_after=finalized_after,
674
+ current_answer_before=current_answer_before,
675
+ id_in=id_in,
676
+ question_id_in=question_id_in,
677
+ )
653
678
  questions = self.realityeth_subgraph.Query.questions(where=where_stms)
654
679
  fields = self._get_fields_for_reality_questions(questions)
655
680
  result = self.sg.query_json(fields)
@@ -669,11 +694,24 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
669
694
  items = self._parse_items_from_json(result)
670
695
  return [RealityAnswer.model_validate(i) for i in items]
671
696
 
672
- def get_responses(self, question_id: HexBytes) -> list[RealityResponse]:
673
- response = self.realityeth_subgraph.Response
674
- where_stms = [
675
- response.question.questionId == question_id.hex(),
676
- ]
697
+ def get_responses(
698
+ self,
699
+ user: HexAddress | None = None,
700
+ question_id: HexBytes | None = None,
701
+ question_claimed: bool | None = None,
702
+ question_finalized_before: datetime | None = None,
703
+ ) -> list[RealityResponse]:
704
+ where_stms: dict[str, t.Any] = {}
705
+
706
+ if user is not None:
707
+ where_stms["user"] = user.lower()
708
+
709
+ where_stms["question_"] = self.get_reality_question_filters(
710
+ question_id=question_id,
711
+ claimed=question_claimed,
712
+ finalized_before=question_finalized_before,
713
+ )
714
+
677
715
  responses = self.realityeth_subgraph.Query.responses(where=where_stms)
678
716
  fields = self._get_fields_for_responses(responses)
679
717
  result = self.sg.query_json(fields)
@@ -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
  [tool.poetry]
2
2
  name = "prediction-market-agent-tooling"
3
- version = "0.48.9"
3
+ version = "0.48.11"
4
4
  description = "Tools to benchmark, deploy and monitor prediction market agents."
5
5
  authors = ["Gnosis"]
6
6
  readme = "README.md"