prediction-market-agent-tooling 0.39.4__py3-none-any.whl → 0.40.0__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.
@@ -58,14 +58,14 @@ class APIKeys(BaseSettings):
58
58
  "BET_FROM_PRIVATE_KEY missing in the environment.",
59
59
  )
60
60
 
61
+ @property
62
+ def public_key(self) -> ChecksumAddress:
63
+ return private_key_to_public_key(self.bet_from_private_key)
64
+
61
65
  @property
62
66
  def bet_from_address(self) -> ChecksumAddress:
63
67
  """If the SAFE is available, we always route transactions via SAFE. Otherwise we use the EOA."""
64
- return (
65
- self.SAFE_ADDRESS
66
- if self.SAFE_ADDRESS
67
- else private_key_to_public_key(self.bet_from_private_key)
68
- )
68
+ return self.SAFE_ADDRESS if self.SAFE_ADDRESS else self.public_key
69
69
 
70
70
  @property
71
71
  def openai_api_key(self) -> SecretStr:
@@ -22,7 +22,7 @@ from prediction_market_agent_tooling.deploy.gcp.utils import (
22
22
  gcp_function_is_active,
23
23
  gcp_resolve_api_keys_secrets,
24
24
  )
25
- from prediction_market_agent_tooling.gtypes import Probability
25
+ from prediction_market_agent_tooling.gtypes import Probability, xdai_type
26
26
  from prediction_market_agent_tooling.loggers import logger
27
27
  from prediction_market_agent_tooling.markets.agent_market import (
28
28
  AgentMarket,
@@ -36,6 +36,7 @@ from prediction_market_agent_tooling.markets.markets import (
36
36
  )
37
37
  from prediction_market_agent_tooling.markets.omen.omen import (
38
38
  redeem_from_all_user_positions,
39
+ withdraw_wxdai_to_xdai_to_keep_balance,
39
40
  )
40
41
  from prediction_market_agent_tooling.monitor.langfuse.langfuse_wrapper import (
41
42
  LangfuseWrapper,
@@ -260,9 +261,14 @@ class DeployableTraderAgent(DeployableAgent):
260
261
  """
261
262
  Executes actions that occur before bets are placed.
262
263
  """
264
+ api_keys = APIKeys()
263
265
  if market_type == MarketType.OMEN:
264
266
  # Omen is specific, because the user (agent) needs to manually withdraw winnings from the market.
265
- redeem_from_all_user_positions(APIKeys())
267
+ redeem_from_all_user_positions(api_keys)
268
+ # Exchange wxdai back to xdai if the balance is getting low, so we can keep paying for fees.
269
+ withdraw_wxdai_to_xdai_to_keep_balance(
270
+ api_keys, min_required_balance=xdai_type(1), withdraw_multiplier=2
271
+ )
266
272
 
267
273
  def process_bets(self, market_type: MarketType) -> None:
268
274
  """
@@ -2,7 +2,7 @@ from datetime import datetime
2
2
  from enum import Enum
3
3
  from typing import TypeAlias
4
4
 
5
- from pydantic import BaseModel
5
+ from pydantic import BaseModel, computed_field
6
6
 
7
7
  from prediction_market_agent_tooling.gtypes import OutcomeStr
8
8
 
@@ -41,6 +41,7 @@ class ResolvedBet(Bet):
41
41
  resolved_time: datetime
42
42
  profit: ProfitAmount
43
43
 
44
+ @computed_field # type: ignore[misc]
44
45
  @property
45
46
  def is_correct(self) -> bool:
46
47
  return self.outcome == self.market_outcome
@@ -150,7 +150,7 @@ class ManifoldBet(BaseModel):
150
150
  id: str
151
151
  fees: ManifoldBetFees
152
152
  isCancelled: t.Optional[bool] = None
153
- loanAmount: Mana
153
+ loanAmount: Mana | None
154
154
  orderAmount: t.Optional[Mana] = None
155
155
  fills: t.Optional[list[ManifoldBetFills]] = None
156
156
  createdTime: datetime
@@ -1000,3 +1000,40 @@ def get_binary_market_p_yes_history(market: OmenAgentMarket) -> list[Probability
1000
1000
  )
1001
1001
 
1002
1002
  return history
1003
+
1004
+
1005
+ def withdraw_wxdai_to_xdai_to_keep_balance(
1006
+ api_keys: APIKeys,
1007
+ min_required_balance: xDai,
1008
+ withdraw_multiplier: float = 1.0,
1009
+ web3: Web3 | None = None,
1010
+ ) -> None:
1011
+ """
1012
+ Keeps xDai balance above the minimum required balance by withdrawing wxDai to xDai.
1013
+ Optionally, the amount to withdraw can be multiplied by the `withdraw_multiplier`, which can be useful to keep a buffer.
1014
+ """
1015
+ # xDai needs to be in our wallet where we pay transaction fees, so do not check for Safe's balance.
1016
+ current_balances = get_balances(api_keys.public_key, web3)
1017
+
1018
+ if current_balances.xdai >= min_required_balance:
1019
+ logger.info(
1020
+ f"Current xDai balance {current_balances.xdai} is more or equal than the required minimum balance {min_required_balance}."
1021
+ )
1022
+ return
1023
+
1024
+ need_to_withdraw = xDai(
1025
+ (min_required_balance - current_balances.xdai) * withdraw_multiplier
1026
+ )
1027
+
1028
+ if current_balances.wxdai < need_to_withdraw:
1029
+ raise ValueError(
1030
+ f"Current wxDai balance {current_balances.wxdai} is less than the required minimum wxDai to withdraw {need_to_withdraw}."
1031
+ )
1032
+
1033
+ collateral_token_contract = OmenCollateralTokenContract()
1034
+ collateral_token_contract.withdraw(
1035
+ api_keys=api_keys, amount_wei=xdai_to_wei(need_to_withdraw), web3=web3
1036
+ )
1037
+ logger.info(
1038
+ f"Withdrew {need_to_withdraw} wxDai to keep the balance above the minimum required balance {min_required_balance}."
1039
+ )
@@ -630,6 +630,10 @@ class OmenThumbnailMapping(ContractOnGnosisChain):
630
630
  "0xe0cf08311F03850497B0ed6A2cf067f1750C3eFc"
631
631
  )
632
632
 
633
+ @staticmethod
634
+ def construct_ipfs_url(ipfs_hash: IPFSCIDVersion0) -> str:
635
+ return f"https://ipfs.io/ipfs/{ipfs_hash}"
636
+
633
637
  def get(
634
638
  self,
635
639
  market_address: ChecksumAddress,
@@ -646,7 +650,7 @@ class OmenThumbnailMapping(ContractOnGnosisChain):
646
650
  web3: Web3 | None = None,
647
651
  ) -> str | None:
648
652
  hash_ = self.get(market_address, web3)
649
- return f"https://ipfs.io/ipfs/{hash_}" if hash_ is not None else None
653
+ return self.construct_ipfs_url(hash_) if hash_ is not None else None
650
654
 
651
655
  def set(
652
656
  self,
@@ -2,8 +2,11 @@ import sys
2
2
  import typing as t
3
3
  from datetime import datetime
4
4
 
5
+ import requests
5
6
  import tenacity
6
7
  from eth_typing import ChecksumAddress
8
+ from PIL import Image
9
+ from PIL.Image import Image as ImageType
7
10
  from subgrounds import FieldPath, Subgrounds
8
11
 
9
12
  from prediction_market_agent_tooling.config import APIKeys
@@ -20,9 +23,15 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
20
23
  RealityAnswer,
21
24
  RealityQuestion,
22
25
  )
26
+ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
27
+ OmenThumbnailMapping,
28
+ )
23
29
  from prediction_market_agent_tooling.tools.singleton import SingletonMeta
24
30
  from prediction_market_agent_tooling.tools.utils import to_int_timestamp, utcnow
25
- from prediction_market_agent_tooling.tools.web3_utils import ZERO_BYTES
31
+ from prediction_market_agent_tooling.tools.web3_utils import (
32
+ ZERO_BYTES,
33
+ byte32_to_ipfscidv0,
34
+ )
26
35
 
27
36
 
28
37
  class OmenSubgraphHandler(metaclass=SingletonMeta):
@@ -36,6 +45,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
36
45
 
37
46
  REALITYETH_GRAPH_URL = "https://gateway-arbitrum.network.thegraph.com/api/{graph_api_key}/subgraphs/id/E7ymrCnNcQdAAgLbdFWzGE5mvr5Mb5T9VfT43FqA7bNh"
38
47
 
48
+ # TODO: Switch to arbitrum subgraph once it's published.
49
+ OMEN_IMAGE_MAPPING_GRAPH_URL = (
50
+ "https://api.studio.thegraph.com/query/63564/omen-thumbnailmapping/v0.0.3"
51
+ )
52
+
39
53
  INVALID_ANSWER = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
40
54
 
41
55
  def __init__(self) -> None:
@@ -66,6 +80,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
66
80
  graph_api_key=keys.graph_api_key.get_secret_value()
67
81
  )
68
82
  )
83
+ self.omen_image_mapping_subgraph = self.sg.load_subgraph(
84
+ self.OMEN_IMAGE_MAPPING_GRAPH_URL.format(
85
+ graph_api_key=keys.graph_api_key.get_secret_value()
86
+ )
87
+ )
69
88
 
70
89
  def _get_fields_for_bets(self, bets_field: FieldPath) -> list[FieldPath]:
71
90
  markets = bets_field.fpmm
@@ -609,3 +628,23 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
609
628
  f"Incorrect number of markets fetched {len(markets)}, expected 1."
610
629
  )
611
630
  return markets[0]
631
+
632
+ def get_market_image_url(self, market_id: HexAddress) -> str | None:
633
+ image = self.omen_image_mapping_subgraph.Query.omenThumbnailMapping(
634
+ id=market_id.lower()
635
+ )
636
+ fields = [image.id, image.image_hash]
637
+ result = self.sg.query_json(fields)
638
+ items = self._parse_items_from_json(result)
639
+ if not items:
640
+ return None
641
+ parsed = byte32_to_ipfscidv0(HexBytes(items[0]["image_hash"]))
642
+ return OmenThumbnailMapping.construct_ipfs_url(parsed)
643
+
644
+ def get_market_image(self, market_id: HexAddress) -> ImageType | None:
645
+ image_url = self.get_market_image_url(market_id)
646
+ return (
647
+ Image.open(requests.get(image_url, stream=True).raw)
648
+ if image_url is not None
649
+ else None
650
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.39.4
3
+ Version: 0.40.0
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -12,8 +12,8 @@ prediction_market_agent_tooling/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-
12
12
  prediction_market_agent_tooling/benchmark/agents.py,sha256=HPIFJvackW110ch3UkktbxhU48gMRVo4gQse84Klhdc,4000
13
13
  prediction_market_agent_tooling/benchmark/benchmark.py,sha256=xiHKzZx5GHSsDerFHMZ9j_LXAXnSaITSvv67iPe3MEU,21095
14
14
  prediction_market_agent_tooling/benchmark/utils.py,sha256=iS1BzyXcCMfMm1Rx--1QCH0pHvBTblTndcDQFbTUJ2s,2897
15
- prediction_market_agent_tooling/config.py,sha256=pTeV4mbvPmrS_MzmiBklg05_gtsR3pa9Id5HCS-AzKQ,4519
16
- prediction_market_agent_tooling/deploy/agent.py,sha256=h33uU97x3DjBy8INONtS1Hc5B-NnNDV6MENeeCp0qoA,10185
15
+ prediction_market_agent_tooling/config.py,sha256=kIluGnzhBWIs6DIEoBXbRcIEKaEDU39kVAa3lbIOWlY,4562
16
+ prediction_market_agent_tooling/deploy/agent.py,sha256=TXuQ0L2-dG0tIrJ7srxD3Hbabe_2gILfdBQI-tkl9Og,10522
17
17
  prediction_market_agent_tooling/deploy/agent_example.py,sha256=tqXVA2HSFK3pdZ49tMmta8aKdJFT8JN8WeJ1akjrpBk,909
18
18
  prediction_market_agent_tooling/deploy/constants.py,sha256=M5ty8URipYMGe_G-RzxRydK3AFL6CyvmqCraJUrLBnE,82
19
19
  prediction_market_agent_tooling/deploy/gcp/deploy.py,sha256=CYUgnfy-9XVk04kkxA_5yp0GE9Mw5caYqlFUZQ2j3ks,3739
@@ -23,19 +23,19 @@ prediction_market_agent_tooling/gtypes.py,sha256=lbV2nsPyhMIRI9olx0_6A06jwTWKYBP
23
23
  prediction_market_agent_tooling/loggers.py,sha256=ua9rynYmsbOJZjxPIFxRBooomeN08zuLSJ7lxZMDS7w,3133
24
24
  prediction_market_agent_tooling/markets/agent_market.py,sha256=ZpBpNLqY2QXTAdmkCr8-L3yjN70H_y-KiCptx3OFQgM,8099
25
25
  prediction_market_agent_tooling/markets/categorize.py,sha256=yTd-lDMPW4ESDSzmxeLLBuzLX0FggOF7Vbswh7295o0,941
26
- prediction_market_agent_tooling/markets/data_models.py,sha256=6J8tyq-ZJI2HknqJolDCMfWXVXZsdBq3EhVQeIiT6bY,1418
26
+ prediction_market_agent_tooling/markets/data_models.py,sha256=IYI8fne-OA18ZP1lcXySEo9rcJHYv3wZrUvJziSaHew,1476
27
27
  prediction_market_agent_tooling/markets/manifold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  prediction_market_agent_tooling/markets/manifold/api.py,sha256=m6qOzDiyQfxj62Eo_SzzQLkX4ijpi8KtQKGd4CpKAsk,7307
29
- prediction_market_agent_tooling/markets/manifold/data_models.py,sha256=Iw-ajDPYhtfcTfN45nJN_kZShfWcWe9mgzexSWnQCCQ,5295
29
+ prediction_market_agent_tooling/markets/manifold/data_models.py,sha256=xoCqxk9cO6MZ_px_SEGYZ8hHyhGh-X6QDC8dDhyF3rk,5302
30
30
  prediction_market_agent_tooling/markets/manifold/manifold.py,sha256=EwRL06E2Y_ZAzr8efwS5yD6p6rnykrcBhqmNDUGZ8Aw,4075
31
31
  prediction_market_agent_tooling/markets/manifold/utils.py,sha256=cPPFWXm3vCYH1jy7_ctJZuQH9ZDaPL4_AgAYzGWkoow,513
32
32
  prediction_market_agent_tooling/markets/markets.py,sha256=w05Oo7yCA2axpCw69Q9y4i9Gcdpht0u5bZGbWqld3rU,2964
33
33
  prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  prediction_market_agent_tooling/markets/omen/data_models.py,sha256=EXtjmcujx68Xu50BVkYXvLuf_Asx5o65RvFS3ZS6HGs,14405
35
- prediction_market_agent_tooling/markets/omen/omen.py,sha256=dMun3MvkvEVrBmN2NwCCb1Uq3kd9nePe1FhFBgHHcj0,36868
36
- prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=LlslAHfDkGytOje_ZMJDURAv2geAjInDAOnlteNFI0A,21722
35
+ prediction_market_agent_tooling/markets/omen/omen.py,sha256=NtbfiaUQsN0zi7CYbBcQbasc32Dx7OmtIVMv-aXZtbk,38349
36
+ prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=JGXCO9MIVr-DGyoH2sxReAw7ZDTC_ev0UxDpq1QBv5Q,21854
37
37
  prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=g77QsQ5WnSI2rzBlX87L_EhWMwobkyXyfRhHQmpAdzo,9012
38
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=35cRqXuU4DvP5weYKcFNpJXhbaC1cfNBSfOYeO2HagE,23833
38
+ prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=cwimJjzWw7GNXYj_79ztgJawlwJQzf4Q9BPAtqByRFY,25248
39
39
  prediction_market_agent_tooling/markets/polymarket/api.py,sha256=HXmA1akA0qDj0m3e-GEvWG8x75pm6BX4H7YJPQcST7I,4767
40
40
  prediction_market_agent_tooling/markets/polymarket/data_models.py,sha256=9CJzakyEcsn6DQBK2nOXjOMzTZBLAmK_KqevXvW17DI,4292
41
41
  prediction_market_agent_tooling/markets/polymarket/data_models_web.py,sha256=f8SRQy0Rn-gIHSEMrJJAI8H3J7l8lzOLj3aCMe0vJv8,11324
@@ -69,8 +69,8 @@ prediction_market_agent_tooling/tools/singleton.py,sha256=CiIELUiI-OeS7U7eeHEt0r
69
69
  prediction_market_agent_tooling/tools/streamlit_user_login.py,sha256=NXEqfjT9Lc9QtliwSGRASIz1opjQ7Btme43H4qJbzgE,3010
70
70
  prediction_market_agent_tooling/tools/utils.py,sha256=-G22UEbCRm59bm1RWFdeF55hRsaxgwZVAHvK32-Ye1g,6190
71
71
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=nKRHmdLnWSKd3wpo-cysXGvhhrJ2Yf69sN2FFQfSt6s,10578
72
- prediction_market_agent_tooling-0.39.4.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
73
- prediction_market_agent_tooling-0.39.4.dist-info/METADATA,sha256=krPaT1l3JTNUQFg-BDEz7Mg-_w6G0CytIYt69rgSCWc,7634
74
- prediction_market_agent_tooling-0.39.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
75
- prediction_market_agent_tooling-0.39.4.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
76
- prediction_market_agent_tooling-0.39.4.dist-info/RECORD,,
72
+ prediction_market_agent_tooling-0.40.0.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
73
+ prediction_market_agent_tooling-0.40.0.dist-info/METADATA,sha256=Jok34BfwM81xbX25ug6pvRUb1a0ch8-vXpHJyNTGQs0,7634
74
+ prediction_market_agent_tooling-0.40.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
75
+ prediction_market_agent_tooling-0.40.0.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
76
+ prediction_market_agent_tooling-0.40.0.dist-info/RECORD,,