prediction-market-agent-tooling 0.64.0__py3-none-any.whl → 0.64.1.dev590__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.
@@ -418,7 +418,9 @@ class OmenMarket(BaseModel):
418
418
  )
419
419
 
420
420
  def get_resolution_enum_from_answer(self, answer: HexBytes) -> Resolution:
421
- if self.boolean_outcome_from_answer(answer):
421
+ if answer == INVALID_ANSWER_HEX_BYTES:
422
+ return Resolution.CANCEL
423
+ elif self.boolean_outcome_from_answer(answer):
422
424
  return Resolution.YES
423
425
  else:
424
426
  return Resolution.NO
@@ -114,7 +114,8 @@ class SeerAgentMarket(AgentMarket):
114
114
  ) -> OutcomeToken | None:
115
115
  """Returns number of outcome tokens returned for a given bet expressed in collateral units."""
116
116
 
117
- outcome_token = self.get_wrapped_token_for_outcome(direction)
117
+ outcome_str = self.get_outcome_str_from_bool(direction)
118
+ outcome_token = self.get_wrapped_token_for_outcome(outcome_str)
118
119
  bet_amount_in_tokens = self.get_in_token(bet_amount)
119
120
 
120
121
  p = PriceManager.build(market_id=HexBytes(HexStr(self.id)))
@@ -168,7 +169,8 @@ class SeerAgentMarket(AgentMarket):
168
169
  amounts_ot: dict[OutcomeStr, OutcomeToken] = {}
169
170
 
170
171
  for outcome in [True, False]:
171
- wrapped_token = self.get_wrapped_token_for_outcome(outcome)
172
+ outcome_str = self.get_outcome_str_from_bool(outcome)
173
+ wrapped_token = self.get_wrapped_token_for_outcome(outcome_str)
172
174
 
173
175
  outcome_token_balance_wei = OutcomeWei.from_wei(
174
176
  ContractERC20OnGnosisChain(address=wrapped_token).balanceOf(
@@ -192,6 +194,76 @@ class SeerAgentMarket(AgentMarket):
192
194
  amounts_ot=amounts_ot,
193
195
  )
194
196
 
197
+ def get_outcome_str_from_idx(self, outcome_index: int) -> OutcomeStr:
198
+ return self.outcomes[outcome_index]
199
+
200
+ def get_liquidity_for_outcome(
201
+ self, outcome: OutcomeStr, web3: Web3 | None = None
202
+ ) -> CollateralToken:
203
+ """Liquidity per outcome is comprised of the balance of outcomeToken + collateralToken held by the pool itself (see https://github.com/seer-pm/demo/blob/7bfd0a062780ed6567f65714c4fc4f6e6cdf1c4f/web/netlify/functions/utils/fetchPools.ts#L35-L42)."""
204
+
205
+ outcome_token = self.get_wrapped_token_for_outcome(outcome)
206
+ pool = SeerSubgraphHandler().get_pool_by_token(
207
+ token_address=outcome_token,
208
+ collateral_address=self.collateral_token_contract_address_checksummed,
209
+ )
210
+ if not pool:
211
+ logger.info(
212
+ f"Could not fetch pool for token {outcome_token}, no liquidity available for outcome."
213
+ )
214
+ return CollateralToken(0)
215
+ p = PriceManager.build(HexBytes(HexStr(self.id)))
216
+ total = CollateralToken(0)
217
+
218
+ for token_address in [pool.token0.id, pool.token1.id]:
219
+ token_address_checksummed = Web3.to_checksum_address(token_address)
220
+ token_contract = ContractERC20OnGnosisChain(
221
+ address=token_address_checksummed
222
+ )
223
+
224
+ token_balance = token_contract.balance_of_in_tokens(
225
+ for_address=Web3.to_checksum_address(pool.id.hex()),
226
+ web3=web3,
227
+ )
228
+
229
+ # get price
230
+ token_price_in_sdai = (
231
+ p.get_token_price_from_pools(token=token_address_checksummed)
232
+ if token_address_checksummed
233
+ != self.collateral_token_contract_address_checksummed
234
+ else CollateralToken(1.0)
235
+ )
236
+
237
+ # We ignore the liquidity in outcome tokens if price unknown.
238
+ if token_price_in_sdai:
239
+ sdai_balance = token_balance * token_price_in_sdai
240
+ total += sdai_balance
241
+
242
+ return total
243
+
244
+ def get_liquidity(self) -> CollateralToken:
245
+ liquidity_in_collateral = CollateralToken(0)
246
+ # We ignore the invalid outcome
247
+ for outcome in self.outcomes[:-1]:
248
+ liquidity_for_outcome = self.get_liquidity_for_outcome(outcome)
249
+ liquidity_in_collateral += liquidity_for_outcome
250
+
251
+ return liquidity_in_collateral
252
+
253
+ def has_liquidity_for_outcome(self, outcome: OutcomeStr) -> bool:
254
+ liquidity = self.get_liquidity_for_outcome(outcome)
255
+ return liquidity > CollateralToken(0)
256
+
257
+ def has_liquidity(self) -> bool:
258
+ # We define a market as having liquidity if it has liquidity for all outcomes except for the invalid (index -1)
259
+ return all(
260
+ [self.has_liquidity_for_outcome(outcome) for outcome in self.outcomes[:-1]]
261
+ )
262
+
263
+ def get_wrapped_token_for_outcome(self, outcome: OutcomeStr) -> ChecksumAddress:
264
+ outcome_idx = self.outcomes.index(outcome)
265
+ return self.wrapped_tokens[outcome_idx]
266
+
195
267
  def get_position(
196
268
  self, user_id: str, web3: Web3 | None = None
197
269
  ) -> ExistingPosition | None:
@@ -331,26 +403,6 @@ class SeerAgentMarket(AgentMarket):
331
403
  is not None
332
404
  ]
333
405
 
334
- def has_liquidity_for_outcome(self, outcome: bool) -> bool:
335
- outcome_token = self.get_wrapped_token_for_outcome(outcome)
336
- pool = SeerSubgraphHandler().get_pool_by_token(
337
- token_address=outcome_token,
338
- collateral_address=self.collateral_token_contract_address_checksummed,
339
- )
340
- return pool is not None and pool.liquidity > 0
341
-
342
- def has_liquidity(self) -> bool:
343
- # We conservatively define a market as having liquidity if it has liquidity for the `True` outcome token AND the `False` outcome token.
344
- return self.has_liquidity_for_outcome(True) and self.has_liquidity_for_outcome(
345
- False
346
- )
347
-
348
- def get_wrapped_token_for_outcome(self, outcome: bool) -> ChecksumAddress:
349
- outcome_from_enum = SeerOutcomeEnum.from_bool(outcome)
350
- outcome_idx = self.seer_outcomes[outcome_from_enum]
351
- outcome_token = self.wrapped_tokens[outcome_idx]
352
- return outcome_token
353
-
354
406
  def place_bet(
355
407
  self,
356
408
  outcome: bool,
@@ -380,7 +432,8 @@ class SeerAgentMarket(AgentMarket):
380
432
  f"Balance {collateral_balance} not enough for bet size {amount}"
381
433
  )
382
434
 
383
- outcome_token = self.get_wrapped_token_for_outcome(outcome)
435
+ outcome_str = self.get_outcome_str_from_bool(outcome)
436
+ outcome_token = self.get_wrapped_token_for_outcome(outcome_str)
384
437
 
385
438
  # Sell sDAI using token address
386
439
  order_metadata = swap_tokens_waiting(
@@ -407,7 +460,8 @@ class SeerAgentMarket(AgentMarket):
407
460
  """
408
461
  Sells the given number of shares for the given outcome in the given market.
409
462
  """
410
- outcome_token = self.get_wrapped_token_for_outcome(outcome)
463
+ outcome_str = self.get_outcome_str_from_bool(outcome)
464
+ outcome_token = self.get_wrapped_token_for_outcome(outcome_str)
411
465
  api_keys = api_keys if api_keys is not None else APIKeys()
412
466
 
413
467
  token_amount = (
@@ -212,11 +212,11 @@ class ContractERC20BaseClass(ContractBaseClass):
212
212
  owner: ChecksumAddress,
213
213
  for_address: ChecksumAddress,
214
214
  web3: Web3 | None = None,
215
- ) -> int:
215
+ ) -> Wei:
216
216
  allowance_for_user: int = self.call(
217
217
  "allowance", function_params=[owner, for_address], web3=web3
218
218
  )
219
- return allowance_for_user
219
+ return Wei(allowance_for_user)
220
220
 
221
221
  def approve(
222
222
  self,
@@ -3,7 +3,6 @@ from datetime import timedelta
3
3
 
4
4
  import httpx
5
5
  import tenacity
6
- from cowdao_cowpy import swap_tokens
7
6
  from cowdao_cowpy.common.api.errors import UnexpectedResponseError
8
7
  from cowdao_cowpy.common.chains import Chain
9
8
  from cowdao_cowpy.common.config import SupportedChainId
@@ -166,13 +165,20 @@ def swap_tokens_waiting(
166
165
  env: Envs = "prod",
167
166
  web3: Web3 | None = None,
168
167
  ) -> OrderMetaData:
169
- # Approve the CoW Swap Vault Relayer to get the sell token.
170
- ContractERC20OnGnosisChain(address=sell_token).approve(
171
- api_keys,
172
- Web3.to_checksum_address(CowContractAddress.VAULT_RELAYER.value),
173
- amount_wei=amount_wei,
168
+ # Approve the CoW Swap Vault Relayer to get the sell token only if allowance not sufficient.
169
+ for_address = Web3.to_checksum_address(CowContractAddress.VAULT_RELAYER.value)
170
+ current_allowance = ContractERC20OnGnosisChain(address=sell_token).allowance(
171
+ owner=api_keys.bet_from_address,
172
+ for_address=for_address,
174
173
  web3=web3,
175
174
  )
175
+ if current_allowance < amount_wei:
176
+ ContractERC20OnGnosisChain(address=sell_token).approve(
177
+ api_keys,
178
+ for_address=for_address,
179
+ amount_wei=amount_wei,
180
+ web3=web3,
181
+ )
176
182
 
177
183
  # CoW library uses async, so we need to wrap the call in asyncio.run for us to use it.
178
184
  return asyncio.run(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.64.0
3
+ Version: 0.64.1.dev590
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.13
@@ -53,7 +53,7 @@ prediction_market_agent_tooling/markets/metaculus/data_models.py,sha256=FaBCTPPe
53
53
  prediction_market_agent_tooling/markets/metaculus/metaculus.py,sha256=86TIx6cavEWc8Cv4KpZxSvwiSw9oFybXE3YB49pg-CA,4377
54
54
  prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  prediction_market_agent_tooling/markets/omen/cow_contracts.py,sha256=sl1L4cK5nAJwZ2wdhLzqh8p7h_IEValNvLwKUlInKxw,957
56
- prediction_market_agent_tooling/markets/omen/data_models.py,sha256=dtWbRy9tpasssQP80ZFYxAc_9pnVD-zUpVjenBqurnA,30221
56
+ prediction_market_agent_tooling/markets/omen/data_models.py,sha256=I0vS9AMhWlulPQJYgvKq41TbrFVwbk-c89SIPolAtXM,30307
57
57
  prediction_market_agent_tooling/markets/omen/omen.py,sha256=BvTFQ9MZqo9q0wEaE2TzsZ8Q_yPGIZQehehnDIJ3id0,51987
58
58
  prediction_market_agent_tooling/markets/omen/omen_constants.py,sha256=D9oflYKafLQiHYtB5sScMHqmXyzM8JP8J0yATmc4SQQ,233
59
59
  prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=H7jFVLcdbxq6gxWS77YzBFHLnfaItU6MXXVzPzDCkwM,29236
@@ -66,7 +66,7 @@ prediction_market_agent_tooling/markets/polymarket/polymarket.py,sha256=6rc9qulP
66
66
  prediction_market_agent_tooling/markets/polymarket/utils.py,sha256=8kTeVjXPcXC6DkDvWYsZQLY7x8DS6CEp_yznSEazsNU,2037
67
67
  prediction_market_agent_tooling/markets/seer/data_models.py,sha256=TcsDgbk2id1JJ_XT9bnvO4M75dTvOtbzQX67918OQ8E,7442
68
68
  prediction_market_agent_tooling/markets/seer/price_manager.py,sha256=EuOe6zCmEEWXz1loXaQQOYC7ZNQ0cDJn0rZadK1dBlc,5460
69
- prediction_market_agent_tooling/markets/seer/seer.py,sha256=1LTCf_9hQ4LQ_0G0f0Y1HVNT0_lUgUKuVMOYWMLWsN4,18265
69
+ prediction_market_agent_tooling/markets/seer/seer.py,sha256=fx2daHPKRXXNsQYFKI8S0x879WX4FM7uSFAmf2AGWXI,20608
70
70
  prediction_market_agent_tooling/markets/seer/seer_contracts.py,sha256=kH9nPXsx6UM5er42g2f3fLvy36sY5JM2f_beXeuNgUc,3790
71
71
  prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py,sha256=KKRI493VNNAY9tR1AjzNraeH76MvDsBV6GsiLZas0_Y,9859
72
72
  prediction_market_agent_tooling/markets/seer/subgraph_data_models.py,sha256=0izxS8Mtzonfdl9UqvFVXrdj0hVzieroekXhogfZKCw,1817
@@ -89,9 +89,9 @@ prediction_market_agent_tooling/tools/betting_strategies/utils.py,sha256=68zFWUj
89
89
  prediction_market_agent_tooling/tools/caches/db_cache.py,sha256=dB8LNs2JvVRaFCeAKRmIQRwiirsMgtL31he8051wM-g,11431
90
90
  prediction_market_agent_tooling/tools/caches/inmemory_cache.py,sha256=ZW5iI5rmjqeAebu5T7ftRnlkxiL02IC-MxCfDB80x7w,1506
91
91
  prediction_market_agent_tooling/tools/caches/serializers.py,sha256=vFDx4fsPxclXp2q0sv27j4al_M_Tj9aR2JJP-xNHQXA,2151
92
- prediction_market_agent_tooling/tools/contract.py,sha256=1ZFp_VoqTjM8cqOfAhco2Ht0DTqakjhZpuZUrAXr28Q,21332
92
+ prediction_market_agent_tooling/tools/contract.py,sha256=Fxat3JkddtMkeN1HqQoFNB-OEk9YJQczm2LvT2p-Hms,21337
93
93
  prediction_market_agent_tooling/tools/costs.py,sha256=EaAJ7v9laD4VEV3d8B44M4u3_oEO_H16jRVCdoZ93Uw,954
94
- prediction_market_agent_tooling/tools/cow/cow_order.py,sha256=gakwBMVD287v4FrgJC-qwpc5zZHu9yLfTzcmhht-BXA,8797
94
+ prediction_market_agent_tooling/tools/cow/cow_order.py,sha256=nZafUa5d23mFnEL2arm3jLdqdA9zl-z_fN39ceovwg4,9079
95
95
  prediction_market_agent_tooling/tools/custom_exceptions.py,sha256=Fh8z1fbwONvP4-j7AmV_PuEcoqb6-QXa9PJ9m7guMcM,93
96
96
  prediction_market_agent_tooling/tools/datetime_utc.py,sha256=8_WackjtjC8zHXrhQFTGQ6e6Fz_6llWoKR4CSFvIv9I,2766
97
97
  prediction_market_agent_tooling/tools/db/db_manager.py,sha256=GtzHH1NLl8HwqC8Z7s6eTlIQXuV0blxfaV2PeQrBnfQ,3013
@@ -124,8 +124,8 @@ prediction_market_agent_tooling/tools/tokens/usd.py,sha256=yuW8iPPtcpP4eLH2nORMD
124
124
  prediction_market_agent_tooling/tools/transaction_cache.py,sha256=K5YKNL2_tR10Iw2TD9fuP-CTGpBbZtNdgbd0B_R7pjg,1814
125
125
  prediction_market_agent_tooling/tools/utils.py,sha256=AC2a68jwASMWuQi-w8twl8b_M52YwrEJ81abmuEaqMY,6661
126
126
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=zRq-eeBGWt8uUGN9G_WfjmJ0eVvO8aWE9S0Pz_Y6AOA,12342
127
- prediction_market_agent_tooling-0.64.0.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
128
- prediction_market_agent_tooling-0.64.0.dist-info/METADATA,sha256=KnjNTkpA-CeHrfoyRAXM5nEXMLYvXa-H24R0hBeV1Gk,8690
129
- prediction_market_agent_tooling-0.64.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
130
- prediction_market_agent_tooling-0.64.0.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
131
- prediction_market_agent_tooling-0.64.0.dist-info/RECORD,,
127
+ prediction_market_agent_tooling-0.64.1.dev590.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
128
+ prediction_market_agent_tooling-0.64.1.dev590.dist-info/METADATA,sha256=EePp22vTRlQHZkJJJ2nVeobqBrL57_AvljBxlJ7hHfw,8697
129
+ prediction_market_agent_tooling-0.64.1.dev590.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
130
+ prediction_market_agent_tooling-0.64.1.dev590.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
131
+ prediction_market_agent_tooling-0.64.1.dev590.dist-info/RECORD,,