prediction-market-agent-tooling 0.61.1.dev482__py3-none-any.whl → 0.61.1.dev484__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.
- prediction_market_agent_tooling/markets/seer/data_models.py +81 -76
- prediction_market_agent_tooling/markets/seer/price_manager.py +5 -0
- prediction_market_agent_tooling/markets/seer/seer.py +1 -1
- prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +14 -11
- prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +57 -0
- {prediction_market_agent_tooling-0.61.1.dev482.dist-info → prediction_market_agent_tooling-0.61.1.dev484.dist-info}/METADATA +1 -1
- {prediction_market_agent_tooling-0.61.1.dev482.dist-info → prediction_market_agent_tooling-0.61.1.dev484.dist-info}/RECORD +10 -8
- {prediction_market_agent_tooling-0.61.1.dev482.dist-info → prediction_market_agent_tooling-0.61.1.dev484.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.61.1.dev482.dist-info → prediction_market_agent_tooling-0.61.1.dev484.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.61.1.dev482.dist-info → prediction_market_agent_tooling-0.61.1.dev484.dist-info}/entry_points.txt +0 -0
@@ -5,7 +5,6 @@ from urllib.parse import urljoin
|
|
5
5
|
|
6
6
|
from pydantic import BaseModel, ConfigDict, Field
|
7
7
|
from web3 import Web3
|
8
|
-
from web3.constants import ADDRESS_ZERO
|
9
8
|
|
10
9
|
from prediction_market_agent_tooling.config import RPCConfig
|
11
10
|
from prediction_market_agent_tooling.gtypes import (
|
@@ -13,39 +12,22 @@ from prediction_market_agent_tooling.gtypes import (
|
|
13
12
|
HexAddress,
|
14
13
|
HexBytes,
|
15
14
|
Probability,
|
16
|
-
Wei,
|
17
15
|
xdai_type,
|
18
16
|
)
|
19
17
|
from prediction_market_agent_tooling.loggers import logger
|
20
18
|
from prediction_market_agent_tooling.markets.data_models import Resolution
|
19
|
+
from prediction_market_agent_tooling.markets.seer.subgraph_data_models import (
|
20
|
+
SeerParentMarket,
|
21
|
+
SeerPool,
|
22
|
+
)
|
23
|
+
from prediction_market_agent_tooling.tools.caches.inmemory_cache import (
|
24
|
+
persistent_inmemory_cache,
|
25
|
+
)
|
21
26
|
from prediction_market_agent_tooling.tools.cow.cow_manager import CowManager
|
22
27
|
from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC
|
23
28
|
from prediction_market_agent_tooling.tools.web3_utils import xdai_to_wei
|
24
29
|
|
25
30
|
|
26
|
-
class CreateCategoricalMarketsParams(BaseModel):
|
27
|
-
model_config = ConfigDict(populate_by_name=True)
|
28
|
-
|
29
|
-
market_name: str = Field(..., alias="marketName")
|
30
|
-
outcomes: list[str]
|
31
|
-
# Only relevant for scalar markets
|
32
|
-
question_start: str = Field(alias="questionStart", default="")
|
33
|
-
question_end: str = Field(alias="questionEnd", default="")
|
34
|
-
outcome_type: str = Field(alias="outcomeType", default="")
|
35
|
-
|
36
|
-
# Not needed for non-conditional markets.
|
37
|
-
parent_outcome: int = Field(alias="parentOutcome", default=0)
|
38
|
-
parent_market: HexAddress = Field(alias="parentMarket", default=ADDRESS_ZERO)
|
39
|
-
|
40
|
-
category: str
|
41
|
-
lang: str
|
42
|
-
lower_bound: int = Field(alias="lowerBound", default=0)
|
43
|
-
upper_bound: int = Field(alias="upperBound", default=0)
|
44
|
-
min_bond: Wei = Field(..., alias="minBond")
|
45
|
-
opening_time: int = Field(..., alias="openingTime")
|
46
|
-
token_names: list[str] = Field(..., alias="tokenNames")
|
47
|
-
|
48
|
-
|
49
31
|
class SeerOutcomeEnum(str, Enum):
|
50
32
|
YES = "yes"
|
51
33
|
NO = "no"
|
@@ -84,10 +66,6 @@ class SeerOutcomeEnum(str, Enum):
|
|
84
66
|
raise ValueError(f"Unknown outcome: {self}")
|
85
67
|
|
86
68
|
|
87
|
-
class SeerParentMarket(BaseModel):
|
88
|
-
id: HexBytes
|
89
|
-
|
90
|
-
|
91
69
|
SEER_BASE_URL = "https://app.seer.pm"
|
92
70
|
|
93
71
|
|
@@ -187,14 +165,72 @@ class SeerMarket(BaseModel):
|
|
187
165
|
def created_time(self) -> DatetimeUTC:
|
188
166
|
return DatetimeUTC.to_datetime_utc(self.block_timestamp)
|
189
167
|
|
168
|
+
@persistent_inmemory_cache
|
169
|
+
def get_price_for_token(
|
170
|
+
self,
|
171
|
+
token: ChecksumAddress,
|
172
|
+
) -> float:
|
173
|
+
collateral_exchange_amount = xdai_to_wei(xdai_type(1))
|
174
|
+
try:
|
175
|
+
quote = CowManager().get_quote(
|
176
|
+
collateral_token=self.collateral_token_contract_address_checksummed,
|
177
|
+
buy_token=token,
|
178
|
+
sell_amount=collateral_exchange_amount,
|
179
|
+
)
|
180
|
+
except Exception as e:
|
181
|
+
logger.warning(
|
182
|
+
f"Could not get quote for {token=} from Cow, exception {e=}. Falling back to pools. "
|
183
|
+
)
|
184
|
+
price = self.get_token_price_from_pools(token=token)
|
185
|
+
return price
|
186
|
+
|
187
|
+
return collateral_exchange_amount / float(quote.quote.buyAmount.root)
|
188
|
+
|
189
|
+
@staticmethod
|
190
|
+
def _pool_token0_matches_token(token: ChecksumAddress, pool: SeerPool) -> bool:
|
191
|
+
return pool.token0.id.hex().lower() == token.lower()
|
192
|
+
|
193
|
+
def get_token_price_from_pools(
|
194
|
+
self,
|
195
|
+
token: ChecksumAddress,
|
196
|
+
collateral_token_contract_address_checksummed: ChecksumAddress,
|
197
|
+
) -> float:
|
198
|
+
pool = self.subgraph_handler.get_pool_by_token(token_address=token)
|
199
|
+
|
200
|
+
if not pool:
|
201
|
+
logger.warning(f"Could not find a pool for {token=}, returning 0.")
|
202
|
+
return 0
|
203
|
+
# Check if other token is market's collateral (sanity check).
|
204
|
+
|
205
|
+
collateral_address = (
|
206
|
+
pool.token0.id
|
207
|
+
if self._pool_token0_matches_token(token=token, pool=pool)
|
208
|
+
else pool.token1.id
|
209
|
+
)
|
210
|
+
if (
|
211
|
+
collateral_address.hex().lower()
|
212
|
+
!= collateral_token_contract_address_checksummed.lower()
|
213
|
+
):
|
214
|
+
logger.warning(
|
215
|
+
f"Pool {pool.id.hex()} has collateral mismatch with market. Collateral from pool {collateral_address.hex()}, collateral from market {collateral_token_contract_address_checksummed}, returning 0."
|
216
|
+
)
|
217
|
+
return 0
|
218
|
+
|
219
|
+
price_in_collateral_units = (
|
220
|
+
pool.token0Price
|
221
|
+
if self._pool_token0_matches_token(pool)
|
222
|
+
else pool.token1Price
|
223
|
+
)
|
224
|
+
return price_in_collateral_units
|
225
|
+
|
190
226
|
@property
|
191
227
|
def current_p_yes(self) -> Probability:
|
192
228
|
price_data = {}
|
193
|
-
for idx in
|
194
|
-
|
195
|
-
|
196
|
-
token=Web3.to_checksum_address(wrapped_token)
|
229
|
+
for idx, wrapped_token in enumerate(self.wrapped_tokens):
|
230
|
+
price = self.get_price_for_token(
|
231
|
+
token=Web3.to_checksum_address(wrapped_token),
|
197
232
|
)
|
233
|
+
|
198
234
|
price_data[idx] = price
|
199
235
|
|
200
236
|
if sum(price_data.values()) == 0:
|
@@ -203,51 +239,20 @@ class SeerMarket(BaseModel):
|
|
203
239
|
)
|
204
240
|
return Probability(0)
|
205
241
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
)
|
218
|
-
except Exception as e:
|
219
|
-
logger.warning(f"Could not get quote for {token=}, returning price 0. {e=}")
|
220
|
-
return 0
|
221
|
-
|
222
|
-
return collateral_exchange_amount / float(quote.quote.buyAmount.root)
|
242
|
+
price_yes = price_data[self.outcome_as_enums[SeerOutcomeEnum.YES]]
|
243
|
+
price_no = price_data[self.outcome_as_enums[SeerOutcomeEnum.NO]]
|
244
|
+
if price_yes and not price_no:
|
245
|
+
# We simply return p_yes since it's probably a bug that p_no wasn't found.
|
246
|
+
return Probability(price_yes)
|
247
|
+
elif price_no and not price_yes:
|
248
|
+
# We return the complement of p_no (and ignore invalid).
|
249
|
+
return Probability(1.0 - price_no)
|
250
|
+
else:
|
251
|
+
# If all prices are available, we normalize price_yes by the other prices for the final probability.
|
252
|
+
price_yes = price_yes / sum(price_data.values())
|
253
|
+
return Probability(price_yes)
|
223
254
|
|
224
255
|
@property
|
225
256
|
def url(self) -> str:
|
226
257
|
chain_id = RPCConfig().chain_id
|
227
258
|
return urljoin(SEER_BASE_URL, f"markets/{chain_id}/{self.id.hex()}")
|
228
|
-
|
229
|
-
|
230
|
-
class SeerToken(BaseModel):
|
231
|
-
id: HexBytes
|
232
|
-
name: str
|
233
|
-
symbol: str
|
234
|
-
|
235
|
-
|
236
|
-
class SeerPool(BaseModel):
|
237
|
-
model_config = ConfigDict(populate_by_name=True)
|
238
|
-
id: HexBytes
|
239
|
-
liquidity: int
|
240
|
-
token0: SeerToken
|
241
|
-
token1: SeerToken
|
242
|
-
token0Price: float
|
243
|
-
token1Price: float
|
244
|
-
sqrtPrice: int
|
245
|
-
|
246
|
-
|
247
|
-
class NewMarketEvent(BaseModel):
|
248
|
-
market: HexAddress
|
249
|
-
marketName: str
|
250
|
-
parentMarket: HexAddress
|
251
|
-
conditionId: HexBytes
|
252
|
-
questionId: HexBytes
|
253
|
-
questionsIds: list[HexBytes]
|
@@ -352,4 +352,4 @@ def extract_market_address_from_tx(
|
|
352
352
|
.process_receipt(tx_receipt)
|
353
353
|
)
|
354
354
|
new_market_event = NewMarketEvent(**event_logs[0]["args"])
|
355
|
-
return Web3.to_checksum_address(new_market_event.
|
355
|
+
return Web3.to_checksum_address(new_market_event.seer_market)
|
@@ -5,14 +5,15 @@ from typing import Any
|
|
5
5
|
from subgrounds import FieldPath
|
6
6
|
from web3.constants import ADDRESS_ZERO
|
7
7
|
|
8
|
+
from prediction_market_agent_tooling.gtypes import ChecksumAddress
|
8
9
|
from prediction_market_agent_tooling.markets.agent_market import FilterBy, SortBy
|
9
10
|
from prediction_market_agent_tooling.markets.base_subgraph_handler import (
|
10
11
|
BaseSubgraphHandler,
|
11
12
|
)
|
12
13
|
from prediction_market_agent_tooling.markets.seer.data_models import (
|
13
14
|
SeerMarket,
|
14
|
-
SeerPool,
|
15
15
|
)
|
16
|
+
from prediction_market_agent_tooling.markets.seer.subgraph_data_models import SeerPool
|
16
17
|
from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
|
17
18
|
from prediction_market_agent_tooling.tools.utils import to_int_timestamp, utcnow
|
18
19
|
|
@@ -192,7 +193,7 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
|
|
192
193
|
return binary_markets
|
193
194
|
|
194
195
|
def get_market_by_id(self, market_id: HexBytes) -> SeerMarket:
|
195
|
-
markets_field = self.seer_subgraph.Query.
|
196
|
+
markets_field = self.seer_subgraph.Query.seer_market(id=market_id.hex().lower())
|
196
197
|
fields = self._get_fields_for_markets(markets_field)
|
197
198
|
markets = self.do_query(fields=fields, pydantic_model=SeerMarket)
|
198
199
|
if len(markets) != 1:
|
@@ -217,17 +218,19 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
|
|
217
218
|
]
|
218
219
|
return fields
|
219
220
|
|
220
|
-
def
|
221
|
+
def get_pool_by_token(self, token_address: ChecksumAddress) -> SeerPool | None:
|
221
222
|
# We iterate through the wrapped tokens and put them in a where clause so that we hit the subgraph endpoint just once.
|
222
223
|
wheres = []
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
)
|
224
|
+
wheres.extend(
|
225
|
+
[
|
226
|
+
{"token0": token_address.lower()},
|
227
|
+
{"token1": token_address.lower()},
|
228
|
+
]
|
229
|
+
)
|
230
230
|
pools_field = self.swapr_algebra_subgraph.Query.pools(where={"or": wheres})
|
231
231
|
fields = self._get_fields_for_pools(pools_field)
|
232
232
|
pools = self.do_query(fields=fields, pydantic_model=SeerPool)
|
233
|
-
|
233
|
+
# We assume there is only one pool for outcomeToken/sDAI.
|
234
|
+
if pools:
|
235
|
+
return pools[0]
|
236
|
+
return None
|
@@ -0,0 +1,57 @@
|
|
1
|
+
from pydantic import BaseModel, ConfigDict, Field
|
2
|
+
from web3.constants import ADDRESS_ZERO
|
3
|
+
|
4
|
+
from prediction_market_agent_tooling.gtypes import HexBytes, HexAddress, Wei
|
5
|
+
|
6
|
+
|
7
|
+
class SeerToken(BaseModel):
|
8
|
+
id: HexBytes
|
9
|
+
name: str
|
10
|
+
symbol: str
|
11
|
+
|
12
|
+
|
13
|
+
class SeerPool(BaseModel):
|
14
|
+
model_config = ConfigDict(populate_by_name=True)
|
15
|
+
id: HexBytes
|
16
|
+
liquidity: int
|
17
|
+
token0: SeerToken
|
18
|
+
token1: SeerToken
|
19
|
+
token0Price: float
|
20
|
+
token1Price: float
|
21
|
+
sqrtPrice: int
|
22
|
+
|
23
|
+
|
24
|
+
class NewMarketEvent(BaseModel):
|
25
|
+
market: HexAddress
|
26
|
+
marketName: str
|
27
|
+
parentMarket: HexAddress
|
28
|
+
conditionId: HexBytes
|
29
|
+
questionId: HexBytes
|
30
|
+
questionsIds: list[HexBytes]
|
31
|
+
|
32
|
+
|
33
|
+
class CreateCategoricalMarketsParams(BaseModel):
|
34
|
+
model_config = ConfigDict(populate_by_name=True)
|
35
|
+
|
36
|
+
market_name: str = Field(..., alias="marketName")
|
37
|
+
outcomes: list[str]
|
38
|
+
# Only relevant for scalar markets
|
39
|
+
question_start: str = Field(alias="questionStart", default="")
|
40
|
+
question_end: str = Field(alias="questionEnd", default="")
|
41
|
+
outcome_type: str = Field(alias="outcomeType", default="")
|
42
|
+
|
43
|
+
# Not needed for non-conditional markets.
|
44
|
+
parent_outcome: int = Field(alias="parentOutcome", default=0)
|
45
|
+
parent_market: HexAddress = Field(alias="parentMarket", default=ADDRESS_ZERO)
|
46
|
+
|
47
|
+
category: str
|
48
|
+
lang: str
|
49
|
+
lower_bound: int = Field(alias="lowerBound", default=0)
|
50
|
+
upper_bound: int = Field(alias="upperBound", default=0)
|
51
|
+
min_bond: Wei = Field(..., alias="minBond")
|
52
|
+
opening_time: int = Field(..., alias="openingTime")
|
53
|
+
token_names: list[str] = Field(..., alias="tokenNames")
|
54
|
+
|
55
|
+
|
56
|
+
class SeerParentMarket(BaseModel):
|
57
|
+
id: HexBytes
|
@@ -61,10 +61,12 @@ prediction_market_agent_tooling/markets/polymarket/data_models.py,sha256=Fd5PI5y
|
|
61
61
|
prediction_market_agent_tooling/markets/polymarket/data_models_web.py,sha256=VZhVccTApygSKMmy6Au2G02JCJOKJnR_oVeKlaesuSg,12548
|
62
62
|
prediction_market_agent_tooling/markets/polymarket/polymarket.py,sha256=NRoZK71PtH8kkangMqme7twcAXhRJSSabbmOir-UnAI,3418
|
63
63
|
prediction_market_agent_tooling/markets/polymarket/utils.py,sha256=8kTeVjXPcXC6DkDvWYsZQLY7x8DS6CEp_yznSEazsNU,2037
|
64
|
-
prediction_market_agent_tooling/markets/seer/data_models.py,sha256=
|
65
|
-
prediction_market_agent_tooling/markets/seer/
|
64
|
+
prediction_market_agent_tooling/markets/seer/data_models.py,sha256=jLfCiwkw4OZyqw5RV3kEimmWWeBBF6SMmn4Oxzlm5pQ,9101
|
65
|
+
prediction_market_agent_tooling/markets/seer/price_manager.py,sha256=k0I8xLFs0cXEDrTiOtQUxVPaAVYchfz-D8cijeONlXc,176
|
66
|
+
prediction_market_agent_tooling/markets/seer/seer.py,sha256=Anxp66UUzIIKt5wgLoqtUjUM-5HQ0wC5f5rDiYwrRRg,12959
|
66
67
|
prediction_market_agent_tooling/markets/seer/seer_contracts.py,sha256=E7CYAKZiK6cg3dyj1kJuIPKSYYUft98F64shF5S0g4s,2730
|
67
|
-
prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py,sha256=
|
68
|
+
prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py,sha256=lcaKbFHxigMYwi4TCePyTb5HXJhGoCu5dJPFWTj5E28,9047
|
69
|
+
prediction_market_agent_tooling/markets/seer/subgraph_data_models.py,sha256=RIt2oO-PbykzbYN11Qltt8tjjYTty-PfjH3Q4D2VEoA,1644
|
68
70
|
prediction_market_agent_tooling/monitor/financial_metrics/financial_metrics.py,sha256=fjIgjDIx5MhH5mwf7S0cspLOOSU3elYLhGYoIiM26mU,2746
|
69
71
|
prediction_market_agent_tooling/monitor/markets/manifold.py,sha256=TS4ERwTfQnot8dhekNyVNhJYf5ysYsjF-9v5_kM3aVI,3334
|
70
72
|
prediction_market_agent_tooling/monitor/markets/metaculus.py,sha256=LOnyWWBFdg10-cTWdb76nOsNjDloO8OfMT85GBzRCFI,1455
|
@@ -117,8 +119,8 @@ prediction_market_agent_tooling/tools/tokens/main_token.py,sha256=7JPgVF4RbiFzLD
|
|
117
119
|
prediction_market_agent_tooling/tools/transaction_cache.py,sha256=K5YKNL2_tR10Iw2TD9fuP-CTGpBbZtNdgbd0B_R7pjg,1814
|
118
120
|
prediction_market_agent_tooling/tools/utils.py,sha256=jLG4nbEoIzzJiZ4RgMx4Q969Zdl0p0s63p8uET_0Fuw,6440
|
119
121
|
prediction_market_agent_tooling/tools/web3_utils.py,sha256=3wfqNxvMn44ivweFRoeKNVb9QRtFd7kFtp7VUY5juEE,12862
|
120
|
-
prediction_market_agent_tooling-0.61.1.
|
121
|
-
prediction_market_agent_tooling-0.61.1.
|
122
|
-
prediction_market_agent_tooling-0.61.1.
|
123
|
-
prediction_market_agent_tooling-0.61.1.
|
124
|
-
prediction_market_agent_tooling-0.61.1.
|
122
|
+
prediction_market_agent_tooling-0.61.1.dev484.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
123
|
+
prediction_market_agent_tooling-0.61.1.dev484.dist-info/METADATA,sha256=IpD8pQ3IicG0EyoDNg33hCkmVHBpXGKbNg-_FpdXve0,8636
|
124
|
+
prediction_market_agent_tooling-0.61.1.dev484.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
125
|
+
prediction_market_agent_tooling-0.61.1.dev484.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
|
126
|
+
prediction_market_agent_tooling-0.61.1.dev484.dist-info/RECORD,,
|
File without changes
|
File without changes
|