From 666dba795ce451606b0f3d904eebbc273a0c2a08 Mon Sep 17 00:00:00 2001 From: Peter Jung Date: Fri, 29 Nov 2024 14:42:48 +0100 Subject: [PATCH] Fix pending arbitration filter (#564) --- .../markets/omen/data_models.py | 10 ++++--- .../markets/omen/omen.py | 9 +++++-- .../markets/omen/omen_subgraph_handler.py | 27 ++++++++++++++----- pyproject.toml | 2 +- .../omen/test_omen_subgraph_handler.py | 25 +++++++++++++++++ 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/prediction_market_agent_tooling/markets/omen/data_models.py b/prediction_market_agent_tooling/markets/omen/data_models.py index f7d8b8da..bb1fecd9 100644 --- a/prediction_market_agent_tooling/markets/omen/data_models.py +++ b/prediction_market_agent_tooling/markets/omen/data_models.py @@ -594,7 +594,7 @@ class RealityQuestion(BaseModel): updatedTimestamp: int contentHash: HexBytes questionId: HexBytes # This is the `id` on question from omen subgraph. - answerFinalizedTimestamp: int + answerFinalizedTimestamp: int | None currentScheduledFinalizationTimestamp: int @property @@ -602,8 +602,12 @@ def updated_datetime(self) -> DatetimeUTC: return DatetimeUTC.to_datetime_utc(self.updatedTimestamp) @property - def answer_finalized_datetime(self) -> DatetimeUTC: - return DatetimeUTC.to_datetime_utc(self.answerFinalizedTimestamp) + def answer_finalized_datetime(self) -> DatetimeUTC | None: + return ( + DatetimeUTC.to_datetime_utc(self.answerFinalizedTimestamp) + if self.answerFinalizedTimestamp is not None + else None + ) @property def current_scheduled_finalization_datetime(self) -> DatetimeUTC: diff --git a/prediction_market_agent_tooling/markets/omen/omen.py b/prediction_market_agent_tooling/markets/omen/omen.py index 64d90ad0..488bdeec 100644 --- a/prediction_market_agent_tooling/markets/omen/omen.py +++ b/prediction_market_agent_tooling/markets/omen/omen.py @@ -565,13 +565,18 @@ def get_positions( omen_markets: dict[HexBytes, OmenMarket] = { m.condition.id: m for m in sgh.get_omen_binary_markets( - limit=sys.maxsize, + limit=None, condition_id_in=list(omen_positions_dict.keys()), ) } + if len(omen_markets) != len(omen_positions_dict): + missing_conditions_ids = set( + omen_position.position.condition_id for omen_position in omen_positions + ) - set(market.condition.id for market in omen_markets.values()) raise ValueError( - f"Number of condition ids for markets {len(omen_markets)} and positions {len(omen_positions_dict)} are not equal." + f"Number of condition ids for markets {len(omen_markets)} and positions {len(omen_positions_dict)} are not equal. " + f"Missing condition ids: {missing_conditions_ids}" ) positions = [] diff --git a/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py b/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py index a5f29f21..6dfc5d0a 100644 --- a/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +++ b/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py @@ -214,6 +214,7 @@ def _build_where_statements( question_finalized_before: DatetimeUTC | None, question_finalized_after: DatetimeUTC | None, question_with_answers: bool | None, + question_pending_arbitration: bool | None, question_id: HexBytes | None, question_id_in: list[HexBytes] | None, question_current_answer_before: DatetimeUTC | None, @@ -226,7 +227,6 @@ def _build_where_statements( category: str | None, ) -> dict[str, t.Any]: where_stms: dict[str, t.Any] = { - "isPendingArbitration": False, "outcomes": outcomes, "title_not": None, "condition_": {}, @@ -239,6 +239,7 @@ def _build_where_statements( finalized_before=question_finalized_before, finalized_after=question_finalized_after, with_answers=question_with_answers, + pending_arbitration=question_pending_arbitration, current_answer_before=question_current_answer_before, question_id_in=question_id_in, excluded_titles=question_excluded_titles, @@ -377,6 +378,7 @@ def get_omen_binary_markets( question_finalized_before: DatetimeUTC | None = None, question_finalized_after: DatetimeUTC | None = None, question_with_answers: bool | None = None, + question_pending_arbitration: bool | None = None, question_id: HexBytes | None = None, question_id_in: list[HexBytes] | None = None, question_current_answer_before: DatetimeUTC | None = None, @@ -406,6 +408,7 @@ def get_omen_binary_markets( question_finalized_before=question_finalized_before, question_finalized_after=question_finalized_after, question_with_answers=question_with_answers, + question_pending_arbitration=question_pending_arbitration, question_id=question_id, question_id_in=question_id_in, question_current_answer_before=question_current_answer_before, @@ -654,6 +657,7 @@ def get_reality_question_filters( finalized_before: DatetimeUTC | None, finalized_after: DatetimeUTC | None, with_answers: bool | None, + pending_arbitration: bool | None, question_id: HexBytes | None, question_id_in: list[HexBytes] | None, opened_before: t.Optional[DatetimeUTC], @@ -700,9 +704,12 @@ def get_reality_question_filters( if with_answers is not None: if with_answers: - where_stms["answerFinalizedTimestamp_not"] = None + where_stms["currentAnswer_not"] = None else: - where_stms["answerFinalizedTimestamp"] = None + where_stms["currentAnswer"] = None + + if pending_arbitration is not None: + where_stms["isPendingArbitration"] = pending_arbitration if question_id_in is not None: # 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. @@ -720,6 +727,7 @@ def get_omen_question_filters( finalized_before: DatetimeUTC | None, finalized_after: DatetimeUTC | None, with_answers: bool | None, + pending_arbitration: bool | None, question_id: HexBytes | None, question_id_in: list[HexBytes] | None, opened_before: t.Optional[DatetimeUTC], @@ -732,7 +740,7 @@ def get_omen_question_filters( where_stms: dict[str, t.Any] = {} if question_id is not None: - where_stms["questionId"] = question_id.hex() + where_stms["id"] = question_id.hex() if current_answer_before is not None: where_stms["currentAnswerTimestamp_lt"] = to_int_timestamp( @@ -757,9 +765,12 @@ def get_omen_question_filters( if with_answers is not None: if with_answers: - where_stms["answerFinalizedTimestamp_not"] = None + where_stms["currentAnswer_not"] = None else: - where_stms["answerFinalizedTimestamp"] = None + where_stms["currentAnswer"] = None + + if pending_arbitration is not None: + where_stms["isPendingArbitration"] = pending_arbitration if question_id_in is not None: # 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. @@ -780,6 +791,7 @@ def get_questions( finalized_before: DatetimeUTC | None = None, finalized_after: DatetimeUTC | None = None, with_answers: bool | None = None, + pending_arbitration: bool | None = None, question_id_in: list[HexBytes] | None = None, question_id: HexBytes | None = None, opened_before: DatetimeUTC | None = None, @@ -792,6 +804,7 @@ def get_questions( finalized_before=finalized_before, finalized_after=finalized_after, with_answers=with_answers, + pending_arbitration=pending_arbitration, current_answer_before=current_answer_before, question_id_in=question_id_in, question_id=question_id, @@ -834,6 +847,7 @@ def get_responses( question_finalized_before: t.Optional[DatetimeUTC] = None, question_finalized_after: t.Optional[DatetimeUTC] = None, question_with_answers: bool | None = None, + question_pending_arbitration: bool | None = None, question_id: HexBytes | None = None, question_id_in: list[HexBytes] | None = None, question_current_answer_before: DatetimeUTC | None = None, @@ -853,6 +867,7 @@ def get_responses( finalized_before=question_finalized_before, finalized_after=question_finalized_after, with_answers=question_with_answers, + pending_arbitration=question_pending_arbitration, current_answer_before=question_current_answer_before, question_id_in=question_id_in, excluded_titles=question_excluded_titles, diff --git a/pyproject.toml b/pyproject.toml index 59c56d62..7c725887 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "prediction-market-agent-tooling" -version = "0.57.2" +version = "0.57.3" description = "Tools to benchmark, deploy and monitor prediction market agents." authors = ["Gnosis"] readme = "README.md" diff --git a/tests/markets/omen/test_omen_subgraph_handler.py b/tests/markets/omen/test_omen_subgraph_handler.py index eae5f9fa..6e9ae360 100644 --- a/tests/markets/omen/test_omen_subgraph_handler.py +++ b/tests/markets/omen/test_omen_subgraph_handler.py @@ -358,3 +358,28 @@ def test_get_predictions_from_market( assert len(predictions) >= 1 # We can get the 0th element since we sort by block number asc. assert predictions[0].publisher_checksummed == first_publisher + + +def test_get_arbitrated_market_with_answer( + omen_subgraph_handler: OmenSubgraphHandler, +) -> None: + assert omen_subgraph_handler.get_questions( + limit=None, + question_id=HexBytes( + "0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b" + ), + with_answers=True, + ), "Should return it, because that questionId has an answer." + + +def test_do_not_get_arbitrated_market_without_answer( + omen_subgraph_handler: OmenSubgraphHandler, +) -> None: + # If this test starts to fail, check if `0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b` isn't arbitrated anymore, and if so simply delete this test. + assert not omen_subgraph_handler.get_questions( + limit=None, + question_id=HexBytes( + "0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b" + ), + with_answers=False, + ), "Should not return anything, because that questionId has an answer."