prediction-market-agent-tooling 0.66.3__py3-none-any.whl → 0.66.4__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 (19) hide show
  1. prediction_market_agent_tooling/benchmark/utils.py +13 -0
  2. prediction_market_agent_tooling/deploy/agent.py +25 -1
  3. prediction_market_agent_tooling/deploy/constants.py +2 -0
  4. prediction_market_agent_tooling/jobs/omen/omen_jobs.py +2 -0
  5. prediction_market_agent_tooling/markets/agent_market.py +35 -0
  6. prediction_market_agent_tooling/markets/data_models.py +64 -0
  7. prediction_market_agent_tooling/markets/manifold/manifold.py +1 -0
  8. prediction_market_agent_tooling/markets/markets.py +2 -0
  9. prediction_market_agent_tooling/markets/metaculus/metaculus.py +1 -0
  10. prediction_market_agent_tooling/markets/omen/omen.py +1 -0
  11. prediction_market_agent_tooling/markets/polymarket/polymarket.py +1 -0
  12. prediction_market_agent_tooling/markets/seer/data_models.py +15 -1
  13. prediction_market_agent_tooling/markets/seer/seer.py +71 -11
  14. prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +68 -30
  15. {prediction_market_agent_tooling-0.66.3.dist-info → prediction_market_agent_tooling-0.66.4.dist-info}/METADATA +1 -1
  16. {prediction_market_agent_tooling-0.66.3.dist-info → prediction_market_agent_tooling-0.66.4.dist-info}/RECORD +19 -19
  17. {prediction_market_agent_tooling-0.66.3.dist-info → prediction_market_agent_tooling-0.66.4.dist-info}/LICENSE +0 -0
  18. {prediction_market_agent_tooling-0.66.3.dist-info → prediction_market_agent_tooling-0.66.4.dist-info}/WHEEL +0 -0
  19. {prediction_market_agent_tooling-0.66.3.dist-info → prediction_market_agent_tooling-0.66.4.dist-info}/entry_points.txt +0 -0
@@ -6,6 +6,7 @@ from pydantic import BaseModel
6
6
  from prediction_market_agent_tooling.gtypes import OutcomeStr, Probability
7
7
  from prediction_market_agent_tooling.markets.data_models import (
8
8
  CategoricalProbabilisticAnswer,
9
+ ScalarProbabilisticAnswer,
9
10
  )
10
11
 
11
12
 
@@ -16,6 +17,18 @@ def get_most_probable_outcome(
16
17
  return max(probability_map, key=lambda k: float(probability_map[k]))
17
18
 
18
19
 
20
+ class ScalarPrediction(BaseModel):
21
+ is_predictable: bool = True
22
+ outcome_prediction: t.Optional[ScalarProbabilisticAnswer] = None
23
+
24
+ time: t.Optional[float] = None
25
+ cost: t.Optional[float] = None
26
+
27
+ @property
28
+ def is_answered(self) -> bool:
29
+ return self.outcome_prediction is not None
30
+
31
+
19
32
  class Prediction(BaseModel):
20
33
  is_predictable: bool = True
21
34
  outcome_prediction: t.Optional[CategoricalProbabilisticAnswer] = None
@@ -31,6 +31,7 @@ from prediction_market_agent_tooling.markets.data_models import (
31
31
  ExistingPosition,
32
32
  PlacedTrade,
33
33
  ProbabilisticAnswer,
34
+ ScalarProbabilisticAnswer,
34
35
  Trade,
35
36
  )
36
37
  from prediction_market_agent_tooling.markets.markets import MarketType
@@ -219,6 +220,7 @@ class DeployablePredictionAgent(DeployableAgent):
219
220
  self.verify_market = observe()(self.verify_market) # type: ignore[method-assign]
220
221
  self.answer_binary_market = observe()(self.answer_binary_market) # type: ignore[method-assign]
221
222
  self.answer_categorical_market = observe()(self.answer_categorical_market) # type: ignore[method-assign]
223
+ self.answer_scalar_market = observe()(self.answer_scalar_market) # type: ignore[method-assign]
222
224
  self.process_market = observe()(self.process_market) # type: ignore[method-assign]
223
225
 
224
226
  def update_langfuse_trace_by_market(
@@ -299,6 +301,11 @@ class DeployablePredictionAgent(DeployableAgent):
299
301
  ) -> CategoricalProbabilisticAnswer | None:
300
302
  raise NotImplementedError("This method must be implemented by the subclass")
301
303
 
304
+ def answer_scalar_market(
305
+ self, market: AgentMarket
306
+ ) -> ScalarProbabilisticAnswer | None:
307
+ raise NotImplementedError("This method must be implemented by the subclass")
308
+
302
309
  def answer_binary_market(self, market: AgentMarket) -> ProbabilisticAnswer | None:
303
310
  """
304
311
  Answer the binary market.
@@ -321,6 +328,13 @@ class DeployablePredictionAgent(DeployableAgent):
321
328
  return True
322
329
  return False
323
330
 
331
+ @property
332
+ def fetch_scalar_markets(self) -> bool:
333
+ # Check if the subclass has implemented the answer_scalar_market method, if yes, fetch scalar markets as well.
334
+ if self.answer_scalar_market.__wrapped__.__func__ is not DeployablePredictionAgent.answer_scalar_market: # type: ignore[attr-defined] # This works just fine, but mypy doesn't know about it for some reason.
335
+ return True
336
+ return False
337
+
324
338
  def get_markets(
325
339
  self,
326
340
  market_type: MarketType,
@@ -336,6 +350,7 @@ class DeployablePredictionAgent(DeployableAgent):
336
350
  filter_by=self.get_markets_filter_by,
337
351
  created_after=self.trade_on_markets_created_after,
338
352
  fetch_categorical_markets=self.fetch_categorical_markets,
353
+ fetch_scalar_markets=self.fetch_scalar_markets,
339
354
  )
340
355
  return available_markets
341
356
 
@@ -383,7 +398,16 @@ class DeployablePredictionAgent(DeployableAgent):
383
398
  logger.info(
384
399
  "answer_binary_market() not implemented, falling back to answer_categorical_market()"
385
400
  )
386
-
401
+ elif market.is_scalar:
402
+ scalar_answer = self.answer_scalar_market(market)
403
+ return (
404
+ CategoricalProbabilisticAnswer.from_scalar_answer(
405
+ scalar_answer,
406
+ market.outcomes,
407
+ )
408
+ if scalar_answer is not None
409
+ else None
410
+ )
387
411
  return self.answer_categorical_market(market)
388
412
 
389
413
  def verify_answer_outcomes(
@@ -5,3 +5,5 @@ INVALID_OUTCOME_LOWERCASE_IDENTIFIER = "invalid"
5
5
  # Market-agnostic outcome identifiers
6
6
  YES_OUTCOME_LOWERCASE_IDENTIFIER = "yes"
7
7
  NO_OUTCOME_LOWERCASE_IDENTIFIER = "no"
8
+ UP_OUTCOME_LOWERCASE_IDENTIFIER = "up"
9
+ DOWN_OUTCOME_LOWERCASE_IDENTIFIER = "down"
@@ -133,4 +133,6 @@ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
133
133
  condition=market.condition,
134
134
  finalized_time=market.finalized_time,
135
135
  fees=market.fees,
136
+ upper_bound=market.upper_bound,
137
+ lower_bound=market.lower_bound,
136
138
  )
@@ -11,8 +11,10 @@ from web3 import Web3
11
11
  from prediction_market_agent_tooling.benchmark.utils import get_most_probable_outcome
12
12
  from prediction_market_agent_tooling.config import APIKeys
13
13
  from prediction_market_agent_tooling.deploy.constants import (
14
+ DOWN_OUTCOME_LOWERCASE_IDENTIFIER,
14
15
  INVALID_OUTCOME_LOWERCASE_IDENTIFIER,
15
16
  NO_OUTCOME_LOWERCASE_IDENTIFIER,
17
+ UP_OUTCOME_LOWERCASE_IDENTIFIER,
16
18
  YES_OUTCOME_LOWERCASE_IDENTIFIER,
17
19
  )
18
20
  from prediction_market_agent_tooling.gtypes import (
@@ -20,6 +22,7 @@ from prediction_market_agent_tooling.gtypes import (
20
22
  OutcomeToken,
21
23
  OutcomeWei,
22
24
  Probability,
25
+ Wei,
23
26
  )
24
27
  from prediction_market_agent_tooling.markets.data_models import (
25
28
  USD,
@@ -83,6 +86,9 @@ class AgentMarket(BaseModel):
83
86
  volume: CollateralToken | None
84
87
  fees: MarketFees
85
88
 
89
+ upper_bound: Wei | None = None
90
+ lower_bound: Wei | None = None
91
+
86
92
  @field_validator("probabilities")
87
93
  def validate_probabilities(
88
94
  cls,
@@ -165,6 +171,34 @@ class AgentMarket(BaseModel):
165
171
 
166
172
  return has_yes and has_no
167
173
 
174
+ @property
175
+ def is_scalar(self) -> bool:
176
+ # 3 outcomes can also be binary if 3rd outcome is invalid (Seer)
177
+ if len(self.outcomes) not in [2, 3]:
178
+ return False
179
+
180
+ lowercase_outcomes = [outcome.lower() for outcome in self.outcomes]
181
+
182
+ has_up = UP_OUTCOME_LOWERCASE_IDENTIFIER in lowercase_outcomes
183
+ has_down = DOWN_OUTCOME_LOWERCASE_IDENTIFIER in lowercase_outcomes
184
+
185
+ if len(lowercase_outcomes) == 3:
186
+ invalid_outcome = lowercase_outcomes[-1]
187
+ has_invalid = INVALID_OUTCOME_LOWERCASE_IDENTIFIER in invalid_outcome
188
+ return has_up and has_down and has_invalid
189
+
190
+ return has_up and has_down
191
+
192
+ @property
193
+ def p_up(self) -> Probability:
194
+ probs_lowercase = {o.lower(): p for o, p in self.probabilities.items()}
195
+ return check_not_none(probs_lowercase.get(UP_OUTCOME_LOWERCASE_IDENTIFIER))
196
+
197
+ @property
198
+ def p_down(self) -> Probability:
199
+ probs_lowercase = {o.lower(): p for o, p in self.probabilities.items()}
200
+ return check_not_none(probs_lowercase.get(DOWN_OUTCOME_LOWERCASE_IDENTIFIER))
201
+
168
202
  @property
169
203
  def p_yes(self) -> Probability:
170
204
  probs_lowercase = {o.lower(): p for o, p in self.probabilities.items()}
@@ -336,6 +370,7 @@ class AgentMarket(BaseModel):
336
370
  created_after: t.Optional[DatetimeUTC] = None,
337
371
  excluded_questions: set[str] | None = None,
338
372
  fetch_categorical_markets: bool = False,
373
+ fetch_scalar_markets: bool = False,
339
374
  ) -> t.Sequence["AgentMarket"]:
340
375
  raise NotImplementedError("Subclasses must implement this method")
341
376
 
@@ -4,7 +4,10 @@ from typing import Annotated, Sequence
4
4
  from pydantic import BaseModel, BeforeValidator, computed_field
5
5
 
6
6
  from prediction_market_agent_tooling.deploy.constants import (
7
+ DOWN_OUTCOME_LOWERCASE_IDENTIFIER,
8
+ INVALID_OUTCOME_LOWERCASE_IDENTIFIER,
7
9
  NO_OUTCOME_LOWERCASE_IDENTIFIER,
10
+ UP_OUTCOME_LOWERCASE_IDENTIFIER,
8
11
  YES_OUTCOME_LOWERCASE_IDENTIFIER,
9
12
  )
10
13
  from prediction_market_agent_tooling.gtypes import (
@@ -13,6 +16,7 @@ from prediction_market_agent_tooling.gtypes import (
13
16
  OutcomeStr,
14
17
  OutcomeToken,
15
18
  Probability,
19
+ Wei,
16
20
  )
17
21
  from prediction_market_agent_tooling.logprobs_parser import FieldLogprobs
18
22
  from prediction_market_agent_tooling.markets.omen.omen_constants import (
@@ -100,6 +104,31 @@ def to_boolean_outcome(value: str | bool) -> bool:
100
104
  Decision = Annotated[bool, BeforeValidator(to_boolean_outcome)]
101
105
 
102
106
 
107
+ class ScalarProbabilisticAnswer(BaseModel):
108
+ scalar_value: Wei
109
+ upperBound: Wei
110
+ lowerBound: Wei
111
+ confidence: float
112
+ reasoning: str | None = None
113
+ logprobs: list[FieldLogprobs] | None = None
114
+
115
+ @property
116
+ def p_up(self) -> Probability:
117
+ if self.scalar_value > self.upperBound:
118
+ return Probability(1)
119
+ elif self.scalar_value < self.lowerBound:
120
+ return Probability(0)
121
+ else:
122
+ return Probability(
123
+ (self.scalar_value - self.lowerBound)
124
+ / (self.upperBound - self.lowerBound)
125
+ )
126
+
127
+ @property
128
+ def p_down(self) -> Probability:
129
+ return Probability(1 - self.p_up)
130
+
131
+
103
132
  class ProbabilisticAnswer(BaseModel):
104
133
  p_yes: Probability
105
134
  confidence: float
@@ -165,6 +194,41 @@ class CategoricalProbabilisticAnswer(BaseModel):
165
194
  reasoning=answer.reasoning,
166
195
  )
167
196
 
197
+ @staticmethod
198
+ def from_scalar_answer(
199
+ answer: ScalarProbabilisticAnswer,
200
+ market_outcomes: Sequence[OutcomeStr],
201
+ ) -> "CategoricalProbabilisticAnswer":
202
+ probabilities = {}
203
+ lowercase_market_outcomes = [outcome.lower() for outcome in market_outcomes]
204
+
205
+ if not set(
206
+ [
207
+ DOWN_OUTCOME_LOWERCASE_IDENTIFIER,
208
+ UP_OUTCOME_LOWERCASE_IDENTIFIER,
209
+ ]
210
+ ).issubset(lowercase_market_outcomes):
211
+ raise ValueError("Market with no outcomes")
212
+
213
+ probabilities[OutcomeStr(UP_OUTCOME_LOWERCASE_IDENTIFIER.upper())] = answer.p_up
214
+ probabilities[
215
+ OutcomeStr(DOWN_OUTCOME_LOWERCASE_IDENTIFIER.upper())
216
+ ] = answer.p_down
217
+
218
+ if (
219
+ market_outcomes
220
+ and INVALID_OUTCOME_LOWERCASE_IDENTIFIER in lowercase_market_outcomes
221
+ ):
222
+ probabilities[
223
+ OutcomeStr(INVALID_OUTCOME_LOWERCASE_IDENTIFIER.capitalize())
224
+ ] = Probability(1 - answer.p_up - answer.p_down)
225
+
226
+ return CategoricalProbabilisticAnswer(
227
+ probabilities=probabilities,
228
+ confidence=answer.confidence,
229
+ reasoning=answer.reasoning,
230
+ )
231
+
168
232
  def probability_for_market_outcome(self, market_outcome: OutcomeStr) -> Probability:
169
233
  for k, v in self.probabilities.items():
170
234
  if k.lower() == market_outcome.lower():
@@ -111,6 +111,7 @@ class ManifoldAgentMarket(AgentMarket):
111
111
  created_after: t.Optional[DatetimeUTC] = None,
112
112
  excluded_questions: set[str] | None = None,
113
113
  fetch_categorical_markets: bool = False,
114
+ fetch_scalar_markets: bool = False,
114
115
  ) -> t.Sequence["ManifoldAgentMarket"]:
115
116
  sort: t.Literal["newest", "close-date"] | None
116
117
  if sort_by == SortBy.CLOSING_SOONEST:
@@ -68,6 +68,7 @@ def get_binary_markets(
68
68
  sort_by: SortBy = SortBy.NONE,
69
69
  excluded_questions: set[str] | None = None,
70
70
  created_after: DatetimeUTC | None = None,
71
+ fetch_scalar_markets: bool = False,
71
72
  ) -> t.Sequence[AgentMarket]:
72
73
  agent_market_class = MARKET_TYPE_TO_AGENT_MARKET[market_type]
73
74
  markets = agent_market_class.get_markets(
@@ -76,5 +77,6 @@ def get_binary_markets(
76
77
  filter_by=filter_by,
77
78
  created_after=created_after,
78
79
  excluded_questions=excluded_questions,
80
+ fetch_scalar_markets=fetch_scalar_markets,
79
81
  )
80
82
  return markets
@@ -73,6 +73,7 @@ class MetaculusAgentMarket(AgentMarket):
73
73
  created_after: t.Optional[DatetimeUTC] = None,
74
74
  excluded_questions: set[str] | None = None,
75
75
  tournament_id: int | None = None,
76
+ fetch_scalar_markets: bool = False,
76
77
  ) -> t.Sequence["MetaculusAgentMarket"]:
77
78
  order_by: str | None
78
79
  if sort_by == SortBy.NONE:
@@ -380,6 +380,7 @@ class OmenAgentMarket(AgentMarket):
380
380
  created_after: t.Optional[DatetimeUTC] = None,
381
381
  excluded_questions: set[str] | None = None,
382
382
  fetch_categorical_markets: bool = False,
383
+ fetch_scalar_markets: bool = False,
383
384
  ) -> t.Sequence["OmenAgentMarket"]:
384
385
  return [
385
386
  OmenAgentMarket.from_data_model(m)
@@ -62,6 +62,7 @@ class PolymarketAgentMarket(AgentMarket):
62
62
  created_after: t.Optional[DatetimeUTC] = None,
63
63
  excluded_questions: set[str] | None = None,
64
64
  fetch_categorical_markets: bool = False,
65
+ fetch_scalar_markets: bool = False,
65
66
  ) -> t.Sequence["PolymarketAgentMarket"]:
66
67
  if sort_by != SortBy.NONE:
67
68
  raise ValueError(f"Unsuported sort_by {sort_by} for Polymarket.")
@@ -1,8 +1,9 @@
1
1
  import typing as t
2
2
  from datetime import timedelta
3
+ from typing import Annotated
3
4
  from urllib.parse import urljoin
4
5
 
5
- from pydantic import BaseModel, ConfigDict, Field
6
+ from pydantic import BaseModel, BeforeValidator, ConfigDict, Field
6
7
  from web3 import Web3
7
8
  from web3.constants import ADDRESS_ZERO
8
9
 
@@ -50,6 +51,17 @@ class CreateCategoricalMarketsParams(BaseModel):
50
51
  SEER_BASE_URL = "https://app.seer.pm"
51
52
 
52
53
 
54
+ def seer_normalize_wei(value: int | None) -> int | None:
55
+ # See https://github.com/seer-pm/demo/blob/main/web/netlify/edge-functions/utils/common.ts#L22
56
+ if value is None:
57
+ return value
58
+ is_in_wei = value > 1e10
59
+ return value if is_in_wei else value * 10**18
60
+
61
+
62
+ SeerNormalizedWei = Annotated[Wei | None, BeforeValidator(seer_normalize_wei)]
63
+
64
+
53
65
  class SeerMarket(BaseModel):
54
66
  model_config = ConfigDict(populate_by_name=True)
55
67
 
@@ -70,6 +82,8 @@ class SeerMarket(BaseModel):
70
82
  payout_reported: bool = Field(alias="payoutReported")
71
83
  payout_numerators: list[int] = Field(alias="payoutNumerators")
72
84
  outcomes_supply: int = Field(alias="outcomesSupply")
85
+ upper_bound: SeerNormalizedWei = Field(alias="upperBound", default=None)
86
+ lower_bound: SeerNormalizedWei = Field(alias="lowerBound", default=None)
73
87
 
74
88
  @property
75
89
  def has_valid_answer(self) -> bool:
@@ -32,6 +32,9 @@ from prediction_market_agent_tooling.markets.blockchain_utils import store_trade
32
32
  from prediction_market_agent_tooling.markets.data_models import ExistingPosition
33
33
  from prediction_market_agent_tooling.markets.market_fees import MarketFees
34
34
  from prediction_market_agent_tooling.markets.omen.omen import OmenAgentMarket
35
+ from prediction_market_agent_tooling.markets.omen.omen_constants import (
36
+ SDAI_CONTRACT_ADDRESS,
37
+ )
35
38
  from prediction_market_agent_tooling.markets.omen.omen_contracts import (
36
39
  SeerAgentResultMappingContract,
37
40
  )
@@ -62,6 +65,7 @@ from prediction_market_agent_tooling.tools.contract import (
62
65
  to_gnosis_chain_contract,
63
66
  )
64
67
  from prediction_market_agent_tooling.tools.cow.cow_order import (
68
+ NoLiquidityAvailableOnCowException,
65
69
  get_buy_token_amount_else_raise,
66
70
  get_orders_by_owner,
67
71
  get_trades_by_owner,
@@ -128,10 +132,41 @@ class SeerAgentMarket(AgentMarket):
128
132
  )
129
133
 
130
134
  def get_token_in_usd(self, x: CollateralToken) -> USD:
131
- return get_token_in_usd(x, self.collateral_token_contract_address_checksummed)
135
+ try:
136
+ return get_token_in_usd(
137
+ x, self.collateral_token_contract_address_checksummed
138
+ )
139
+ except NoLiquidityAvailableOnCowException as e:
140
+ logger.warning(
141
+ f"Could not get quote for {self.collateral_token_contract_address_checksummed} from Cow, exception {e=}. Falling back to pools. "
142
+ )
143
+ token_price = self.get_colateral_price_from_pools()
144
+ if token_price is None:
145
+ raise RuntimeError(
146
+ "Both CoW and pool-fallback way of getting price failed."
147
+ ) from e
148
+ return USD(x.value * token_price.value)
149
+
150
+ def get_colateral_price_from_pools(self) -> CollateralToken | None:
151
+ p = PriceManager.build(HexBytes(HexStr(self.id)))
152
+ token_price = p.get_token_price_from_pools(token=SDAI_CONTRACT_ADDRESS)
153
+ return token_price
132
154
 
133
155
  def get_usd_in_token(self, x: USD) -> CollateralToken:
134
- return get_usd_in_token(x, self.collateral_token_contract_address_checksummed)
156
+ try:
157
+ return get_usd_in_token(
158
+ x, self.collateral_token_contract_address_checksummed
159
+ )
160
+ except NoLiquidityAvailableOnCowException as e:
161
+ logger.warning(
162
+ f"Could not get quote for {self.collateral_token_contract_address_checksummed} from Cow, exception {e=}. Falling back to pools. "
163
+ )
164
+ token_price = self.get_colateral_price_from_pools()
165
+ if not token_price:
166
+ raise RuntimeError(
167
+ "Both CoW and pool-fallback way of getting price failed."
168
+ ) from e
169
+ return CollateralToken(x.value / token_price.value)
135
170
 
136
171
  def get_buy_token_amount(
137
172
  self, bet_amount: USD | CollateralToken, outcome_str: OutcomeStr
@@ -165,14 +200,26 @@ class SeerAgentMarket(AgentMarket):
165
200
  return CollateralToken.zero()
166
201
 
167
202
  wrapped_outcome_token = self.get_wrapped_token_for_outcome(outcome)
168
-
169
- # We calculate how much collateral we would get back if we sold `amount` of outcome token.
170
- value_outcome_token_in_collateral = get_buy_token_amount_else_raise(
171
- sell_amount=amount.as_outcome_wei.as_wei,
172
- sell_token=wrapped_outcome_token,
173
- buy_token=self.collateral_token_contract_address_checksummed,
174
- )
175
- return value_outcome_token_in_collateral.as_token
203
+ try:
204
+ # We calculate how much collateral we would get back if we sold `amount` of outcome token.
205
+ value_outcome_token_in_collateral = get_buy_token_amount_else_raise(
206
+ sell_amount=amount.as_outcome_wei.as_wei,
207
+ sell_token=wrapped_outcome_token,
208
+ buy_token=self.collateral_token_contract_address_checksummed,
209
+ )
210
+ return value_outcome_token_in_collateral.as_token
211
+ except NoLiquidityAvailableOnCowException as e:
212
+ logger.warning(
213
+ f"No liquidity available on Cow for {wrapped_outcome_token} -> {self.collateral_token_contract_address_checksummed}."
214
+ )
215
+ p = PriceManager.build(market_id=HexBytes(HexStr(self.id)))
216
+ price = p.get_token_price_from_pools(token=wrapped_outcome_token)
217
+ if not price:
218
+ logger.info(
219
+ f"Could not get price for token from pools for {wrapped_outcome_token}"
220
+ )
221
+ raise e
222
+ return CollateralToken(price.value * amount.value)
176
223
 
177
224
  @staticmethod
178
225
  def get_trade_balance(api_keys: APIKeys) -> USD:
@@ -346,6 +393,8 @@ class SeerAgentMarket(AgentMarket):
346
393
  resolution=None,
347
394
  volume=None,
348
395
  probabilities=probability_map,
396
+ upper_bound=model.upper_bound,
397
+ lower_bound=model.lower_bound,
349
398
  )
350
399
 
351
400
  return market
@@ -358,6 +407,7 @@ class SeerAgentMarket(AgentMarket):
358
407
  created_after: t.Optional[DatetimeUTC] = None,
359
408
  excluded_questions: set[str] | None = None,
360
409
  fetch_categorical_markets: bool = False,
410
+ fetch_scalar_markets: bool = False,
361
411
  ) -> t.Sequence["SeerAgentMarket"]:
362
412
  seer_subgraph = SeerSubgraphHandler()
363
413
  markets = seer_subgraph.get_markets(
@@ -365,6 +415,8 @@ class SeerAgentMarket(AgentMarket):
365
415
  sort_by=sort_by,
366
416
  filter_by=filter_by,
367
417
  include_categorical_markets=fetch_categorical_markets,
418
+ include_only_scalar_markets=fetch_scalar_markets,
419
+ include_conditional_markets=False,
368
420
  )
369
421
 
370
422
  # We exclude the None values below because `from_data_model_with_subgraph` can return None, which
@@ -496,7 +548,11 @@ class SeerAgentMarket(AgentMarket):
496
548
  )
497
549
  return order_metadata.uid.root
498
550
 
499
- except (UnexpectedResponseError, TimeoutError) as e:
551
+ except (
552
+ UnexpectedResponseError,
553
+ TimeoutError,
554
+ NoLiquidityAvailableOnCowException,
555
+ ) as e:
500
556
  # We don't retry if not enough balance.
501
557
  if "InsufficientBalance" in str(e):
502
558
  raise e
@@ -506,6 +562,10 @@ class SeerAgentMarket(AgentMarket):
506
562
  f"Exception occured when swapping tokens via Cowswap, doing swap via pools. {e}"
507
563
  )
508
564
 
565
+ if not self.has_liquidity():
566
+ logger.error(f"Market {self.id} has no liquidity. Cannot place bet.")
567
+ raise e
568
+
509
569
  tx_receipt = SwapPoolHandler(
510
570
  api_keys=api_keys,
511
571
  market_id=self.id,
@@ -6,7 +6,9 @@ from subgrounds import FieldPath
6
6
  from web3.constants import ADDRESS_ZERO
7
7
 
8
8
  from prediction_market_agent_tooling.deploy.constants import (
9
+ DOWN_OUTCOME_LOWERCASE_IDENTIFIER,
9
10
  NO_OUTCOME_LOWERCASE_IDENTIFIER,
11
+ UP_OUTCOME_LOWERCASE_IDENTIFIER,
10
12
  YES_OUTCOME_LOWERCASE_IDENTIFIER,
11
13
  )
12
14
  from prediction_market_agent_tooling.gtypes import ChecksumAddress, Wei
@@ -66,6 +68,8 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
66
68
  markets_field.finalizeTs,
67
69
  markets_field.wrappedTokens,
68
70
  markets_field.collateralToken,
71
+ markets_field.upperBound,
72
+ markets_field.lowerBound,
69
73
  ]
70
74
  return fields
71
75
 
@@ -74,12 +78,30 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
74
78
  # We do an extra check for the invalid outcome for safety.
75
79
  return [m for m in markets if len(m.outcomes) == 3]
76
80
 
81
+ @staticmethod
82
+ def _create_case_variations_condition(
83
+ identifier: str,
84
+ outcome_condition: str = "outcomes_contains",
85
+ condition: str = "or",
86
+ ) -> dict[str, list[dict[str, list[str]]]]:
87
+ return {
88
+ condition: [
89
+ {outcome_condition: [variation]}
90
+ for variation in [
91
+ identifier.lower(),
92
+ identifier.capitalize(),
93
+ identifier.upper(),
94
+ ]
95
+ ]
96
+ }
97
+
77
98
  @staticmethod
78
99
  def _build_where_statements(
79
100
  filter_by: FilterBy,
80
101
  outcome_supply_gt_if_open: Wei,
81
102
  include_conditional_markets: bool = False,
82
103
  include_categorical_markets: bool = True,
104
+ include_only_scalar_markets: bool = False,
83
105
  ) -> dict[Any, Any]:
84
106
  now = to_int_timestamp(utcnow())
85
107
 
@@ -101,28 +123,43 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
101
123
  if not include_conditional_markets:
102
124
  and_stms["parentMarket"] = ADDRESS_ZERO.lower()
103
125
 
104
- # We are only interested in binary markets of type YES/NO/Invalid.
105
126
  yes_stms, no_stms = {}, {}
106
- if not include_categorical_markets:
107
- # Create single OR conditions with all variations
108
- yes_stms["or"] = [
109
- {"outcomes_contains": [variation]}
110
- for variation in [
111
- YES_OUTCOME_LOWERCASE_IDENTIFIER,
112
- YES_OUTCOME_LOWERCASE_IDENTIFIER.capitalize(),
113
- YES_OUTCOME_LOWERCASE_IDENTIFIER.upper(),
114
- ]
115
- ]
116
- no_stms["or"] = [
117
- {"outcomes_contains": [variation]}
118
- for variation in [
119
- NO_OUTCOME_LOWERCASE_IDENTIFIER,
120
- NO_OUTCOME_LOWERCASE_IDENTIFIER.capitalize(),
121
- NO_OUTCOME_LOWERCASE_IDENTIFIER.upper(),
122
- ]
123
- ]
127
+ exclude_scalar_yes, exclude_scalar_no = {}, {}
124
128
 
125
- where_stms: dict[str, t.Any] = {"and": [and_stms, yes_stms, no_stms]}
129
+ # Return scalar markets.
130
+ if include_only_scalar_markets:
131
+ # We are interested in scalar markets only - this excludes categorical markets
132
+ yes_stms = SeerSubgraphHandler._create_case_variations_condition(
133
+ UP_OUTCOME_LOWERCASE_IDENTIFIER, "outcomes_contains", "or"
134
+ )
135
+ no_stms = SeerSubgraphHandler._create_case_variations_condition(
136
+ DOWN_OUTCOME_LOWERCASE_IDENTIFIER, "outcomes_contains", "or"
137
+ )
138
+ elif include_conditional_markets and not include_categorical_markets:
139
+ # We are interested in binary markets only
140
+ yes_stms = SeerSubgraphHandler._create_case_variations_condition(
141
+ YES_OUTCOME_LOWERCASE_IDENTIFIER, "outcomes_contains", "or"
142
+ )
143
+ no_stms = SeerSubgraphHandler._create_case_variations_condition(
144
+ NO_OUTCOME_LOWERCASE_IDENTIFIER, "outcomes_contains", "or"
145
+ )
146
+
147
+ if (
148
+ not include_only_scalar_markets
149
+ or include_categorical_markets
150
+ or include_conditional_markets
151
+ ):
152
+ # We should not provide any scalar markets because they are exclusive for categorical markets
153
+ exclude_scalar_yes = SeerSubgraphHandler._create_case_variations_condition(
154
+ UP_OUTCOME_LOWERCASE_IDENTIFIER, "outcomes_not_contains", "and"
155
+ )
156
+ exclude_scalar_no = SeerSubgraphHandler._create_case_variations_condition(
157
+ DOWN_OUTCOME_LOWERCASE_IDENTIFIER, "outcomes_not_contains", "and"
158
+ )
159
+
160
+ where_stms: dict[str, t.Any] = {
161
+ "and": [and_stms, yes_stms, no_stms, exclude_scalar_yes, exclude_scalar_no]
162
+ }
126
163
  return where_stms
127
164
 
128
165
  def _build_sort_params(
@@ -159,6 +196,7 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
159
196
  outcome_supply_gt_if_open: Wei = Wei(0),
160
197
  include_conditional_markets: bool = True,
161
198
  include_categorical_markets: bool = True,
199
+ include_only_scalar_markets: bool = False,
162
200
  ) -> list[SeerMarket]:
163
201
  sort_direction, sort_by_field = self._build_sort_params(sort_by)
164
202
 
@@ -169,6 +207,7 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
169
207
  outcome_supply_gt_if_open=outcome_supply_gt_if_open,
170
208
  include_conditional_markets=include_conditional_markets,
171
209
  include_categorical_markets=include_categorical_markets,
210
+ include_only_scalar_markets=include_only_scalar_markets,
172
211
  )
173
212
 
174
213
  # These values can not be set to `None`, but they can be omitted.
@@ -219,26 +258,25 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
219
258
  self, token_address: ChecksumAddress, collateral_address: ChecksumAddress
220
259
  ) -> SeerPool | None:
221
260
  # We iterate through the wrapped tokens and put them in a where clause so that we hit the subgraph endpoint just once.
222
- wheres = []
223
- wheres.extend(
224
- [
261
+
262
+ where_argument = {
263
+ "or": [
225
264
  {
226
- "token0": token_address.lower(),
227
- "token1": collateral_address.lower(),
265
+ "token0_": {"id": token_address.lower()},
266
+ "token1_": {"id": collateral_address.lower()},
228
267
  },
229
268
  {
230
- "token0": collateral_address.lower(),
231
- "token1": token_address.lower(),
269
+ "token0_": {"id": collateral_address.lower()},
270
+ "token1_": {"id": token_address.lower()},
232
271
  },
233
272
  ]
234
- )
235
-
273
+ }
236
274
  optional_params = {}
237
275
  optional_params["orderBy"] = self.swapr_algebra_subgraph.Pool.liquidity
238
276
  optional_params["orderDirection"] = "desc"
239
277
 
240
278
  pools_field = self.swapr_algebra_subgraph.Query.pools(
241
- where=unwrap_generic_value({"or": wheres}), **optional_params
279
+ where=unwrap_generic_value(where_argument), **optional_params
242
280
  )
243
281
 
244
282
  fields = self._get_fields_for_pools(pools_field)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.66.3
3
+ Version: 0.66.4
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.13
@@ -22,14 +22,14 @@ prediction_market_agent_tooling/abis/swapr_router.abi.json,sha256=Y1wK20D1-zdbdl
22
22
  prediction_market_agent_tooling/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  prediction_market_agent_tooling/benchmark/agents.py,sha256=zC5tUM6pPTWtqSddOOSYV_fxHYmZb5uGAb4Ru87Tah8,4221
24
24
  prediction_market_agent_tooling/benchmark/benchmark.py,sha256=hpIpjjePDFTLhK841sGftFbhu8bDDZr28KO4VTneewM,17837
25
- prediction_market_agent_tooling/benchmark/utils.py,sha256=xQd7p9H08-OtN3iC4QT2i9bkUTmrXa6rxGXeg9yMhgU,2986
25
+ prediction_market_agent_tooling/benchmark/utils.py,sha256=vmVTQLER8I7MM_bHFiavrNM9aQe28PL6WihM6J-E65k,3327
26
26
  prediction_market_agent_tooling/chains.py,sha256=1qQstoqXMwqwM7k-KH7MjMz8Ei-D83KZByvDbCZpAxs,116
27
27
  prediction_market_agent_tooling/config.py,sha256=-kJfdDr-m0R-tGZ1KRI-hJJk0mXDt142CAlvwaJ2N2I,11778
28
28
  prediction_market_agent_tooling/data_download/langfuse_data_downloader.py,sha256=VY23h324VKIVkevj1B1O-zL1eEp9AElmcfn6SwYDUSc,14246
29
- prediction_market_agent_tooling/deploy/agent.py,sha256=EEAZQnOqsru1xRzt141iBy_9tG7zo1vnxkLqpg1SuDw,26313
29
+ prediction_market_agent_tooling/deploy/agent.py,sha256=s6DZrf2weAum67RZZ2wm_1emnJqmcW8bzFBXDNWBLgA,27494
30
30
  prediction_market_agent_tooling/deploy/agent_example.py,sha256=yS1fWkHynr9MYGNOM2WsCnRWLPaffY4bOc6bIudrdd4,1377
31
31
  prediction_market_agent_tooling/deploy/betting_strategy.py,sha256=wiUV_zyB9ASLH-VUETIme0H_IMih8jZwiwEmcRa3W5Q,21125
32
- prediction_market_agent_tooling/deploy/constants.py,sha256=Qe9cllgsGMkecfmbhXoFkPxuJyG6ATsrT87RF9SmPWM,249
32
+ prediction_market_agent_tooling/deploy/constants.py,sha256=iobTlZpQD6_2UL9TfoElAnBEbqzIIAKZSsAoMCGhwmA,331
33
33
  prediction_market_agent_tooling/deploy/gcp/deploy.py,sha256=CYUgnfy-9XVk04kkxA_5yp0GE9Mw5caYqlFUZQ2j3ks,3739
34
34
  prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py,sha256=OsPboCFGiZKsvGyntGZHwdqPlLTthITkNF5rJFvGgU8,2582
35
35
  prediction_market_agent_tooling/deploy/gcp/utils.py,sha256=WI2ycX1X-IlTRoNoG4ggFlRwPL28kwM9VGDFD2fePLo,5699
@@ -37,28 +37,28 @@ prediction_market_agent_tooling/deploy/trade_interval.py,sha256=Xk9j45alQ_vrasGv
37
37
  prediction_market_agent_tooling/gtypes.py,sha256=bUIZfZIGvIi3aiZNu5rVE9kRevw8sfMa4bcze6QeBg8,6058
38
38
  prediction_market_agent_tooling/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  prediction_market_agent_tooling/jobs/jobs_models.py,sha256=DoZ9dlvVhpNrnINiR1uy6YUOsuzI_L-avBt362y5xXM,2467
40
- prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=UN7OF-oi3_cgaGEBxJO2SxzURnuTFFEUcrUWM2rnSGA,5044
40
+ prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=lCymxn0iH4xDmqouTP2LMORoGCiTzlK1_yqYtx1Njj4,5132
41
41
  prediction_market_agent_tooling/loggers.py,sha256=o1HyvwtK1DbuC0YWQwJNqzXLLbSC41gNBkEUxiAziEg,5796
42
42
  prediction_market_agent_tooling/logprobs_parser.py,sha256=DBlBQtWX8_URXhzTU3YWIPa76Zx3QDHlx1ARqbgJsVI,5008
43
- prediction_market_agent_tooling/markets/agent_market.py,sha256=nMIa6BkoUWdiz12kFDKuKXD_m6PhLzp3to1vgyj63ZQ,18834
43
+ prediction_market_agent_tooling/markets/agent_market.py,sha256=6x2ajWZYCB0_7qRAQKct1h3qC23CyK3JWXqxerwDXYk,20149
44
44
  prediction_market_agent_tooling/markets/base_subgraph_handler.py,sha256=7RaYO_4qAmQ6ZGM8oPK2-CkiJfKmV9MxM-rJlduaecU,1971
45
45
  prediction_market_agent_tooling/markets/blockchain_utils.py,sha256=6REOt70v3vnzmtCbuRcUTdwt6htXy9nAfNkLOH3Bv1U,2987
46
46
  prediction_market_agent_tooling/markets/categorize.py,sha256=orLZlPaHgeREU66m1amxfWikeV77idV4sZDPB8NgSD0,1300
47
- prediction_market_agent_tooling/markets/data_models.py,sha256=H3G-2I9QFhWrBY_KI-4BO2jMtb_f9yauzHz-zA4NI5Q,8016
47
+ prediction_market_agent_tooling/markets/data_models.py,sha256=x4dBbdPb7dd2JiaD15jDaiA65KB1IcDGnx1hYcY0-2U,10063
48
48
  prediction_market_agent_tooling/markets/manifold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  prediction_market_agent_tooling/markets/manifold/api.py,sha256=tWnjuqvU8pcCuja2B_ynHeds1iiEFc6QWHjeSO_GSxY,7676
50
50
  prediction_market_agent_tooling/markets/manifold/data_models.py,sha256=3z1gFbPMEgCDGqeH-IK8wcvqmIHgLdZX8C2M1UQ7iDw,6740
51
- prediction_market_agent_tooling/markets/manifold/manifold.py,sha256=7s8BC32QkzU80coLTKzms1FrG0E-GEeHfkrl_MgrrLk,5301
51
+ prediction_market_agent_tooling/markets/manifold/manifold.py,sha256=LG54vm0lV05VXk8h3BBdjUyZjOisfmRmbyqDGhwBFPM,5345
52
52
  prediction_market_agent_tooling/markets/manifold/utils.py,sha256=DCigEbpGWkXR-RZT_oJrvJhilmxKFAxcWMjUFi0nBBI,530
53
53
  prediction_market_agent_tooling/markets/market_fees.py,sha256=YeK3ynjYIguB0xf6sO5iyg9lOdW_HD4C6nbJfiGyRCU,1351
54
- prediction_market_agent_tooling/markets/markets.py,sha256=lIEPfPJD1Gz90pTvN2pZi51rpb969STPgQtNFCqHUJg,2667
54
+ prediction_market_agent_tooling/markets/markets.py,sha256=XfUX2xFQS4nU8xxa1rMovgEWRPBJ2NlSbQRMqVoL6Y4,2758
55
55
  prediction_market_agent_tooling/markets/metaculus/api.py,sha256=4TRPGytQQbSdf42DCg2M_JWYPAuNjqZ3eBqaQBLkNks,2736
56
56
  prediction_market_agent_tooling/markets/metaculus/data_models.py,sha256=WjPt0MKeJNtoY-8oLQTLC8vQYYQ-dBj8UZoPq-UBYsQ,3288
57
- prediction_market_agent_tooling/markets/metaculus/metaculus.py,sha256=S1Kkf_F3KuqFO938d5bun60wd8lsGvnGqxsW-tgEBgw,5110
57
+ prediction_market_agent_tooling/markets/metaculus/metaculus.py,sha256=fsDU2c1F9ZZDZ9T8487bX8dw06QXeneYq7Gsq6FGeQQ,5154
58
58
  prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  prediction_market_agent_tooling/markets/omen/cow_contracts.py,sha256=sFaW82u_haL4nze8fjTmnQsOuV0OecunQlAhh1OAw0w,1091
60
60
  prediction_market_agent_tooling/markets/omen/data_models.py,sha256=RsBYSbM4deA6Os4kQ3egH3HvwT80tQho6T1yyoATCMs,31103
61
- prediction_market_agent_tooling/markets/omen/omen.py,sha256=fYDP64-gL3n18K86BXMrM9nO8ZQ4FQY8LynVL7Xm588,50468
61
+ prediction_market_agent_tooling/markets/omen/omen.py,sha256=6pTXa0423IXPnu3rK47DxsNEDI6MigIdyh8GYC7cfDc,50512
62
62
  prediction_market_agent_tooling/markets/omen/omen_constants.py,sha256=XtRk4vpxwUYkTndfjlcmghA-NOIneV8zdHFdyI7tHhM,487
63
63
  prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=27-HRngTqfk_wgvttB3GeVHhy_O2YZcz9izo9OufOI0,29991
64
64
  prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=D-ubf_LumHs_c5rBAAntQ8wGKprtO2V1JZeedmChNIE,11035
@@ -66,14 +66,14 @@ prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=2fL
66
66
  prediction_market_agent_tooling/markets/polymarket/api.py,sha256=UZ4_TG8ceb9Y-qgsOKs8Qiv8zDt957QkT8IX2c83yqo,4800
67
67
  prediction_market_agent_tooling/markets/polymarket/data_models.py,sha256=U1SXTz93FIG3GO1h5BJWSt1hPKn_YAMBeZ3k8IS-ook,4552
68
68
  prediction_market_agent_tooling/markets/polymarket/data_models_web.py,sha256=wCwpZ8Kppy8JG_1HZDfEK_Gg1g1sL7NCbGoPeTeMSko,12756
69
- prediction_market_agent_tooling/markets/polymarket/polymarket.py,sha256=meAhQ5_gwVDvlSxhGGVAvRB7B47zKLnRvZ-_13tKtwY,3433
69
+ prediction_market_agent_tooling/markets/polymarket/polymarket.py,sha256=_g2T4LfI2lLvOKIHXqvoRJ6vlgfgnA_90q3Iy4C4KC0,3477
70
70
  prediction_market_agent_tooling/markets/polymarket/utils.py,sha256=8kTeVjXPcXC6DkDvWYsZQLY7x8DS6CEp_yznSEazsNU,2037
71
- prediction_market_agent_tooling/markets/seer/data_models.py,sha256=osM9WaLsxQf-pfVGq0O-IkM93ehP9a7fVUf-hi2VlMs,5523
71
+ prediction_market_agent_tooling/markets/seer/data_models.py,sha256=Fkn9jG8f0W8XlfM4EFfMSw0V0c3IGSqnKPt1UnG34Ag,6084
72
72
  prediction_market_agent_tooling/markets/seer/exceptions.py,sha256=cEObdjluivD94tgOLzmimR7wgQEOt6SRakrYdhsRQtk,112
73
73
  prediction_market_agent_tooling/markets/seer/price_manager.py,sha256=MClY2NGwOV70nZYIcmzXFy6Ogd8NBIq7telQcQ3VcU4,6243
74
- prediction_market_agent_tooling/markets/seer/seer.py,sha256=_9NAisDsk9cu9RP3O-cphiefENN2nPK1Puk0C5eiGWg,24630
74
+ prediction_market_agent_tooling/markets/seer/seer.py,sha256=ZeP7TecIK8QOLojh-3kLoBmLjjMFGo2YVYB6Kl7bhE8,27331
75
75
  prediction_market_agent_tooling/markets/seer/seer_contracts.py,sha256=uMzpHpI6_tgfhWxPzupLdUJlZ1P2wr0rRiYjAGClKgU,4984
76
- prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py,sha256=pJxch9_u0EdiIatQP1-UFClt8UEfMZAXBlk5wDO_ovk,9940
76
+ prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py,sha256=DwFR_EscEujnja8KvtpiL1U4RKcO8noHnZVoUn17_to,11670
77
77
  prediction_market_agent_tooling/markets/seer/subgraph_data_models.py,sha256=0izxS8Mtzonfdl9UqvFVXrdj0hVzieroekXhogfZKCw,1817
78
78
  prediction_market_agent_tooling/markets/seer/swap_pool_handler.py,sha256=y0pDL2BoxayROy3warEN3r8Fs3rPCPPZ191bgrgZikg,3403
79
79
  prediction_market_agent_tooling/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -125,8 +125,8 @@ prediction_market_agent_tooling/tools/tokens/usd.py,sha256=yuW8iPPtcpP4eLH2nORMD
125
125
  prediction_market_agent_tooling/tools/transaction_cache.py,sha256=K5YKNL2_tR10Iw2TD9fuP-CTGpBbZtNdgbd0B_R7pjg,1814
126
126
  prediction_market_agent_tooling/tools/utils.py,sha256=RlWSlzS2LavMIWrpwn1fevbzgPZruD4VcXTa-XxjWnE,7343
127
127
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=0r26snqCXGdLKCWA8jpe7DV8x2NPYWZwOy4oyKyDCYk,12615
128
- prediction_market_agent_tooling-0.66.3.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
129
- prediction_market_agent_tooling-0.66.3.dist-info/METADATA,sha256=zW4isyxA9kXcMHO8I9V2FcsLMdcjriSD-kKmko9uAZs,8726
130
- prediction_market_agent_tooling-0.66.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
131
- prediction_market_agent_tooling-0.66.3.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
132
- prediction_market_agent_tooling-0.66.3.dist-info/RECORD,,
128
+ prediction_market_agent_tooling-0.66.4.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
129
+ prediction_market_agent_tooling-0.66.4.dist-info/METADATA,sha256=GCQu4RpxmyMXJNideo3bY_YM06t3A-1O4Cxb7Cf5R6U,8726
130
+ prediction_market_agent_tooling-0.66.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
131
+ prediction_market_agent_tooling-0.66.4.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
132
+ prediction_market_agent_tooling-0.66.4.dist-info/RECORD,,