prediction-market-agent-tooling 0.68.0.dev999__py3-none-any.whl → 0.69.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.
Files changed (42) hide show
  1. prediction_market_agent_tooling/chains.py +1 -0
  2. prediction_market_agent_tooling/config.py +37 -2
  3. prediction_market_agent_tooling/deploy/agent.py +26 -21
  4. prediction_market_agent_tooling/deploy/betting_strategy.py +133 -22
  5. prediction_market_agent_tooling/jobs/jobs_models.py +2 -2
  6. prediction_market_agent_tooling/jobs/omen/omen_jobs.py +17 -20
  7. prediction_market_agent_tooling/markets/agent_market.py +27 -9
  8. prediction_market_agent_tooling/markets/blockchain_utils.py +3 -3
  9. prediction_market_agent_tooling/markets/markets.py +16 -0
  10. prediction_market_agent_tooling/markets/omen/data_models.py +3 -18
  11. prediction_market_agent_tooling/markets/omen/omen.py +26 -11
  12. prediction_market_agent_tooling/markets/omen/omen_contracts.py +2 -196
  13. prediction_market_agent_tooling/markets/omen/omen_resolving.py +2 -2
  14. prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +13 -11
  15. prediction_market_agent_tooling/markets/polymarket/api.py +35 -1
  16. prediction_market_agent_tooling/markets/polymarket/clob_manager.py +156 -0
  17. prediction_market_agent_tooling/markets/polymarket/constants.py +15 -0
  18. prediction_market_agent_tooling/markets/polymarket/data_models.py +33 -5
  19. prediction_market_agent_tooling/markets/polymarket/polymarket.py +247 -18
  20. prediction_market_agent_tooling/markets/polymarket/polymarket_contracts.py +35 -0
  21. prediction_market_agent_tooling/markets/polymarket/polymarket_subgraph_handler.py +2 -1
  22. prediction_market_agent_tooling/markets/seer/data_models.py +41 -6
  23. prediction_market_agent_tooling/markets/seer/price_manager.py +69 -1
  24. prediction_market_agent_tooling/markets/seer/seer.py +77 -26
  25. prediction_market_agent_tooling/markets/seer/seer_api.py +28 -0
  26. prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +71 -20
  27. prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +67 -0
  28. prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +17 -22
  29. prediction_market_agent_tooling/tools/contract.py +236 -4
  30. prediction_market_agent_tooling/tools/cow/cow_order.py +13 -8
  31. prediction_market_agent_tooling/tools/datetime_utc.py +14 -2
  32. prediction_market_agent_tooling/tools/hexbytes_custom.py +3 -9
  33. prediction_market_agent_tooling/tools/langfuse_client_utils.py +17 -5
  34. prediction_market_agent_tooling/tools/tokens/auto_deposit.py +2 -2
  35. prediction_market_agent_tooling/tools/tokens/usd.py +5 -2
  36. prediction_market_agent_tooling/tools/web3_utils.py +9 -4
  37. {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/METADATA +8 -7
  38. {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/RECORD +41 -38
  39. prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -366
  40. {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/LICENSE +0 -0
  41. {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/WHEEL +0 -0
  42. {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/entry_points.txt +0 -0
@@ -23,6 +23,7 @@ from prediction_market_agent_tooling.gtypes import (
23
23
  OutcomeWei,
24
24
  Probability,
25
25
  Wei,
26
+ xDai,
26
27
  )
27
28
  from prediction_market_agent_tooling.markets.data_models import (
28
29
  USD,
@@ -44,9 +45,6 @@ from prediction_market_agent_tooling.tools.utils import (
44
45
 
45
46
  class ProcessedMarket(BaseModel):
46
47
  answer: CategoricalProbabilisticAnswer
47
-
48
-
49
- class ProcessedTradedMarket(ProcessedMarket):
50
48
  trades: list[PlacedTrade]
51
49
 
52
50
 
@@ -190,6 +188,17 @@ class AgentMarket(BaseModel):
190
188
  f"Could not find probability for market outcome {market_outcome}"
191
189
  )
192
190
 
191
+ @property
192
+ def question_type(self) -> QuestionType:
193
+ if self.is_binary:
194
+ return QuestionType.BINARY
195
+
196
+ elif self.is_scalar:
197
+ return QuestionType.SCALAR
198
+
199
+ else:
200
+ return QuestionType.CATEGORICAL
201
+
193
202
  @property
194
203
  def is_binary(self) -> bool:
195
204
  # 3 outcomes can also be binary if 3rd outcome is invalid (Seer)
@@ -450,7 +459,7 @@ class AgentMarket(BaseModel):
450
459
 
451
460
  def store_trades(
452
461
  self,
453
- traded_market: ProcessedTradedMarket | None,
462
+ traded_market: ProcessedMarket | None,
454
463
  keys: APIKeys,
455
464
  agent_name: str,
456
465
  web3: Web3 | None = None,
@@ -509,11 +518,20 @@ class AgentMarket(BaseModel):
509
518
  )
510
519
 
511
520
  def get_outcome_index(self, outcome: OutcomeStr) -> int:
512
- outcomes_lowercase = [o.lower() for o in self.outcomes]
521
+ """Get the index of the given outcome in the market's outcomes."""
513
522
  try:
514
- return outcomes_lowercase.index(outcome.lower())
515
- except ValueError:
516
- raise ValueError(f"Outcome `{outcome}` not found in `{self.outcomes}`.")
523
+ return [o.lower() for o in self.outcomes].index(outcome.lower())
524
+ except ValueError as e:
525
+ raise ValueError(
526
+ f"Outcome '{outcome}' not found in market outcomes: {self.outcomes}"
527
+ ) from e
528
+
529
+ def ensure_min_native_balance(
530
+ self,
531
+ min_required_balance: xDai,
532
+ multiplier: float = 3.0,
533
+ ) -> None:
534
+ raise NotImplementedError("Subclass must implement this method")
517
535
 
518
536
  def get_token_balance(self, user_id: str, outcome: OutcomeStr) -> OutcomeToken:
519
537
  raise NotImplementedError("Subclasses must implement this method")
@@ -562,7 +580,7 @@ class AgentMarket(BaseModel):
562
580
 
563
581
  @staticmethod
564
582
  def get_user_id(api_keys: APIKeys) -> str:
565
- raise NotImplementedError("Subclasses must implement this method")
583
+ return api_keys.bet_from_address
566
584
 
567
585
  def get_most_recent_trade_datetime(self, user_id: str) -> DatetimeUTC | None:
568
586
  raise NotImplementedError("Subclasses must implement this method")
@@ -11,7 +11,7 @@ from prediction_market_agent_tooling.gtypes import (
11
11
  OutcomeStr,
12
12
  )
13
13
  from prediction_market_agent_tooling.loggers import logger
14
- from prediction_market_agent_tooling.markets.agent_market import ProcessedTradedMarket
14
+ from prediction_market_agent_tooling.markets.agent_market import ProcessedMarket
15
15
  from prediction_market_agent_tooling.markets.omen.data_models import (
16
16
  ContractPrediction,
17
17
  IPFSAgentResult,
@@ -28,7 +28,7 @@ def store_trades(
28
28
  contract: _AgentResultMappingContract,
29
29
  market_id: ChecksumAddress,
30
30
  outcomes: Sequence[OutcomeStr],
31
- traded_market: ProcessedTradedMarket | None,
31
+ traded_market: ProcessedMarket | None,
32
32
  keys: APIKeys,
33
33
  agent_name: str,
34
34
  web3: Web3 | None = None,
@@ -83,5 +83,5 @@ def store_trades(
83
83
  web3=web3,
84
84
  )
85
85
  logger.info(
86
- f"Added prediction to market {market_id}. - receipt {tx_receipt['transactionHash'].hex()}."
86
+ f"Added prediction to market {market_id}. - receipt {tx_receipt['transactionHash'].to_0x_hex()}."
87
87
  )
@@ -31,6 +31,10 @@ class MarketType(str, Enum):
31
31
  METACULUS = "metaculus"
32
32
  SEER = "seer"
33
33
 
34
+ @staticmethod
35
+ def from_market(market: AgentMarket) -> "MarketType":
36
+ return AGENT_MARKET_TO_MARKET_TYPE[type(market)]
37
+
34
38
  @property
35
39
  def market_class(self) -> type[AgentMarket]:
36
40
  if self not in MARKET_TYPE_TO_AGENT_MARKET:
@@ -43,6 +47,15 @@ class MarketType(str, Enum):
43
47
  raise ValueError(f"Unknown market type: {self}")
44
48
  return JOB_MARKET_TYPE_TO_JOB_AGENT_MARKET[self]
45
49
 
50
+ @property
51
+ def is_trading_market(self) -> bool:
52
+ return self in [
53
+ MarketType.OMEN,
54
+ MarketType.POLYMARKET,
55
+ MarketType.SEER,
56
+ MarketType.MANIFOLD,
57
+ ]
58
+
46
59
  @property
47
60
  def is_blockchain_market(self) -> bool:
48
61
  return self in [MarketType.OMEN, MarketType.POLYMARKET, MarketType.SEER]
@@ -56,6 +69,9 @@ MARKET_TYPE_TO_AGENT_MARKET: dict[MarketType, type[AgentMarket]] = {
56
69
  MarketType.SEER: SeerAgentMarket,
57
70
  }
58
71
 
72
+ AGENT_MARKET_TO_MARKET_TYPE: dict[type[AgentMarket], MarketType] = {
73
+ v: k for k, v in MARKET_TYPE_TO_AGENT_MARKET.items()
74
+ }
59
75
 
60
76
  JOB_MARKET_TYPE_TO_JOB_AGENT_MARKET: dict[MarketType, type[JobAgentMarket]] = {
61
77
  MarketType.OMEN: OmenJobAgentMarket,
@@ -28,6 +28,7 @@ from prediction_market_agent_tooling.markets.omen.omen_constants import (
28
28
  OMEN_TRUE_OUTCOME,
29
29
  )
30
30
  from prediction_market_agent_tooling.tools.contract import (
31
+ ConditionPreparationEvent,
31
32
  ContractERC20OnGnosisChain,
32
33
  init_collateral_token_contract,
33
34
  to_gnosis_chain_contract,
@@ -47,7 +48,7 @@ OMEN_BINARY_MARKET_OUTCOMES: t.Sequence[OutcomeStr] = [
47
48
  ]
48
49
  INVALID_ANSWER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
49
50
  INVALID_ANSWER_HEX_BYTES = HexBytes(INVALID_ANSWER)
50
- INVALID_ANSWER_STR = HexStr(INVALID_ANSWER_HEX_BYTES.hex())
51
+ INVALID_ANSWER_STR = HexStr(INVALID_ANSWER_HEX_BYTES.to_0x_hex())
51
52
  OMEN_BASE_URL = "https://aiomen.eth.limo"
52
53
  PRESAGIO_BASE_URL = "https://presagio.pages.dev"
53
54
  TEST_CATEGORY = "test" # This category is hidden on Presagio for testing purposes.
@@ -594,7 +595,7 @@ class OmenBet(BaseModel):
594
595
  )
595
596
 
596
597
  return ResolvedBet(
597
- id=self.transactionHash.hex(),
598
+ id=self.transactionHash.to_0x_hex(),
598
599
  # Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
599
600
  amount=self.collateral_amount_token,
600
601
  outcome=self.fpmm.outcomes[self.outcomeIndex],
@@ -795,13 +796,6 @@ class OmenFixedProductMarketMakerCreationEvent(BaseModel):
795
796
  return Web3.to_checksum_address(self.collateralToken)
796
797
 
797
798
 
798
- class ConditionPreparationEvent(BaseModel):
799
- conditionId: HexBytes
800
- oracle: HexAddress
801
- questionId: HexBytes
802
- outcomeSlotCount: int
803
-
804
-
805
799
  class FPMMFundingAddedEvent(BaseModel):
806
800
  funder: HexAddress
807
801
  amountsAdded: list[Wei]
@@ -895,12 +889,3 @@ class IPFSAgentResult(BaseModel):
895
889
  model_config = ConfigDict(
896
890
  extra="forbid",
897
891
  )
898
-
899
-
900
- class PayoutRedemptionEvent(BaseModel):
901
- redeemer: HexAddress
902
- collateralToken: HexAddress
903
- parentCollectionId: HexBytes
904
- conditionId: HexBytes
905
- indexSets: list[int]
906
- payout: Wei
@@ -6,6 +6,7 @@ import tenacity
6
6
  from pydantic import BaseModel
7
7
  from tqdm import tqdm
8
8
  from web3 import Web3
9
+ from web3.constants import HASH_ZERO
9
10
 
10
11
  from prediction_market_agent_tooling.config import APIKeys
11
12
  from prediction_market_agent_tooling.gtypes import (
@@ -28,7 +29,6 @@ from prediction_market_agent_tooling.markets.agent_market import (
28
29
  FilterBy,
29
30
  MarketFees,
30
31
  ProcessedMarket,
31
- ProcessedTradedMarket,
32
32
  QuestionType,
33
33
  SortBy,
34
34
  )
@@ -43,7 +43,6 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
43
43
  OMEN_TRUE_OUTCOME,
44
44
  PRESAGIO_BASE_URL,
45
45
  Condition,
46
- ConditionPreparationEvent,
47
46
  CreatedMarket,
48
47
  OmenBet,
49
48
  OmenMarket,
@@ -60,13 +59,13 @@ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
60
59
  OmenOracleContract,
61
60
  OmenRealitioContract,
62
61
  WrappedxDaiContract,
63
- build_parent_collection_id,
64
62
  )
65
63
  from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
66
64
  OmenSubgraphHandler,
67
65
  )
68
66
  from prediction_market_agent_tooling.tools.balances import get_balances
69
67
  from prediction_market_agent_tooling.tools.contract import (
68
+ ConditionPreparationEvent,
70
69
  init_collateral_token_contract,
71
70
  to_gnosis_chain_contract,
72
71
  )
@@ -411,6 +410,26 @@ class OmenAgentMarket(AgentMarket):
411
410
  def redeem_winnings(api_keys: APIKeys) -> None:
412
411
  redeem_from_all_user_positions(api_keys)
413
412
 
413
+ def ensure_min_native_balance(
414
+ self,
415
+ min_required_balance: xDai,
416
+ multiplier: float = 3.0,
417
+ ) -> None:
418
+ """
419
+ Ensure the EOA has at least the minimum required native token balance.
420
+ If not, transfer wrapped native tokens from the betting address and unwrap them.
421
+
422
+ Args:
423
+ min_required_balance: Minimum required native token balance to maintain
424
+ multiplier: Multiplier to apply to the required balance to keep as a buffer
425
+ """
426
+
427
+ send_keeping_token_to_eoa_xdai(
428
+ api_keys=APIKeys(),
429
+ min_required_balance=min_required_balance,
430
+ multiplier=multiplier,
431
+ )
432
+
414
433
  @staticmethod
415
434
  def get_trade_balance(api_keys: APIKeys, web3: Web3 | None = None) -> USD:
416
435
  native_usd = get_xdai_in_usd(
@@ -438,7 +457,7 @@ class OmenAgentMarket(AgentMarket):
438
457
 
439
458
  def store_trades(
440
459
  self,
441
- traded_market: ProcessedTradedMarket | None,
460
+ traded_market: ProcessedMarket | None,
442
461
  keys: APIKeys,
443
462
  agent_name: str,
444
463
  web3: Web3 | None = None,
@@ -653,10 +672,6 @@ class OmenAgentMarket(AgentMarket):
653
672
  def get_user_balance(user_id: str) -> float:
654
673
  return float(get_balances(Web3.to_checksum_address(user_id)).total)
655
674
 
656
- @staticmethod
657
- def get_user_id(api_keys: APIKeys) -> str:
658
- return api_keys.bet_from_address
659
-
660
675
  def get_most_recent_trade_datetime(self, user_id: str) -> DatetimeUTC | None:
661
676
  sgh = OmenSubgraphHandler()
662
677
  trades = sgh.get_trades(
@@ -734,7 +749,7 @@ def omen_buy_outcome_tx(
734
749
  web3=web3,
735
750
  )
736
751
 
737
- return tx_receipt["transactionHash"].hex()
752
+ return tx_receipt["transactionHash"].to_0x_hex()
738
753
 
739
754
 
740
755
  def binary_omen_buy_outcome_tx(
@@ -828,7 +843,7 @@ def omen_sell_outcome_tx(
828
843
  web3=web3,
829
844
  )
830
845
 
831
- return tx_receipt["transactionHash"].hex()
846
+ return tx_receipt["transactionHash"].to_0x_hex()
832
847
 
833
848
 
834
849
  def binary_omen_sell_outcome_tx(
@@ -1076,7 +1091,7 @@ def get_conditional_tokens_balance_for_market(
1076
1091
  """
1077
1092
  balance_per_index_set: dict[int, OutcomeWei] = {}
1078
1093
  conditional_token_contract = OmenConditionalTokenContract()
1079
- parent_collection_id = build_parent_collection_id()
1094
+ parent_collection_id = HASH_ZERO
1080
1095
 
1081
1096
  for index_set in market.condition.index_sets:
1082
1097
  collection_id = conditional_token_contract.getCollectionId(
@@ -5,7 +5,6 @@ from datetime import timedelta
5
5
  from enum import Enum
6
6
 
7
7
  from web3 import Web3
8
- from web3.constants import HASH_ZERO
9
8
 
10
9
  from prediction_market_agent_tooling.config import APIKeys
11
10
  from prediction_market_agent_tooling.gtypes import (
@@ -13,7 +12,6 @@ from prediction_market_agent_tooling.gtypes import (
13
12
  ChecksumAddress,
14
13
  HexAddress,
15
14
  HexBytes,
16
- HexStr,
17
15
  IPFSCIDVersion0,
18
16
  OutcomeWei,
19
17
  TxParams,
@@ -24,11 +22,9 @@ from prediction_market_agent_tooling.gtypes import (
24
22
  )
25
23
  from prediction_market_agent_tooling.markets.omen.data_models import (
26
24
  INVALID_ANSWER_HEX_BYTES,
27
- ConditionPreparationEvent,
28
25
  ContractPrediction,
29
26
  FPMMFundingAddedEvent,
30
27
  OmenFixedProductMarketMakerCreationEvent,
31
- PayoutRedemptionEvent,
32
28
  RealitioLogNewQuestionEvent,
33
29
  format_realitio_question,
34
30
  )
@@ -38,6 +34,7 @@ from prediction_market_agent_tooling.markets.omen.omen_constants import (
38
34
  WRAPPED_XDAI_CONTRACT_ADDRESS,
39
35
  )
40
36
  from prediction_market_agent_tooling.tools.contract import (
37
+ ConditionalTokenContract,
41
38
  ContractDepositableWrapperERC20OnGnosisChain,
42
39
  ContractERC20OnGnosisChain,
43
40
  ContractERC4626OnGnosisChain,
@@ -96,202 +93,11 @@ class OmenOracleContract(ContractOnGnosisChain):
96
93
  )
97
94
 
98
95
 
99
- def build_parent_collection_id() -> HexStr:
100
- return HASH_ZERO # Taken from Olas
101
-
102
-
103
- class OmenConditionalTokenContract(ContractOnGnosisChain):
104
- # Contract ABI taken from https://gnosisscan.io/address/0xCeAfDD6bc0bEF976fdCd1112955828E00543c0Ce#code.
105
- abi: ABI = abi_field_validator(
106
- os.path.join(
107
- os.path.dirname(os.path.realpath(__file__)),
108
- "../../abis/omen_fpmm_conditionaltokens.abi.json",
109
- )
110
- )
96
+ class OmenConditionalTokenContract(ConditionalTokenContract, ContractOnGnosisChain):
111
97
  address: ChecksumAddress = Web3.to_checksum_address(
112
98
  "0xCeAfDD6bc0bEF976fdCd1112955828E00543c0Ce"
113
99
  )
114
100
 
115
- def getConditionId(
116
- self,
117
- question_id: HexBytes,
118
- oracle_address: ChecksumAddress,
119
- outcomes_slot_count: int,
120
- web3: Web3 | None = None,
121
- ) -> HexBytes:
122
- id_ = HexBytes(
123
- self.call(
124
- "getConditionId",
125
- [oracle_address, question_id, outcomes_slot_count],
126
- web3=web3,
127
- )
128
- )
129
- return id_
130
-
131
- def balanceOf(
132
- self, from_address: ChecksumAddress, position_id: int, web3: Web3 | None = None
133
- ) -> OutcomeWei:
134
- balance = OutcomeWei(
135
- self.call("balanceOf", [from_address, position_id], web3=web3)
136
- )
137
- return balance
138
-
139
- def getCollectionId(
140
- self,
141
- parent_collection_id: HexStr,
142
- condition_id: HexBytes,
143
- index_set: int,
144
- web3: Web3 | None = None,
145
- ) -> HexBytes:
146
- collection_id = HexBytes(
147
- self.call(
148
- "getCollectionId",
149
- [parent_collection_id, condition_id, index_set],
150
- web3=web3,
151
- )
152
- )
153
- return collection_id
154
-
155
- def getPositionId(
156
- self,
157
- collateral_token_address: ChecksumAddress,
158
- collection_id: HexBytes,
159
- web3: Web3 | None = None,
160
- ) -> int:
161
- position_id: int = self.call(
162
- "getPositionId",
163
- [collateral_token_address, collection_id],
164
- web3=web3,
165
- )
166
- return position_id
167
-
168
- def mergePositions(
169
- self,
170
- api_keys: APIKeys,
171
- collateral_token_address: ChecksumAddress,
172
- conditionId: HexBytes,
173
- index_sets: t.List[int],
174
- amount: OutcomeWei,
175
- parent_collection_id: HexStr = build_parent_collection_id(),
176
- web3: Web3 | None = None,
177
- ) -> TxReceipt:
178
- return self.send(
179
- api_keys=api_keys,
180
- function_name="mergePositions",
181
- function_params=[
182
- collateral_token_address,
183
- parent_collection_id,
184
- conditionId,
185
- index_sets,
186
- amount,
187
- ],
188
- web3=web3,
189
- )
190
-
191
- def redeemPositions(
192
- self,
193
- api_keys: APIKeys,
194
- collateral_token_address: HexAddress,
195
- condition_id: HexBytes,
196
- index_sets: t.List[int],
197
- parent_collection_id: HexStr = build_parent_collection_id(),
198
- web3: Web3 | None = None,
199
- ) -> PayoutRedemptionEvent:
200
- receipt_tx = self.send(
201
- api_keys=api_keys,
202
- function_name="redeemPositions",
203
- function_params=[
204
- collateral_token_address,
205
- parent_collection_id,
206
- condition_id,
207
- index_sets,
208
- ],
209
- web3=web3,
210
- )
211
- redeem_event_logs = (
212
- self.get_web3_contract(web3=web3)
213
- .events.PayoutRedemption()
214
- .process_receipt(receipt_tx)
215
- )
216
- redeem_event = PayoutRedemptionEvent(**redeem_event_logs[0]["args"])
217
- return redeem_event
218
-
219
- def getOutcomeSlotCount(
220
- self, condition_id: HexBytes, web3: Web3 | None = None
221
- ) -> int:
222
- count: int = self.call("getOutcomeSlotCount", [condition_id], web3=web3)
223
- return count
224
-
225
- def does_condition_exists(
226
- self, condition_id: HexBytes, web3: Web3 | None = None
227
- ) -> bool:
228
- return self.getOutcomeSlotCount(condition_id, web3=web3) > 0
229
-
230
- def is_condition_resolved(
231
- self, condition_id: HexBytes, web3: Web3 | None = None
232
- ) -> bool:
233
- # from ConditionalTokens.redeemPositions:
234
- # uint den = payoutDenominator[conditionId]; require(den > 0, "result for condition not received yet");
235
- payout_for_condition = self.payoutDenominator(condition_id, web3=web3)
236
- return payout_for_condition > 0
237
-
238
- def payoutDenominator(
239
- self, condition_id: HexBytes, web3: Web3 | None = None
240
- ) -> int:
241
- payoutForCondition: int = self.call(
242
- "payoutDenominator", [condition_id], web3=web3
243
- )
244
- return payoutForCondition
245
-
246
- def setApprovalForAll(
247
- self,
248
- api_keys: APIKeys,
249
- for_address: ChecksumAddress,
250
- approve: bool,
251
- tx_params: t.Optional[TxParams] = None,
252
- web3: Web3 | None = None,
253
- ) -> TxReceipt:
254
- return self.send(
255
- api_keys=api_keys,
256
- function_name="setApprovalForAll",
257
- function_params=[
258
- for_address,
259
- approve,
260
- ],
261
- tx_params=tx_params,
262
- web3=web3,
263
- )
264
-
265
- def prepareCondition(
266
- self,
267
- api_keys: APIKeys,
268
- oracle_address: ChecksumAddress,
269
- question_id: HexBytes,
270
- outcomes_slot_count: int,
271
- tx_params: t.Optional[TxParams] = None,
272
- web3: Web3 | None = None,
273
- ) -> ConditionPreparationEvent:
274
- receipt_tx = self.send(
275
- api_keys=api_keys,
276
- function_name="prepareCondition",
277
- function_params=[
278
- oracle_address,
279
- question_id,
280
- outcomes_slot_count,
281
- ],
282
- tx_params=tx_params,
283
- web3=web3,
284
- )
285
-
286
- event_logs = (
287
- self.get_web3_contract(web3=web3)
288
- .events.ConditionPreparation()
289
- .process_receipt(receipt_tx)
290
- )
291
- cond_event = ConditionPreparationEvent(**event_logs[0]["args"])
292
-
293
- return cond_event
294
-
295
101
 
296
102
  class OmenFixedProductMarketMakerContract(ContractOnGnosisChain):
297
103
  # File content taken from https://github.com/protofire/omen-exchange/blob/master/app/src/abi/marketMaker.json.
@@ -85,10 +85,10 @@ def claim_bonds_on_realitio_question(
85
85
  responses = sorted(responses, key=lambda x: x.timestamp)
86
86
 
87
87
  if not responses:
88
- raise ValueError(f"No answers found for {question.questionId.hex()=}")
88
+ raise ValueError(f"No answers found for {question.questionId.to_0x_hex()=}")
89
89
 
90
90
  if responses[-1].question.historyHash == ZERO_BYTES:
91
- raise ValueError(f"Already claimed {question.questionId.hex()=}.")
91
+ raise ValueError(f"Already claimed {question.questionId.to_0x_hex()=}.")
92
92
 
93
93
  history_hashes: list[HexBytes] = []
94
94
  addresses: list[ChecksumAddress] = []
@@ -285,7 +285,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
285
285
  where_stms["liquidityParameter_gt"] = liquidity_bigger_than
286
286
 
287
287
  if condition_id_in is not None:
288
- where_stms["condition_"]["id_in"] = [x.hex() for x in condition_id_in]
288
+ where_stms["condition_"]["id_in"] = [x.to_0x_hex() for x in condition_id_in]
289
289
 
290
290
  if id_in is not None:
291
291
  where_stms["id_in"] = [i.lower() for i in id_in]
@@ -513,7 +513,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
513
513
  where_stms: dict[str, t.Any] = {}
514
514
 
515
515
  if condition_id is not None:
516
- where_stms["conditionIds_contains"] = [condition_id.hex()]
516
+ where_stms["conditionIds_contains"] = [condition_id.to_0x_hex()]
517
517
 
518
518
  positions = self.conditional_tokens_subgraph.Query.positions(
519
519
  first=sys.maxsize, where=unwrap_generic_value(where_stms)
@@ -541,10 +541,12 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
541
541
  where_stms["totalBalance_gt"] = total_balance_bigger_than
542
542
 
543
543
  if user_position_id_in is not None:
544
- where_stms["id_in"] = [x.hex() for x in user_position_id_in]
544
+ where_stms["id_in"] = [x.to_0x_hex() for x in user_position_id_in]
545
545
 
546
546
  if position_id_in is not None:
547
- where_stms["position_"]["positionId_in"] = [x.hex() for x in position_id_in]
547
+ where_stms["position_"]["positionId_in"] = [
548
+ x.to_0x_hex() for x in position_id_in
549
+ ]
548
550
 
549
551
  positions = self.conditional_tokens_subgraph.Query.userPositions(
550
552
  first=sys.maxsize, where=unwrap_generic_value(where_stms)
@@ -710,13 +712,13 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
710
712
  where_stms["user"] = user.lower()
711
713
 
712
714
  if question_id is not None:
713
- where_stms["questionId"] = question_id.hex()
715
+ where_stms["questionId"] = question_id.to_0x_hex()
714
716
 
715
717
  if claimed is not None:
716
718
  if claimed:
717
- where_stms["historyHash"] = ZERO_BYTES.hex()
719
+ where_stms["historyHash"] = ZERO_BYTES.to_0x_hex()
718
720
  else:
719
- where_stms["historyHash_not"] = ZERO_BYTES.hex()
721
+ where_stms["historyHash_not"] = ZERO_BYTES.to_0x_hex()
720
722
 
721
723
  if current_answer_before is not None:
722
724
  where_stms["currentAnswerTimestamp_lt"] = to_int_timestamp(
@@ -750,7 +752,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
750
752
 
751
753
  if question_id_in is not None:
752
754
  # Be aware: On Omen subgraph, question's `id` represents `questionId` on reality subgraph. And `id` on reality subraph is just a weird concat of multiple things from the question.
753
- where_stms["questionId_in"] = [x.hex() for x in question_id_in]
755
+ where_stms["questionId_in"] = [x.to_0x_hex() for x in question_id_in]
754
756
 
755
757
  if excluded_titles:
756
758
  # Be aware: This is called `title_not_in` on Omen subgraph.
@@ -777,7 +779,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
777
779
  where_stms: dict[str, t.Any] = {}
778
780
 
779
781
  if question_id is not None:
780
- where_stms["id"] = question_id.hex()
782
+ where_stms["id"] = question_id.to_0x_hex()
781
783
 
782
784
  if current_answer_before is not None:
783
785
  where_stms["currentAnswerTimestamp_lt"] = to_int_timestamp(
@@ -811,7 +813,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
811
813
 
812
814
  if question_id_in is not None:
813
815
  # Be aware: On Omen subgraph, question's `id` represents `questionId` on reality subgraph. And `id` on reality subraph is just a weird concat of multiple things from the question.
814
- where_stms["id_in"] = [x.hex() for x in question_id_in]
816
+ where_stms["id_in"] = [x.to_0x_hex() for x in question_id_in]
815
817
 
816
818
  if excluded_titles:
817
819
  # Be aware: This is called `qTitle_not_in` on Omen subgraph.
@@ -864,7 +866,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
864
866
  answer = self.realityeth_subgraph.Answer
865
867
  # subgrounds complains if bytes is passed, hence we convert it to HexStr
866
868
  where_stms = [
867
- answer.question.questionId == question_id.hex(),
869
+ answer.question.questionId == question_id.to_0x_hex(),
868
870
  ]
869
871
 
870
872
  answers = self.realityeth_subgraph.Query.answers(