prediction-market-agent-tooling 0.48.6__tar.gz → 0.48.8__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.6 → prediction_market_agent_tooling-0.48.8}/PKG-INFO +1 -1
  2. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/data_models.py +4 -0
  3. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/omen/data_models.py +28 -0
  4. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +3 -2
  5. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +22 -44
  6. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +63 -1
  7. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +41 -38
  8. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/pyproject.toml +1 -1
  9. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/LICENSE +0 -0
  10. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/README.md +0 -0
  11. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  12. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  13. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  14. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  15. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  16. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  17. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  18. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  19. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  20. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  21. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  22. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  23. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  24. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  25. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  26. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  27. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/config.py +0 -0
  28. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/deploy/agent.py +0 -0
  29. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  30. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/deploy/betting_strategy.py +0 -0
  31. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  32. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  33. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  34. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  35. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/gtypes.py +0 -0
  36. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/loggers.py +0 -0
  37. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
  38. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  39. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  40. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  41. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  42. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  43. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  44. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/markets.py +0 -0
  45. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  46. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
  47. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
  48. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  49. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/omen/omen.py +0 -0
  50. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
  51. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  52. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  53. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  54. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
  55. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -0
  56. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
  57. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
  58. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/monitor/monitor.py +0 -0
  59. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/monitor/monitor_app.py +0 -0
  60. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
  61. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/py.typed +0 -0
  62. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/balances.py +0 -0
  63. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
  64. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
  65. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
  66. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  67. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/cache.py +0 -0
  68. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/contract.py +0 -0
  69. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/costs.py +0 -0
  70. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -0
  71. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/google.py +0 -0
  72. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  73. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  74. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  75. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  76. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  77. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  78. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/safe.py +0 -0
  79. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  80. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  81. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py +0 -0
  82. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py +0 -0
  83. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/utils.py +0 -0
  84. {prediction_market_agent_tooling-0.48.6 → prediction_market_agent_tooling-0.48.8}/prediction_market_agent_tooling/tools/web3_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.6
3
+ Version: 0.48.8
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -19,6 +19,10 @@ class Resolution(str, Enum):
19
19
  CANCEL = "CANCEL"
20
20
  MKT = "MKT"
21
21
 
22
+ @staticmethod
23
+ def from_bool(value: bool) -> "Resolution":
24
+ return Resolution.YES if value else Resolution.NO
25
+
22
26
 
23
27
  class TokenAmount(BaseModel):
24
28
  amount: float
@@ -470,6 +470,8 @@ class RealityQuestion(BaseModel):
470
470
  updatedTimestamp: datetime
471
471
  contentHash: HexBytes
472
472
  questionId: HexBytes
473
+ answerFinalizedTimestamp: datetime
474
+ currentScheduledFinalizationTimestamp: datetime
473
475
 
474
476
  @property
475
477
  def url(self) -> str:
@@ -486,6 +488,32 @@ class RealityAnswer(BaseModel):
486
488
  createdBlock: int
487
489
 
488
490
 
491
+ class RealityResponse(BaseModel):
492
+ """
493
+ This is similar to `RealityAnswer`, but contains additional fields, most importantly `historyHash`.
494
+ """
495
+
496
+ id: str
497
+ timestamp: datetime
498
+ answer: HexBytes
499
+ isUnrevealed: bool
500
+ isCommitment: bool
501
+ bond: Wei
502
+ user: HexAddress
503
+ historyHash: HexBytes
504
+ question: RealityQuestion
505
+ createdBlock: int
506
+ revealedBlock: int | None
507
+
508
+ @property
509
+ def bond_xdai(self) -> xDai:
510
+ return wei_to_xdai(self.bond)
511
+
512
+ @property
513
+ def user_checksummed(self) -> ChecksumAddress:
514
+ return Web3.to_checksum_address(self.user)
515
+
516
+
489
517
  class RealityAnswers(BaseModel):
490
518
  answers: list[RealityAnswer]
491
519
 
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import random
3
3
  import typing as t
4
- from datetime import datetime
4
+ from datetime import datetime, timedelta
5
5
  from enum import Enum
6
6
 
7
7
  from web3 import Web3
@@ -521,6 +521,7 @@ class OmenRealitioContract(ContractOnGnosisChain):
521
521
  language: str,
522
522
  arbitrator: Arbitrator,
523
523
  opening: datetime,
524
+ timeout: timedelta = timedelta(days=1),
524
525
  nonce: int | None = None,
525
526
  tx_params: t.Optional[TxParams] = None,
526
527
  web3: Web3 | None = None,
@@ -547,7 +548,7 @@ class OmenRealitioContract(ContractOnGnosisChain):
547
548
  template_id=template_id,
548
549
  question=realitio_question,
549
550
  arbitrator=arbitrator_contract_address,
550
- timeout=86400, # See https://github.com/protofire/omen-exchange/blob/2cfdf6bfe37afa8b169731d51fea69d42321d66c/app/src/util/networks.ts#L278.
551
+ timeout=int(timeout.total_seconds()),
551
552
  opening_ts=int(opening.timestamp()),
552
553
  nonce=(
553
554
  nonce if nonce is not None else random.randint(0, 1000000)
@@ -33,7 +33,6 @@ from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
33
33
  from prediction_market_agent_tooling.markets.polymarket.utils import (
34
34
  find_resolution_on_polymarket,
35
35
  )
36
- from prediction_market_agent_tooling.tools.utils import check_not_none
37
36
  from prediction_market_agent_tooling.tools.web3_utils import ZERO_BYTES, xdai_to_wei
38
37
 
39
38
 
@@ -42,7 +41,6 @@ def claim_bonds_on_realitio_questions(
42
41
  questions: list[RealityQuestion],
43
42
  auto_withdraw: bool,
44
43
  web3: Web3 | None = None,
45
- silent_errors: bool = False,
46
44
  ) -> list[HexBytes]:
47
45
  claimed_questions: list[HexBytes] = []
48
46
 
@@ -50,19 +48,10 @@ def claim_bonds_on_realitio_questions(
50
48
  logger.info(
51
49
  f"[{idx+1} / {len(questions)}] Claiming bond for {question.questionId=} {question.url=}"
52
50
  )
53
- try:
54
- claim_bonds_on_realitio_question(
55
- api_keys, question, auto_withdraw=auto_withdraw, web3=web3
56
- )
57
- claimed_questions.append(question.questionId)
58
- except Exception as e:
59
- # TODO: This shouldn't be required once `claim_bonds_on_realitio_question` below is fixed.
60
- if silent_errors:
61
- logger.warning(
62
- f"Error while claiming bond for {question.questionId=} {question.url=}: {e}"
63
- )
64
- else:
65
- raise
51
+ claim_bonds_on_realitio_question(
52
+ api_keys, question, auto_withdraw=auto_withdraw, web3=web3
53
+ )
54
+ claimed_questions.append(question.questionId)
66
55
 
67
56
  return claimed_questions
68
57
 
@@ -77,50 +66,39 @@ def claim_bonds_on_realitio_question(
77
66
  realitio_contract = OmenRealitioContract()
78
67
 
79
68
  # Get all answers for the question.
80
- answers_objects = OmenSubgraphHandler().get_answers(question_id=question.questionId)
69
+ responses = OmenSubgraphHandler().get_responses(question_id=question.questionId)
81
70
 
82
- if not answers_objects:
83
- raise ValueError(f"No answers found for {question.questionId=}")
71
+ # They need to be processed in order.
72
+ responses = sorted(responses, key=lambda x: x.timestamp)
84
73
 
85
- if answers_objects[-1].question.historyHash == ZERO_BYTES:
86
- raise ValueError(f"Already claimed {question.questionId=}.")
74
+ if not responses:
75
+ raise ValueError(f"No answers found for {question.questionId.hex()=}")
87
76
 
88
- if len(answers_objects) > 1:
89
- # As you can see below, we need `history_hash` for every answer.
90
- # The trouble is, that historyHash is updated after each new answer and the contract holds only the latest one.
91
- # So if we have more than 1 answer, we missing the historyHash n-1 of them and this would fail.
92
- # You can find how to calculate history hash at https://realitio.github.io/docs/html/contract_explanation.html#answer-history-entries.
93
- # At the moment, we support only 1 answer, as for that one answer we will have the hash.
94
- raise NotImplementedError()
77
+ if responses[-1].question.historyHash == ZERO_BYTES:
78
+ raise ValueError(f"Already claimed {question.questionId.hex()=}.")
95
79
 
96
- # Logic taken from packages/valory/skills/decision_maker_abci/models.py in `def claim_params`.
97
80
  history_hashes: list[HexBytes] = []
98
81
  addresses: list[ChecksumAddress] = []
99
82
  bonds: list[Wei] = []
100
83
  answers: list[HexBytes] = []
101
84
 
102
- for i, answer in enumerate(reversed(answers_objects)):
103
- # history_hashes second-last-to-first, the hash of each history entry, calculated as described here:
104
- # https://realitio.github.io/docs/html/contract_explanation.html#answer-history-entries.
105
- if i == len(answers_objects) - 1:
85
+ # Caller must provide the answer history, in reverse order.
86
+ # See https://gnosisscan.io/address/0x79e32aE03fb27B07C89c0c568F80287C01ca2E57#code#L625 for the `claimWinnings` logic.
87
+ reversed_responses = list(reversed(responses))
88
+
89
+ for i, response in enumerate(reversed_responses):
90
+ # second-last-to-first, the hash of each history entry. (Final one should be empty).
91
+ if i == len(reversed_responses) - 1:
106
92
  history_hashes.append(ZERO_BYTES)
107
93
  else:
108
- # TODO: See `if len(answers_objects) > 1` above.
109
- # This is from the original Olas implementation (https://github.com/kongzii/trader/blob/700af475a4538cc3d5d22caf9dec9e9d22d72af1/packages/valory/skills/market_manager_abci/graph_tooling/requests.py#L297),
110
- # but it's most probably wrong (see comment above).
111
- history_hashes.append(
112
- check_not_none(
113
- answers_objects[i + 1].question.historyHash,
114
- "Shouldn't be None here.",
115
- )
116
- )
94
+ history_hashes.append(reversed_responses[i + 1].historyHash)
117
95
 
118
96
  # last-to-first, the address of each answerer or commitment sender
119
- addresses.append(Web3.to_checksum_address(answer.question.user))
97
+ addresses.append(Web3.to_checksum_address(response.user))
120
98
  # last-to-first, the bond supplied with each answer or commitment
121
- bonds.append(answer.lastBond)
99
+ bonds.append(response.bond)
122
100
  # last-to-first, each answer supplied, or commitment ID if the answer was supplied with commit->reveal
123
- answers.append(answer.answer)
101
+ answers.append(response.answer)
124
102
 
125
103
  realitio_contract.claimWinnings(
126
104
  api_keys=api_keys,
@@ -22,6 +22,7 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
22
22
  OmenUserPosition,
23
23
  RealityAnswer,
24
24
  RealityQuestion,
25
+ RealityResponse,
25
26
  )
26
27
  from prediction_market_agent_tooling.markets.omen.omen_contracts import (
27
28
  OmenThumbnailMapping,
@@ -118,6 +119,8 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
118
119
  questions_field.questionId,
119
120
  questions_field.contentHash,
120
121
  questions_field.historyHash,
122
+ questions_field.answerFinalizedTimestamp,
123
+ questions_field.currentScheduledFinalizationTimestamp,
121
124
  ]
122
125
 
123
126
  def _get_fields_for_answers(self, answers_field: FieldPath) -> list[FieldPath]:
@@ -130,6 +133,20 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
130
133
  answers_field.createdBlock,
131
134
  ] + self._get_fields_for_reality_questions(answers_field.question)
132
135
 
136
+ def _get_fields_for_responses(self, responses_field: FieldPath) -> list[FieldPath]:
137
+ return [
138
+ responses_field.id,
139
+ responses_field.timestamp,
140
+ responses_field.answer,
141
+ responses_field.isUnrevealed,
142
+ responses_field.isCommitment,
143
+ responses_field.bond,
144
+ responses_field.user,
145
+ responses_field.historyHash,
146
+ responses_field.createdBlock,
147
+ responses_field.revealedBlock,
148
+ ] + self._get_fields_for_reality_questions(responses_field.question)
149
+
133
150
  def _get_fields_for_market_questions(
134
151
  self, questions_field: FieldPath
135
152
  ) -> list[FieldPath]:
@@ -175,11 +192,13 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
175
192
  def _build_where_statements(
176
193
  self,
177
194
  creator: t.Optional[HexAddress] = None,
195
+ creator_in: t.Optional[t.Sequence[HexAddress]] = None,
178
196
  outcomes: list[str] = [OMEN_TRUE_OUTCOME, OMEN_FALSE_OUTCOME],
179
197
  created_after: t.Optional[datetime] = None,
180
198
  opened_before: t.Optional[datetime] = None,
181
199
  opened_after: t.Optional[datetime] = None,
182
200
  finalized_before: t.Optional[datetime] = None,
201
+ finalized_after: t.Optional[datetime] = None,
183
202
  finalized: bool | None = None,
184
203
  resolved: bool | None = None,
185
204
  liquidity_bigger_than: Wei | None = None,
@@ -202,7 +221,10 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
202
221
  ]
203
222
 
204
223
  if creator:
205
- where_stms["creator"] = creator
224
+ where_stms["creator"] = creator.lower()
225
+
226
+ if creator_in:
227
+ where_stms["creator_in"] = [x.lower() for x in creator_in]
206
228
 
207
229
  if created_after:
208
230
  where_stms["creationTimestamp_gt"] = to_int_timestamp(created_after)
@@ -244,6 +266,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
244
266
  finalized_before
245
267
  )
246
268
 
269
+ if finalized_after:
270
+ where_stms["answerFinalizedTimestamp_gt"] = to_int_timestamp(
271
+ finalized_after
272
+ )
273
+
247
274
  # `excluded_question_titles` can not be an empty list, otherwise the API bugs out and returns nothing.
248
275
  excluded_question_titles = [""]
249
276
  if excluded_questions:
@@ -331,9 +358,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
331
358
  opened_before: t.Optional[datetime] = None,
332
359
  opened_after: t.Optional[datetime] = None,
333
360
  finalized_before: t.Optional[datetime] = None,
361
+ finalized_after: t.Optional[datetime] = None,
334
362
  finalized: bool | None = None,
335
363
  resolved: bool | None = None,
336
364
  creator: t.Optional[HexAddress] = None,
365
+ creator_in: t.Optional[t.Sequence[HexAddress]] = None,
337
366
  liquidity_bigger_than: Wei | None = None,
338
367
  condition_id_in: list[HexBytes] | None = None,
339
368
  id_in: list[str] | None = None,
@@ -353,11 +382,13 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
353
382
  """
354
383
  where_stms = self._build_where_statements(
355
384
  creator=creator,
385
+ creator_in=creator_in,
356
386
  outcomes=outcomes,
357
387
  created_after=created_after,
358
388
  opened_before=opened_before,
359
389
  opened_after=opened_after,
360
390
  finalized_before=finalized_before,
391
+ finalized_after=finalized_after,
361
392
  finalized=finalized,
362
393
  resolved=resolved,
363
394
  condition_id_in=condition_id_in,
@@ -582,6 +613,10 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
582
613
  user: HexAddress | None = None,
583
614
  claimed: bool | None = None,
584
615
  current_answer_before: datetime | None = None,
616
+ finalized_before: datetime | None = None,
617
+ finalized_after: datetime | None = None,
618
+ id_in: list[str] | None = None,
619
+ question_id_in: list[HexBytes] | None = None,
585
620
  ) -> list[RealityQuestion]:
586
621
  where_stms: dict[str, t.Any] = {}
587
622
 
@@ -599,6 +634,22 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
599
634
  current_answer_before
600
635
  )
601
636
 
637
+ if finalized_before is not None:
638
+ where_stms["answerFinalizedTimestamp_lt"] = to_int_timestamp(
639
+ finalized_before
640
+ )
641
+
642
+ if finalized_after is not None:
643
+ where_stms["answerFinalizedTimestamp_gt"] = to_int_timestamp(
644
+ finalized_after
645
+ )
646
+
647
+ if id_in is not None:
648
+ where_stms["id_in"] = id_in
649
+
650
+ if question_id_in is not None:
651
+ where_stms["questionId_in"] = [x.hex() for x in question_id_in]
652
+
602
653
  questions = self.realityeth_subgraph.Query.questions(where=where_stms)
603
654
  fields = self._get_fields_for_reality_questions(questions)
604
655
  result = self.sg.query_json(fields)
@@ -618,6 +669,17 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
618
669
  items = self._parse_items_from_json(result)
619
670
  return [RealityAnswer.model_validate(i) for i in items]
620
671
 
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
+ ]
677
+ responses = self.realityeth_subgraph.Query.responses(where=where_stms)
678
+ fields = self._get_fields_for_responses(responses)
679
+ result = self.sg.query_json(fields)
680
+ items = self._parse_items_from_json(result)
681
+ return [RealityResponse.model_validate(i) for i in items]
682
+
621
683
  def get_markets_from_all_user_positions(
622
684
  self, user_positions: list[OmenUserPosition]
623
685
  ) -> list[OmenMarket]:
@@ -38,7 +38,7 @@ class Event(BaseModel):
38
38
 
39
39
 
40
40
  class Event1(BaseModel):
41
- startDate: datetime
41
+ startDate: datetime | None = None
42
42
  slug: str
43
43
 
44
44
 
@@ -78,13 +78,13 @@ class Market(BaseModel):
78
78
  conditionId: str
79
79
  slug: str
80
80
  twitterCardImage: t.Any | None = None
81
- resolutionSource: str
81
+ resolutionSource: str | None = None
82
82
  endDate: datetime
83
83
  category: t.Any | None = None
84
84
  ammType: t.Any | None = None
85
85
  description: str
86
86
  liquidity: str | None = None
87
- startDate: datetime
87
+ startDate: datetime | None = None
88
88
  createdAt: datetime
89
89
  xAxisValue: t.Any | None = None
90
90
  yAxisValue: t.Any | None = None
@@ -93,8 +93,8 @@ class Market(BaseModel):
93
93
  lowerBound: t.Any | None = None
94
94
  upperBound: t.Any | None = None
95
95
  outcomes: list[str]
96
- image: str
97
- icon: str
96
+ image: str | None = None
97
+ icon: str | None = None
98
98
  imageOptimized: t.Any | None = None
99
99
  iconOptimized: t.Any | None = None
100
100
  outcomePrices: list[USDC]
@@ -108,23 +108,23 @@ class Market(BaseModel):
108
108
  marketMakerAddress: HexAddress
109
109
  closedTime: datetime | None = None
110
110
  wideFormat: bool | None = None
111
- new: bool
111
+ new: bool | None = None
112
112
  sentDiscord: t.Any | None = None
113
113
  mailchimpTag: t.Any | None = None
114
- featured: bool
115
- submitted_by: str
114
+ featured: bool | None = None
115
+ submitted_by: str | None = None
116
116
  subcategory: t.Any | None = None
117
117
  categoryMailchimpTag: t.Any | None = None
118
- archived: bool
119
- resolvedBy: str
120
- restricted: bool
121
- groupItemTitle: str
122
- groupItemThreshold: str
123
- questionID: str
118
+ archived: bool | None = None
119
+ resolvedBy: str | None = None
120
+ restricted: bool | None = None
121
+ groupItemTitle: str | None = None
122
+ groupItemThreshold: str | None = None
123
+ questionID: str | None = None
124
124
  umaEndDate: t.Any | None = None
125
- enableOrderBook: bool
126
- orderPriceMinTickSize: float
127
- orderMinSize: int
125
+ enableOrderBook: bool | None = None
126
+ orderPriceMinTickSize: float | None = None
127
+ orderMinSize: int | None = None
128
128
  umaResolutionStatus: t.Any | None = None
129
129
  curationOrder: t.Any | None = None
130
130
  volumeNum: USDC | None = None
@@ -134,9 +134,9 @@ class Market(BaseModel):
134
134
  umaEndDateIso: datetime | None = None
135
135
  commentsEnabled: bool | None = None
136
136
  disqusThread: t.Any | None = None
137
- gameStartTime: datetime | None = None
137
+ gameStartTime: t.Any | None = None
138
138
  secondsDelay: int | None = None
139
- clobTokenIds: list[str]
139
+ clobTokenIds: list[str] | None = None
140
140
  liquidityAmm: float | None = None
141
141
  liquidityClob: float | None = None
142
142
  makerBaseFee: int | None = None
@@ -144,27 +144,27 @@ class Market(BaseModel):
144
144
  negRisk: t.Any | None = None
145
145
  negRiskRequestID: t.Any | None = None
146
146
  negRiskMarketID: t.Any | None = None
147
- events: list[Event]
148
- markets: list[Market1]
147
+ events: list[Event] | None = None
148
+ markets: list[Market1] | None = None
149
149
  lower_bound_date: t.Any | None = None
150
150
  upper_bound_date: t.Any | None = None
151
151
  market_type: str | None = None
152
- resolution_source: str
153
- end_date: str
152
+ resolution_source: str | None = None
153
+ end_date: str | None = None
154
154
  amm_type: t.Any | None = None
155
155
  x_axis_value: t.Any | None = None
156
156
  y_axis_value: t.Any | None = None
157
157
  denomination_token: t.Any | None = None
158
- resolved_by: str
158
+ resolved_by: str | None = None
159
159
  upper_bound: t.Any | None = None
160
160
  lower_bound: t.Any | None = None
161
- created_at: str
161
+ created_at: str | None = None
162
162
  updated_at: t.Any | None = None
163
163
  closed_time: t.Any | None = None
164
164
  wide_format: bool | None = None
165
165
  volume_num: USDC | None = None
166
166
  liquidity_num: USDC | None = None
167
- image_raw: str
167
+ image_raw: str | None = None
168
168
  resolutionData: ResolutionData
169
169
 
170
170
  @field_validator("closedTime", mode="before")
@@ -234,19 +234,19 @@ class PolymarketFullMarket(BaseModel):
234
234
  title: str
235
235
  subtitle: t.Any | None = None
236
236
  description: str
237
- commentCount: int
238
- resolutionSource: str
239
- startDate: datetime
237
+ commentCount: int | None = None
238
+ resolutionSource: str | None = None
239
+ startDate: datetime | None = None
240
240
  endDate: datetime
241
- image: str
242
- icon: str
241
+ image: str | None = None
242
+ icon: str | None = None
243
243
  featuredImage: str | None = None
244
244
  active: bool
245
245
  closed: bool
246
- archived: bool
247
- new: bool
248
- featured: bool
249
- restricted: bool
246
+ archived: bool | None = None
247
+ new: bool | None = None
248
+ featured: bool | None = None
249
+ restricted: bool | None = None
250
250
  liquidity: USDC | None = None
251
251
  volume: USDC | None = None
252
252
  volume24hr: USDC | None = None
@@ -257,7 +257,7 @@ class PolymarketFullMarket(BaseModel):
257
257
  commentsEnabled: bool | None = None
258
258
  disqusThread: t.Any | None = None
259
259
  updatedAt: datetime
260
- enableOrderBook: bool
260
+ enableOrderBook: bool | None = None
261
261
  liquidityAmm: float | None = None
262
262
  liquidityClob: float | None = None
263
263
  imageOptimized: ImageOptimized | None = None
@@ -269,7 +269,7 @@ class PolymarketFullMarket(BaseModel):
269
269
  markets: list[Market]
270
270
  categories: list[Category] | None = None
271
271
  series: t.Any | None = None
272
- image_raw: str
272
+ image_raw: str | None = None
273
273
 
274
274
  @property
275
275
  def url(self) -> str:
@@ -298,6 +298,8 @@ class PolymarketFullMarket(BaseModel):
298
298
 
299
299
  Warning: This is a very slow operation, as it requires fetching the website. Use it only when necessary.
300
300
  """
301
+ logger.info(f"Fetching full market from {url}")
302
+
301
303
  # Fetch the website as a normal browser would.
302
304
  headers = {
303
305
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
@@ -352,7 +354,8 @@ class State(BaseModel):
352
354
  | dict[str, MarketBidsAndAsks]
353
355
  | dict[str, PriceSide]
354
356
  | None
355
- ) # It's none if you go to the website and it says "Oops...we didn't forecast this".
357
+ # It's none if you go to the website and it says "Oops...we didn't forecast this".
358
+ )
356
359
  dataUpdateCount: int
357
360
  dataUpdatedAt: int
358
361
  error: t.Any | None = None
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "prediction-market-agent-tooling"
3
- version = "0.48.6"
3
+ version = "0.48.8"
4
4
  description = "Tools to benchmark, deploy and monitor prediction market agents."
5
5
  authors = ["Gnosis"]
6
6
  readme = "README.md"