prediction-market-agent-tooling 0.61.0__py3-none-any.whl → 0.61.1.dev461__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 (49) hide show
  1. prediction_market_agent_tooling/config.py +3 -0
  2. prediction_market_agent_tooling/deploy/agent.py +4 -5
  3. prediction_market_agent_tooling/deploy/betting_strategy.py +53 -69
  4. prediction_market_agent_tooling/gtypes.py +105 -27
  5. prediction_market_agent_tooling/jobs/jobs_models.py +5 -7
  6. prediction_market_agent_tooling/jobs/omen/omen_jobs.py +13 -17
  7. prediction_market_agent_tooling/markets/agent_market.py +96 -52
  8. prediction_market_agent_tooling/markets/blockchain_utils.py +1 -27
  9. prediction_market_agent_tooling/markets/data_models.py +40 -44
  10. prediction_market_agent_tooling/markets/manifold/api.py +2 -6
  11. prediction_market_agent_tooling/markets/manifold/data_models.py +33 -25
  12. prediction_market_agent_tooling/markets/manifold/manifold.py +8 -11
  13. prediction_market_agent_tooling/markets/market_fees.py +4 -2
  14. prediction_market_agent_tooling/markets/omen/data_models.py +66 -57
  15. prediction_market_agent_tooling/markets/omen/omen.py +214 -249
  16. prediction_market_agent_tooling/markets/omen/omen_contracts.py +31 -29
  17. prediction_market_agent_tooling/markets/omen/omen_resolving.py +7 -14
  18. prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +20 -14
  19. prediction_market_agent_tooling/markets/polymarket/data_models.py +3 -3
  20. prediction_market_agent_tooling/markets/polymarket/data_models_web.py +4 -4
  21. prediction_market_agent_tooling/markets/polymarket/polymarket.py +3 -5
  22. prediction_market_agent_tooling/markets/seer/data_models.py +8 -8
  23. prediction_market_agent_tooling/markets/seer/seer.py +85 -71
  24. prediction_market_agent_tooling/markets/seer/seer_contracts.py +10 -5
  25. prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +5 -2
  26. prediction_market_agent_tooling/monitor/monitor.py +2 -2
  27. prediction_market_agent_tooling/tools/_generic_value.py +246 -0
  28. prediction_market_agent_tooling/tools/balances.py +9 -11
  29. prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +12 -10
  30. prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +27 -24
  31. prediction_market_agent_tooling/tools/betting_strategies/utils.py +3 -1
  32. prediction_market_agent_tooling/tools/contract.py +14 -10
  33. prediction_market_agent_tooling/tools/cow/cow_manager.py +3 -4
  34. prediction_market_agent_tooling/tools/cow/cow_order.py +3 -4
  35. prediction_market_agent_tooling/tools/langfuse_client_utils.py +13 -1
  36. prediction_market_agent_tooling/tools/omen/sell_positions.py +6 -3
  37. prediction_market_agent_tooling/tools/safe.py +5 -6
  38. prediction_market_agent_tooling/tools/tokens/auto_deposit.py +32 -30
  39. prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +5 -22
  40. prediction_market_agent_tooling/tools/tokens/main_token.py +2 -2
  41. prediction_market_agent_tooling/tools/tokens/token_utils.py +46 -0
  42. prediction_market_agent_tooling/tools/tokens/usd.py +63 -0
  43. prediction_market_agent_tooling/tools/utils.py +14 -8
  44. prediction_market_agent_tooling/tools/web3_utils.py +24 -41
  45. {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/METADATA +2 -1
  46. {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/RECORD +49 -46
  47. {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/LICENSE +0 -0
  48. {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/WHEEL +0 -0
  49. {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,3 @@
1
- import sys
2
1
  import typing as t
3
2
  from datetime import timedelta
4
3
 
@@ -7,16 +6,17 @@ from web3 import Web3
7
6
 
8
7
  from prediction_market_agent_tooling.config import APIKeys
9
8
  from prediction_market_agent_tooling.gtypes import (
9
+ USD,
10
10
  ChecksumAddress,
11
11
  HexAddress,
12
12
  HexStr,
13
- OmenOutcomeToken,
14
13
  OutcomeStr,
14
+ OutcomeToken,
15
+ OutcomeWei,
15
16
  Probability,
17
+ Token,
16
18
  Wei,
17
- wei_type,
18
19
  xDai,
19
- xdai_type,
20
20
  )
21
21
  from prediction_market_agent_tooling.loggers import logger
22
22
  from prediction_market_agent_tooling.markets.agent_market import (
@@ -27,17 +27,11 @@ from prediction_market_agent_tooling.markets.agent_market import (
27
27
  ProcessedTradedMarket,
28
28
  SortBy,
29
29
  )
30
- from prediction_market_agent_tooling.markets.blockchain_utils import (
31
- get_total_balance,
32
- store_trades,
33
- )
30
+ from prediction_market_agent_tooling.markets.blockchain_utils import store_trades
34
31
  from prediction_market_agent_tooling.markets.data_models import (
35
32
  Bet,
36
- BetAmount,
37
- Currency,
38
- Position,
33
+ ExistingPosition,
39
34
  ResolvedBet,
40
- TokenAmount,
41
35
  )
42
36
  from prediction_market_agent_tooling.markets.omen.data_models import (
43
37
  OMEN_FALSE_OUTCOME,
@@ -65,6 +59,7 @@ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
65
59
  build_parent_collection_id,
66
60
  )
67
61
  from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
62
+ SAFE_COLLATERAL_TOKENS_ADDRESSES,
68
63
  OmenSubgraphHandler,
69
64
  )
70
65
  from prediction_market_agent_tooling.tools.balances import get_balances
@@ -81,21 +76,20 @@ from prediction_market_agent_tooling.tools.tokens.auto_withdraw import (
81
76
  auto_withdraw_collateral_token,
82
77
  )
83
78
  from prediction_market_agent_tooling.tools.tokens.main_token import KEEPING_ERC20_TOKEN
79
+ from prediction_market_agent_tooling.tools.tokens.usd import (
80
+ get_token_in_usd,
81
+ get_usd_in_token,
82
+ get_xdai_in_usd,
83
+ )
84
84
  from prediction_market_agent_tooling.tools.utils import (
85
85
  DatetimeUTC,
86
86
  calculate_sell_amount_in_collateral,
87
87
  check_not_none,
88
88
  )
89
- from prediction_market_agent_tooling.tools.web3_utils import (
90
- add_fraction,
91
- get_receipt_block_timestamp,
92
- remove_fraction,
93
- wei_to_xdai,
94
- xdai_to_wei,
95
- )
89
+ from prediction_market_agent_tooling.tools.web3_utils import get_receipt_block_timestamp
96
90
 
97
- OMEN_DEFAULT_REALITIO_BOND_VALUE = xdai_type(0.01)
98
- OMEN_TINY_BET_AMOUNT = xdai_type(0.00001)
91
+ OMEN_DEFAULT_REALITIO_BOND_VALUE = xDai(0.01)
92
+ OMEN_TINY_BET_AMOUNT = USD(0.00001)
99
93
 
100
94
 
101
95
  class OmenAgentMarket(AgentMarket):
@@ -103,7 +97,6 @@ class OmenAgentMarket(AgentMarket):
103
97
  Omen's market class that can be used by agents to make predictions.
104
98
  """
105
99
 
106
- currency: t.ClassVar[Currency] = Currency.xDai
107
100
  base_url: t.ClassVar[str] = PRESAGIO_BASE_URL
108
101
  creator: HexAddress
109
102
 
@@ -152,25 +145,24 @@ class OmenAgentMarket(AgentMarket):
152
145
  def get_liquidity_in_wei(self, web3: Web3 | None = None) -> Wei:
153
146
  return self.get_contract().totalSupply(web3)
154
147
 
155
- def get_liquidity_in_xdai(self, web3: Web3 | None = None) -> xDai:
156
- return wei_to_xdai(self.get_liquidity_in_wei(web3))
148
+ def get_liquidity(self, web3: Web3 | None = None) -> Token:
149
+ return self.get_liquidity_in_wei(web3).as_token
157
150
 
158
- def get_liquidity(self) -> TokenAmount:
159
- return TokenAmount(
160
- amount=self.get_liquidity_in_xdai(),
161
- currency=self.currency,
162
- )
151
+ def get_tiny_bet_amount(self) -> Token:
152
+ return self.get_in_token(OMEN_TINY_BET_AMOUNT)
163
153
 
164
- @classmethod
165
- def get_tiny_bet_amount(cls) -> BetAmount:
166
- return BetAmount(amount=OMEN_TINY_BET_AMOUNT, currency=cls.currency)
154
+ def get_token_in_usd(self, x: Token) -> USD:
155
+ return get_token_in_usd(x, self.collateral_token_contract_address_checksummed)
156
+
157
+ def get_usd_in_token(self, x: USD) -> Token:
158
+ return get_usd_in_token(x, self.collateral_token_contract_address_checksummed)
167
159
 
168
160
  def liquidate_existing_positions(
169
161
  self,
170
162
  bet_outcome: bool,
171
163
  web3: Web3 | None = None,
172
164
  api_keys: APIKeys | None = None,
173
- larger_than: float | None = None,
165
+ larger_than: OutcomeToken | None = None,
174
166
  ) -> None:
175
167
  """
176
168
  Liquidates all previously existing positions.
@@ -179,16 +171,14 @@ class OmenAgentMarket(AgentMarket):
179
171
  api_keys = api_keys if api_keys is not None else APIKeys()
180
172
  better_address = api_keys.bet_from_address
181
173
  larger_than = (
182
- larger_than
183
- if larger_than is not None
184
- else self.get_liquidatable_amount().amount
174
+ larger_than if larger_than is not None else self.get_liquidatable_amount()
185
175
  )
186
176
  prev_positions_for_market = self.get_positions(
187
177
  user_id=better_address, liquid_only=True, larger_than=larger_than
188
178
  )
189
179
 
190
180
  for prev_position in prev_positions_for_market:
191
- for position_outcome, token_amount in prev_position.amounts.items():
181
+ for position_outcome, token_amount in prev_position.amounts_ot.items():
192
182
  position_outcome_bool = get_boolean_outcome(position_outcome)
193
183
  if position_outcome_bool != bet_outcome:
194
184
  self.sell_tokens(
@@ -202,7 +192,7 @@ class OmenAgentMarket(AgentMarket):
202
192
  def place_bet(
203
193
  self,
204
194
  outcome: bool,
205
- amount: BetAmount,
195
+ amount: USD,
206
196
  auto_deposit: bool = True,
207
197
  web3: Web3 | None = None,
208
198
  api_keys: APIKeys | None = None,
@@ -211,12 +201,9 @@ class OmenAgentMarket(AgentMarket):
211
201
  raise ValueError(
212
202
  f"Market {self.id} is not open for trading. Cannot place bet."
213
203
  )
214
- if amount.currency != self.currency:
215
- raise ValueError(f"Omen bets are made in xDai. Got {amount.currency}.")
216
- amount_xdai = xDai(amount.amount)
217
204
  return binary_omen_buy_outcome_tx(
218
205
  api_keys=api_keys if api_keys is not None else APIKeys(),
219
- amount=amount_xdai,
206
+ amount=amount,
220
207
  market=self,
221
208
  binary_outcome=outcome,
222
209
  auto_deposit=auto_deposit,
@@ -226,7 +213,7 @@ class OmenAgentMarket(AgentMarket):
226
213
  def buy_tokens(
227
214
  self,
228
215
  outcome: bool,
229
- amount: TokenAmount,
216
+ amount: USD,
230
217
  web3: Web3 | None = None,
231
218
  api_keys: APIKeys | None = None,
232
219
  ) -> str:
@@ -237,28 +224,37 @@ class OmenAgentMarket(AgentMarket):
237
224
  api_keys=api_keys,
238
225
  )
239
226
 
240
- def calculate_sell_amount_in_collateral(
241
- self, amount: TokenAmount, outcome: bool, web3: Web3 | None = None
242
- ) -> xDai:
227
+ def get_sell_value_of_outcome_token(
228
+ self, outcome: str, amount: OutcomeToken, web3: Web3 | None = None
229
+ ) -> Token:
230
+ """
231
+ Market can have as collateral token GNO for example.
232
+ When you place bet, you buy shares with GNO. For example, you get 10 shares for 1 GNO.
233
+ When selling, you need to provide the amount in GNO, which is cumbersome because you know how much shares you have, but you don't have the price of the shares in GNO.
234
+ Use this to convert how much collateral token (GNO in our example) to sell, to get the amount of shares you want to sell.
235
+ """
236
+ outcome_bool = get_boolean_outcome(outcome)
237
+
243
238
  pool_balance = get_conditional_tokens_balance_for_market(
244
239
  self, self.market_maker_contract_address_checksummed, web3=web3
245
240
  )
246
241
 
247
- sell_str = self.outcomes[self.yes_index if outcome else self.no_index]
248
- other_str = self.outcomes[self.no_index if outcome else self.yes_index]
242
+ sell_str = self.outcomes[self.yes_index if outcome_bool else self.no_index]
243
+ other_str = self.outcomes[self.no_index if outcome_bool else self.yes_index]
249
244
 
250
245
  collateral = calculate_sell_amount_in_collateral(
251
- shares_to_sell=amount.amount,
252
- holdings=wei_to_xdai(pool_balance[self.get_index_set(sell_str)]),
253
- other_holdings=wei_to_xdai(pool_balance[self.get_index_set(other_str)]),
246
+ shares_to_sell=amount,
247
+ holdings=pool_balance[self.get_index_set(sell_str)].as_outcome_token,
248
+ other_holdings=pool_balance[self.get_index_set(other_str)].as_outcome_token,
254
249
  fees=self.fees,
255
250
  )
256
- return xDai(collateral)
251
+
252
+ return collateral
257
253
 
258
254
  def sell_tokens(
259
255
  self,
260
256
  outcome: bool,
261
- amount: TokenAmount,
257
+ amount: USD | OutcomeToken,
262
258
  auto_withdraw: bool = True,
263
259
  api_keys: APIKeys | None = None,
264
260
  web3: Web3 | None = None,
@@ -267,16 +263,8 @@ class OmenAgentMarket(AgentMarket):
267
263
  raise ValueError(
268
264
  f"Market {self.id} is not open for trading. Cannot sell tokens."
269
265
  )
270
-
271
- # Convert from token (i.e. share) number to xDai value of tokens, as
272
- # this is the expected unit of the argument in the smart contract.
273
- collateral = self.calculate_sell_amount_in_collateral(
274
- amount=amount,
275
- outcome=outcome,
276
- web3=web3,
277
- )
278
266
  return binary_omen_sell_outcome_tx(
279
- amount=collateral,
267
+ amount=amount,
280
268
  api_keys=api_keys if api_keys is not None else APIKeys(),
281
269
  market=self,
282
270
  binary_outcome=outcome,
@@ -324,7 +312,7 @@ class OmenAgentMarket(AgentMarket):
324
312
  better_address=user,
325
313
  position_id_in=[p.id for p in positions],
326
314
  # After redeem, this will became zero.
327
- total_balance_bigger_than=wei_type(0),
315
+ total_balance_bigger_than=OutcomeWei(0),
328
316
  )
329
317
  return len(user_positions) > 0
330
318
 
@@ -361,16 +349,16 @@ class OmenAgentMarket(AgentMarket):
361
349
  current_p_yes=model.current_p_yes,
362
350
  condition=model.condition,
363
351
  url=model.url,
364
- volume=wei_to_xdai(model.collateralVolume),
352
+ volume=model.collateralVolume.as_token,
365
353
  close_time=model.close_time,
366
354
  fees=MarketFees(
367
355
  bet_proportion=(
368
- float(wei_to_xdai(model.fee)) if model.fee is not None else 0.0
356
+ model.fee.as_token.value if model.fee is not None else 0.0
369
357
  ),
370
358
  absolute=0,
371
359
  ),
372
360
  outcome_token_pool={
373
- model.outcomes[i]: wei_to_xdai(Wei(model.outcomeTokenAmounts[i]))
361
+ model.outcomes[i]: model.outcomeTokenAmounts[i].as_outcome_token
374
362
  for i in range(len(model.outcomes))
375
363
  },
376
364
  )
@@ -407,22 +395,24 @@ class OmenAgentMarket(AgentMarket):
407
395
  redeem_from_all_user_positions(api_keys)
408
396
 
409
397
  @staticmethod
410
- def get_trade_balance(api_keys: APIKeys, web3: Web3 | None = None) -> xDai:
411
- native_token_balance = get_balances(api_keys.bet_from_address, web3=web3).xdai
412
- return xdai_type(
413
- wei_to_xdai(
414
- KEEPING_ERC20_TOKEN.balanceOf(api_keys.bet_from_address, web3=web3)
415
- )
416
- + native_token_balance
398
+ def get_trade_balance(api_keys: APIKeys, web3: Web3 | None = None) -> USD:
399
+ native_usd = get_xdai_in_usd(
400
+ get_balances(api_keys.bet_from_address, web3=web3).xdai
401
+ )
402
+ keeping_usd = get_token_in_usd(
403
+ KEEPING_ERC20_TOKEN.balance_of_in_tokens(
404
+ api_keys.bet_from_address, web3=web3
405
+ ),
406
+ KEEPING_ERC20_TOKEN.address,
417
407
  )
408
+ return keeping_usd + native_usd
418
409
 
419
410
  @staticmethod
420
411
  def verify_operational_balance(api_keys: APIKeys) -> bool:
421
- return get_total_balance(
422
- api_keys.public_key,
412
+ return get_balances(
423
413
  # Use `public_key`, not `bet_from_address` because transaction costs are paid from the EOA wallet.
424
- sum_wxdai=False,
425
- ) > xdai_type(0.001)
414
+ api_keys.public_key,
415
+ ).xdai > xDai(0.001)
426
416
 
427
417
  def store_prediction(
428
418
  self, processed_market: ProcessedMarket | None, keys: APIKeys, agent_name: str
@@ -497,22 +487,19 @@ class OmenAgentMarket(AgentMarket):
497
487
 
498
488
  def get_token_balance(
499
489
  self, user_id: str, outcome: str, web3: Web3 | None = None
500
- ) -> TokenAmount:
490
+ ) -> OutcomeToken:
501
491
  index_set = self.get_index_set(outcome)
502
492
  balances = get_conditional_tokens_balance_for_market(
503
493
  self, Web3.to_checksum_address(user_id), web3=web3
504
494
  )
505
- return TokenAmount(
506
- amount=wei_to_xdai(balances[index_set]),
507
- currency=self.currency,
508
- )
495
+ return balances[index_set].as_outcome_token
509
496
 
510
- def get_position(self, user_id: str) -> Position | None:
497
+ def get_position(self, user_id: str) -> ExistingPosition | None:
511
498
  liquidatable_amount = self.get_liquidatable_amount()
512
499
  existing_positions = self.get_positions(
513
500
  user_id=user_id,
514
501
  liquid_only=True,
515
- larger_than=liquidatable_amount.amount,
502
+ larger_than=liquidatable_amount,
516
503
  )
517
504
  existing_position = next(
518
505
  iter([i for i in existing_positions if i.market_id == self.id]), None
@@ -524,12 +511,12 @@ class OmenAgentMarket(AgentMarket):
524
511
  cls,
525
512
  user_id: str,
526
513
  liquid_only: bool = False,
527
- larger_than: float = 0,
528
- ) -> list[Position]:
514
+ larger_than: OutcomeToken = OutcomeToken(0),
515
+ ) -> t.Sequence[ExistingPosition]:
529
516
  sgh = OmenSubgraphHandler()
530
517
  omen_positions = sgh.get_user_positions(
531
518
  better_address=Web3.to_checksum_address(user_id),
532
- total_balance_bigger_than=xdai_to_wei(xDai(larger_than)),
519
+ total_balance_bigger_than=larger_than.as_outcome_wei,
533
520
  )
534
521
 
535
522
  # Sort positions and corresponding markets by condition_id
@@ -563,142 +550,105 @@ class OmenAgentMarket(AgentMarket):
563
550
  if liquid_only and not market.can_be_traded():
564
551
  continue
565
552
 
566
- amounts: dict[OutcomeStr, TokenAmount] = {}
553
+ amounts_ot: dict[OutcomeStr, OutcomeToken] = {}
554
+
567
555
  for omen_position in omen_positions:
568
556
  outecome_str = market.index_set_to_outcome_str(
569
557
  omen_position.position.index_set
570
558
  )
571
559
 
572
560
  # Validate that outcomes are unique for a given condition_id.
573
- if outecome_str in amounts:
561
+ if outecome_str in amounts_ot:
574
562
  raise ValueError(
575
- f"Outcome {outecome_str} already exists in {amounts=}"
563
+ f"Outcome {outecome_str} already exists in {amounts_ot=}"
576
564
  )
577
565
 
578
- amounts[outecome_str] = TokenAmount(
579
- amount=wei_to_xdai(omen_position.totalBalance),
580
- currency=cls.currency,
581
- )
582
-
583
- positions.append(Position(market_id=market.id, amounts=amounts))
584
-
585
- return positions
586
-
587
- @classmethod
588
- def get_positions_value(cls, positions: list[Position]) -> BetAmount:
589
- # Two dicts to map from market ids to (1) positions and (2) market.
590
- market_ids_positions = {p.market_id: p for p in positions}
591
- # Check there is only one position per market.
592
- if len(set(market_ids_positions.keys())) != len(positions):
593
- raise ValueError(
594
- f"Markets for positions ({market_ids_positions.keys()}) are not unique."
595
- )
596
- markets: list[OmenAgentMarket] = [
597
- OmenAgentMarket.from_data_model(m)
598
- for m in OmenSubgraphHandler().get_omen_binary_markets(
599
- limit=sys.maxsize, id_in=list(market_ids_positions.keys())
600
- )
601
- ]
602
- market_ids_markets = {m.id: m for m in markets}
566
+ amounts_ot[outecome_str] = omen_position.totalBalance.as_outcome_token
603
567
 
604
- # Validate that dict keys are the same.
605
- if set(market_ids_positions.keys()) != set(market_ids_markets.keys()):
606
- raise ValueError(
607
- f"Market ids in {market_ids_positions.keys()} are not the same as in {market_ids_markets.keys()}"
568
+ amounts_current = {
569
+ k: market.get_token_in_usd(
570
+ # If the market is not open for trading anymore, then current value is equal to potential value.
571
+ market.get_sell_value_of_outcome_token(k, v)
572
+ if market.can_be_traded()
573
+ else v.as_token
574
+ )
575
+ for k, v in amounts_ot.items()
576
+ }
577
+ amounts_potential = {
578
+ k: market.get_token_in_usd(v.as_token) for k, v in amounts_ot.items()
579
+ }
580
+ positions.append(
581
+ ExistingPosition(
582
+ market_id=market.id,
583
+ amounts_current=amounts_current,
584
+ amounts_potential=amounts_potential,
585
+ amounts_ot=amounts_ot,
586
+ )
608
587
  )
609
588
 
610
- # Initialise position value.
611
- total_position_value = 0.0
612
-
613
- for market_id in market_ids_positions.keys():
614
- position = market_ids_positions[market_id]
615
- market = market_ids_markets[market_id]
616
-
617
- yes_tokens = 0.0
618
- no_tokens = 0.0
619
- if OMEN_TRUE_OUTCOME in position.amounts:
620
- yes_tokens = position.amounts[OutcomeStr(OMEN_TRUE_OUTCOME)].amount
621
- if OMEN_FALSE_OUTCOME in position.amounts:
622
- no_tokens = position.amounts[OutcomeStr(OMEN_FALSE_OUTCOME)].amount
623
-
624
- # Account for the value of positions in resolved markets
625
- if market.is_resolved() and market.has_successful_resolution():
626
- valued_tokens = yes_tokens if market.boolean_outcome else no_tokens
627
- total_position_value += valued_tokens
628
-
629
- # Or if the market is open and trading, get the value of the position
630
- elif market.can_be_traded():
631
- total_position_value += yes_tokens * market.yes_outcome_price
632
- total_position_value += no_tokens * market.no_outcome_price
633
-
634
- # Or if the market is still open but not trading, estimate the value
635
- # of the position
636
- else:
637
- if yes_tokens:
638
- yes_price = check_not_none(
639
- market.get_last_trade_yes_outcome_price()
640
- )
641
- total_position_value += yes_tokens * yes_price
642
- if no_tokens:
643
- no_price = check_not_none(market.get_last_trade_no_outcome_price())
644
- total_position_value += no_tokens * no_price
645
-
646
- return BetAmount(amount=total_position_value, currency=cls.currency)
589
+ return positions
647
590
 
648
591
  @classmethod
649
592
  def get_user_url(cls, keys: APIKeys) -> str:
650
593
  return get_omen_user_url(keys.bet_from_address)
651
594
 
652
595
  def get_buy_token_amount(
653
- self, bet_amount: BetAmount, direction: bool
654
- ) -> TokenAmount:
596
+ self, bet_amount: USD | Token, direction: bool
597
+ ) -> OutcomeToken:
655
598
  """
656
599
  Note: this is only valid if the market instance's token pool is
657
600
  up-to-date with the smart contract.
658
601
  """
659
602
  outcome_token_pool = check_not_none(self.outcome_token_pool)
660
603
  amount = get_buy_outcome_token_amount(
661
- investment_amount=bet_amount.amount,
604
+ investment_amount=self.get_in_token(bet_amount),
662
605
  buy_direction=direction,
663
606
  yes_outcome_pool_size=outcome_token_pool[OMEN_TRUE_OUTCOME],
664
607
  no_outcome_pool_size=outcome_token_pool[OMEN_FALSE_OUTCOME],
665
608
  fees=self.fees,
666
609
  )
667
- return TokenAmount(amount=amount, currency=self.currency)
610
+ return amount
668
611
 
669
612
  def _get_buy_token_amount_from_smart_contract(
670
- self, bet_amount: BetAmount, direction: bool
671
- ) -> TokenAmount:
672
- received_token_amount_wei = Wei(
673
- self.get_contract().calcBuyAmount(
674
- investment_amount=xdai_to_wei(xDai(bet_amount.amount)),
675
- outcome_index=self.get_outcome_index(
676
- self.get_outcome_str_from_bool(direction)
677
- ),
678
- )
613
+ self, bet_amount: USD, direction: bool
614
+ ) -> OutcomeToken:
615
+ bet_amount_in_tokens = get_usd_in_token(
616
+ bet_amount, self.collateral_token_contract_address_checksummed
679
617
  )
680
- received_token_amount = float(wei_to_xdai(received_token_amount_wei))
681
- return TokenAmount(amount=received_token_amount, currency=self.currency)
618
+ received_token_amount_wei = self.get_contract().calcBuyAmount(
619
+ investment_amount=bet_amount_in_tokens.as_wei,
620
+ outcome_index=self.get_outcome_index(
621
+ self.get_outcome_str_from_bool(direction)
622
+ ),
623
+ )
624
+ received_token_amount = received_token_amount_wei.as_outcome_token
625
+ return received_token_amount
682
626
 
683
- def get_new_p_yes(self, bet_amount: BetAmount, direction: bool) -> Probability:
627
+ def get_new_p_yes(self, bet_amount: USD, direction: bool) -> Probability:
684
628
  """
685
629
  Calculate the new p_yes based on the bet amount and direction.
686
630
  """
687
631
  if not self.has_token_pool():
688
632
  raise ValueError("Outcome token pool is required to calculate new p_yes.")
689
633
 
634
+ bet_amount_in_tokens = self.get_usd_in_token(bet_amount)
690
635
  outcome_token_pool = check_not_none(self.outcome_token_pool)
691
- yes_outcome_pool_size = outcome_token_pool[self.get_outcome_str_from_bool(True)]
692
- no_outcome_pool_size = outcome_token_pool[self.get_outcome_str_from_bool(False)]
636
+
637
+ yes_outcome_pool_size = outcome_token_pool[
638
+ self.get_outcome_str_from_bool(True)
639
+ ].value
640
+ no_outcome_pool_size = outcome_token_pool[
641
+ self.get_outcome_str_from_bool(False)
642
+ ].value
693
643
 
694
644
  new_yes_outcome_pool_size = yes_outcome_pool_size + (
695
- self.fees.get_bet_size_after_fees(bet_amount.amount)
645
+ self.fees.get_after_fees(bet_amount_in_tokens).value
696
646
  )
697
647
  new_no_outcome_pool_size = no_outcome_pool_size + (
698
- self.fees.get_bet_size_after_fees(bet_amount.amount)
648
+ self.fees.get_after_fees(bet_amount_in_tokens).value
699
649
  )
700
650
 
701
- received_token_amount = self.get_buy_token_amount(bet_amount, direction).amount
651
+ received_token_amount = self.get_buy_token_amount(bet_amount, direction).value
702
652
  if direction:
703
653
  new_yes_outcome_pool_size -= received_token_amount
704
654
  else:
@@ -737,11 +687,18 @@ def get_omen_user_url(address: ChecksumAddress) -> str:
737
687
 
738
688
 
739
689
  def pick_binary_market(
740
- sort_by: SortBy = SortBy.CLOSING_SOONEST, filter_by: FilterBy = FilterBy.OPEN
690
+ sort_by: SortBy = SortBy.CLOSING_SOONEST,
691
+ filter_by: FilterBy = FilterBy.OPEN,
692
+ collateral_token_address_in: (
693
+ tuple[ChecksumAddress, ...] | None
694
+ ) = SAFE_COLLATERAL_TOKENS_ADDRESSES,
741
695
  ) -> OmenMarket:
742
696
  subgraph_handler = OmenSubgraphHandler()
743
697
  return subgraph_handler.get_omen_binary_markets_simple(
744
- limit=1, sort_by=sort_by, filter_by=filter_by
698
+ limit=1,
699
+ sort_by=sort_by,
700
+ filter_by=filter_by,
701
+ collateral_token_address_in=collateral_token_address_in,
745
702
  )[0]
746
703
 
747
704
 
@@ -752,7 +709,7 @@ def pick_binary_market(
752
709
  )
753
710
  def omen_buy_outcome_tx(
754
711
  api_keys: APIKeys,
755
- amount: xDai,
712
+ amount: USD | Token,
756
713
  market: OmenAgentMarket,
757
714
  outcome: str,
758
715
  auto_deposit: bool,
@@ -760,35 +717,32 @@ def omen_buy_outcome_tx(
760
717
  slippage: float = 0.01,
761
718
  ) -> str:
762
719
  """
763
- Bets the given amount of xDai for the given outcome in the given market.
720
+ Bets the given amount for the given outcome in the given market.
764
721
  """
765
- amount_wei = xdai_to_wei(amount)
766
-
767
722
  market_contract: OmenFixedProductMarketMakerContract = market.get_contract()
768
723
  collateral_token_contract = market_contract.get_collateral_token_contract(web3)
769
724
 
770
- # In case of ERC4626, obtained (for example) sDai out of xDai could be lower than the `amount_wei`, so we need to handle it.
771
- amount_wei_to_buy = collateral_token_contract.get_in_shares(amount_wei, web3)
725
+ amount_token = market.get_in_token(amount)
726
+ amount_wei = amount_token.as_wei
772
727
 
773
728
  # Get the index of the outcome we want to buy.
774
729
  outcome_index: int = market.get_outcome_index(outcome)
775
730
 
776
731
  # Calculate the amount of shares we will get for the given investment amount.
777
732
  expected_shares = market_contract.calcBuyAmount(
778
- amount_wei_to_buy, outcome_index, web3=web3
733
+ amount_wei, outcome_index, web3=web3
779
734
  )
780
735
  # Allow small slippage.
781
- expected_shares = remove_fraction(expected_shares, slippage)
736
+ expected_shares = expected_shares.without_fraction(slippage)
782
737
  # Approve the market maker to withdraw our collateral token.
783
738
  collateral_token_contract.approve(
784
739
  api_keys=api_keys,
785
740
  for_address=market_contract.address,
786
- amount_wei=amount_wei_to_buy,
741
+ amount_wei=amount_wei,
787
742
  web3=web3,
788
743
  )
789
744
 
790
745
  if auto_deposit:
791
- # In auto-depositing, we need to deposit the original `amount_wei`, e.g. we can deposit 2 xDai, but receive 1.8 sDai, so for the bet we will use `amount_wei_to_buy`.
792
746
  auto_deposit_collateral_token(
793
747
  collateral_token_contract, amount_wei, api_keys, web3
794
748
  )
@@ -796,7 +750,7 @@ def omen_buy_outcome_tx(
796
750
  # Buy shares using the deposited xDai in the collateral token.
797
751
  tx_receipt = market_contract.buy(
798
752
  api_keys=api_keys,
799
- amount_wei=amount_wei_to_buy,
753
+ amount_wei=amount_wei,
800
754
  outcome_index=outcome_index,
801
755
  min_outcome_tokens_to_buy=expected_shares,
802
756
  web3=web3,
@@ -807,7 +761,7 @@ def omen_buy_outcome_tx(
807
761
 
808
762
  def binary_omen_buy_outcome_tx(
809
763
  api_keys: APIKeys,
810
- amount: xDai,
764
+ amount: USD | Token,
811
765
  market: OmenAgentMarket,
812
766
  binary_outcome: bool,
813
767
  auto_deposit: bool,
@@ -825,7 +779,7 @@ def binary_omen_buy_outcome_tx(
825
779
 
826
780
  def omen_sell_outcome_tx(
827
781
  api_keys: APIKeys,
828
- amount: xDai, # The xDai value of shares to sell.
782
+ amount: OutcomeToken | Token | USD,
829
783
  market: OmenAgentMarket,
830
784
  outcome: str,
831
785
  auto_withdraw: bool,
@@ -839,13 +793,18 @@ def omen_sell_outcome_tx(
839
793
  The number of shares sold will depend on the share price at the time of the
840
794
  transaction.
841
795
  """
842
- amount_wei = xdai_to_wei(amount)
843
- amount_wei = remove_fraction(amount_wei, slippage)
844
-
845
796
  market_contract: OmenFixedProductMarketMakerContract = market.get_contract()
846
797
  conditional_token_contract = OmenConditionalTokenContract()
847
798
  collateral_token_contract = market_contract.get_collateral_token_contract(web3)
848
799
 
800
+ amount_token = (
801
+ market.get_sell_value_of_outcome_token(outcome, amount, web3)
802
+ if isinstance(amount, OutcomeToken)
803
+ else market.get_in_token(amount)
804
+ )
805
+ amount_wei = amount_token.as_wei
806
+ amount_wei = amount_wei.without_fraction(slippage)
807
+
849
808
  # Verify, that markets uses conditional tokens that we expect.
850
809
  if (
851
810
  market_contract.conditionalTokens(web3=web3)
@@ -855,15 +814,15 @@ def omen_sell_outcome_tx(
855
814
  f"Market {market.id} uses conditional token that we didn't expect, {market_contract.conditionalTokens()} != {conditional_token_contract.address=}"
856
815
  )
857
816
 
858
- # Get the index of the outcome we want to buy.
817
+ # Get the index of the outcome we want to sell.
859
818
  outcome_index: int = market.get_outcome_index(outcome)
860
819
 
861
- # Calculate the amount of shares we will sell for the given selling amount of xdai.
820
+ # Calculate the amount of shares we will sell for the given selling amount of collateral.
862
821
  max_outcome_tokens_to_sell = market_contract.calcSellAmount(
863
822
  amount_wei, outcome_index, web3=web3
864
823
  )
865
824
  # Allow small slippage.
866
- max_outcome_tokens_to_sell = add_fraction(max_outcome_tokens_to_sell, slippage)
825
+ max_outcome_tokens_to_sell = max_outcome_tokens_to_sell.with_fraction(slippage)
867
826
 
868
827
  # Approve the market maker to move our (all) conditional tokens.
869
828
  conditional_token_contract.setApprovalForAll(
@@ -893,7 +852,7 @@ def omen_sell_outcome_tx(
893
852
 
894
853
  def binary_omen_sell_outcome_tx(
895
854
  api_keys: APIKeys,
896
- amount: xDai,
855
+ amount: OutcomeToken | Token | USD,
897
856
  market: OmenAgentMarket,
898
857
  binary_outcome: bool,
899
858
  auto_withdraw: bool,
@@ -911,16 +870,16 @@ def binary_omen_sell_outcome_tx(
911
870
 
912
871
  def omen_create_market_tx(
913
872
  api_keys: APIKeys,
914
- initial_funds: xDai,
873
+ initial_funds: USD | Token,
915
874
  question: str,
916
875
  closing_time: DatetimeUTC,
917
876
  category: str,
918
877
  language: str,
919
- outcomes: list[str],
878
+ outcomes: t.Sequence[str],
920
879
  auto_deposit: bool,
921
880
  finalization_timeout: timedelta = REALITY_DEFAULT_FINALIZATION_TIMEOUT,
922
881
  fee_perc: float = OMEN_DEFAULT_MARKET_FEE_PERC,
923
- distribution_hint: list[OmenOutcomeToken] | None = None,
882
+ distribution_hint: list[OutcomeWei] | None = None,
924
883
  collateral_token_address: ChecksumAddress = WrappedxDaiContract().address,
925
884
  arbitrator: Arbitrator = Arbitrator.KLEROS_31_JURORS_WITH_APPEAL,
926
885
  web3: Web3 | None = None,
@@ -931,7 +890,12 @@ def omen_create_market_tx(
931
890
  web3 = (
932
891
  web3 or OmenFixedProductMarketMakerFactoryContract.get_web3()
933
892
  ) # Default to Gnosis web3.
934
- initial_funds_wei = xdai_to_wei(initial_funds)
893
+ initial_funds_in_collateral = (
894
+ get_usd_in_token(initial_funds, collateral_token_address)
895
+ if isinstance(initial_funds, USD)
896
+ else initial_funds
897
+ )
898
+ initial_funds_in_collateral_wei = initial_funds_in_collateral.as_wei
935
899
 
936
900
  realitio_contract = OmenRealitioContract()
937
901
  conditional_token_contract = OmenConditionalTokenContract()
@@ -955,9 +919,9 @@ def omen_create_market_tx(
955
919
 
956
920
  if auto_deposit:
957
921
  auto_deposit_collateral_token(
958
- collateral_token_contract=collateral_token_contract,
922
+ collateral_token_contract,
923
+ initial_funds_in_collateral_wei,
959
924
  api_keys=api_keys,
960
- amount_wei=initial_funds_wei,
961
925
  web3=web3,
962
926
  )
963
927
 
@@ -991,21 +955,16 @@ def omen_create_market_tx(
991
955
  web3=web3,
992
956
  )
993
957
 
994
- # In case of ERC4626, obtained (for example) sDai out of xDai could be lower than the `amount_wei`, so we need to handle it.
995
- initial_funds_in_shares = collateral_token_contract.get_in_shares(
996
- amount=initial_funds_wei, web3=web3
997
- )
998
-
999
958
  # Approve the market maker to withdraw our collateral token.
1000
959
  collateral_token_contract.approve(
1001
960
  api_keys=api_keys,
1002
961
  for_address=factory_contract.address,
1003
- amount_wei=initial_funds_in_shares,
962
+ amount_wei=initial_funds_in_collateral_wei,
1004
963
  web3=web3,
1005
964
  )
1006
965
 
1007
966
  # Create the market.
1008
- fee = xdai_to_wei(xdai_type(fee_perc))
967
+ fee = Token(fee_perc).as_wei
1009
968
  (
1010
969
  market_event,
1011
970
  funding_event,
@@ -1015,7 +974,7 @@ def omen_create_market_tx(
1015
974
  condition_id=condition_id,
1016
975
  fee=fee,
1017
976
  distribution_hint=distribution_hint,
1018
- initial_funds_wei=initial_funds_in_shares,
977
+ initial_funds_wei=initial_funds_in_collateral_wei,
1019
978
  collateral_token_address=collateral_token_contract.address,
1020
979
  web3=web3,
1021
980
  )
@@ -1032,7 +991,7 @@ def omen_create_market_tx(
1032
991
  condition_id=condition_id,
1033
992
  question_event=question_event,
1034
993
  condition_event=cond_event,
1035
- initial_funds=initial_funds_wei,
994
+ initial_funds=initial_funds_in_collateral_wei,
1036
995
  fee=fee,
1037
996
  distribution_hint=distribution_hint,
1038
997
  )
@@ -1041,27 +1000,28 @@ def omen_create_market_tx(
1041
1000
  def omen_fund_market_tx(
1042
1001
  api_keys: APIKeys,
1043
1002
  market: OmenAgentMarket,
1044
- funds: Wei,
1003
+ funds: USD | Token,
1045
1004
  auto_deposit: bool,
1046
1005
  web3: Web3 | None = None,
1047
1006
  ) -> None:
1007
+ funds_in_collateral = market.get_in_token(funds)
1008
+ funds_in_collateral_wei = funds_in_collateral.as_wei
1048
1009
  market_contract = market.get_contract()
1049
1010
  collateral_token_contract = market_contract.get_collateral_token_contract(web3=web3)
1050
1011
 
1051
- amount_to_fund = collateral_token_contract.get_in_shares(funds, web3)
1052
-
1053
1012
  collateral_token_contract.approve(
1054
1013
  api_keys=api_keys,
1055
1014
  for_address=market_contract.address,
1056
- amount_wei=amount_to_fund,
1015
+ amount_wei=funds_in_collateral_wei,
1057
1016
  web3=web3,
1058
1017
  )
1059
1018
 
1060
1019
  if auto_deposit:
1061
- # In auto-depositing, we need to deposit the original `funds`, e.g. we can deposit 2 xDai, but receive 1.8 sDai, so for the funding we will use `amount_to_fund`.
1062
- auto_deposit_collateral_token(collateral_token_contract, funds, api_keys, web3)
1020
+ auto_deposit_collateral_token(
1021
+ collateral_token_contract, funds_in_collateral_wei, api_keys, web3
1022
+ )
1063
1023
 
1064
- market_contract.addFunding(api_keys, amount_to_fund, web3=web3)
1024
+ market_contract.addFunding(api_keys, funds_in_collateral_wei, web3=web3)
1065
1025
 
1066
1026
 
1067
1027
  def omen_redeem_full_position_tx(
@@ -1094,7 +1054,7 @@ def omen_redeem_full_position_tx(
1094
1054
  amount_per_index = get_conditional_tokens_balance_for_market(
1095
1055
  market, from_address, web3
1096
1056
  )
1097
- amount_wei = sum(amount_per_index.values())
1057
+ amount_wei = sum(amount_per_index.values(), start=OutcomeWei.zero())
1098
1058
  if amount_wei == 0:
1099
1059
  logger.debug("No balance to claim. Exiting.")
1100
1060
  return
@@ -1112,10 +1072,10 @@ def omen_redeem_full_position_tx(
1112
1072
  web3=web3,
1113
1073
  )
1114
1074
  new_balance = collateral_token_contract.balanceOf(from_address, web3=web3)
1115
- balance_diff = wei_type(new_balance - original_balance)
1075
+ balance_diff = new_balance - original_balance
1116
1076
 
1117
1077
  logger.info(
1118
- f"Redeemed {wei_to_xdai(balance_diff)} {collateral_token_contract.symbol_cached(web3=web3)} from market {market.question=} ({market.url})."
1078
+ f"Redeemed {balance_diff.as_token} {collateral_token_contract.symbol_cached(web3=web3)} from market {market.question=} ({market.url})."
1119
1079
  )
1120
1080
 
1121
1081
  if auto_withdraw:
@@ -1131,12 +1091,12 @@ def get_conditional_tokens_balance_for_market(
1131
1091
  market: OmenAgentMarket,
1132
1092
  from_address: ChecksumAddress,
1133
1093
  web3: Web3 | None = None,
1134
- ) -> dict[int, Wei]:
1094
+ ) -> dict[int, OutcomeWei]:
1135
1095
  """
1136
1096
  We derive the withdrawable balance from the ConditionalTokens contract through CollectionId -> PositionId (which
1137
1097
  also serves as tokenId) -> TokenBalances.
1138
1098
  """
1139
- balance_per_index_set: dict[int, Wei] = {}
1099
+ balance_per_index_set: dict[int, OutcomeWei] = {}
1140
1100
  conditional_token_contract = OmenConditionalTokenContract()
1141
1101
  parent_collection_id = build_parent_collection_id()
1142
1102
 
@@ -1153,7 +1113,7 @@ def get_conditional_tokens_balance_for_market(
1153
1113
  balance_for_position = conditional_token_contract.balanceOf(
1154
1114
  from_address=from_address, position_id=position_id, web3=web3
1155
1115
  )
1156
- balance_per_index_set[index_set] = wei_type(balance_for_position)
1116
+ balance_per_index_set[index_set] = balance_for_position
1157
1117
 
1158
1118
  return balance_per_index_set
1159
1119
 
@@ -1214,11 +1174,11 @@ def omen_remove_fund_market_tx(
1214
1174
  )
1215
1175
 
1216
1176
  new_balance = market_collateral_token_contract.balanceOf(from_address, web3=web3)
1217
- balance_diff = wei_type(new_balance - original_balance)
1177
+ balance_diff = new_balance - original_balance
1218
1178
 
1219
1179
  logger.debug(f"Result from merge positions {result}")
1220
1180
  logger.info(
1221
- f"Withdrawn {wei_to_xdai(balance_diff)} {market_collateral_token_contract.symbol_cached(web3=web3)} from liquidity at {market.url=}."
1181
+ f"Withdrawn {balance_diff.as_token} {market_collateral_token_contract.symbol_cached(web3=web3)} from liquidity at {market.url=}."
1222
1182
  )
1223
1183
 
1224
1184
  if auto_withdraw:
@@ -1244,7 +1204,7 @@ def redeem_from_all_user_positions(
1244
1204
  user_positions = OmenSubgraphHandler().get_user_positions(
1245
1205
  public_key,
1246
1206
  # After redeem, this will became zero and we won't re-process it.
1247
- total_balance_bigger_than=wei_type(0),
1207
+ total_balance_bigger_than=OutcomeWei(0),
1248
1208
  )
1249
1209
 
1250
1210
  for index, user_position in enumerate(user_positions):
@@ -1272,10 +1232,10 @@ def redeem_from_all_user_positions(
1272
1232
  web3=web3,
1273
1233
  )
1274
1234
  new_balance = collateral_token_contract.balanceOf(public_key, web3=web3)
1275
- balance_diff = wei_type(new_balance - original_balance)
1235
+ balance_diff = new_balance - original_balance
1276
1236
 
1277
1237
  logger.info(
1278
- f"Redeemed {wei_to_xdai(balance_diff)} {collateral_token_contract.symbol_cached(web3=web3)} from position {user_position.id=}."
1238
+ f"Redeemed {balance_diff.as_token} {collateral_token_contract.symbol_cached(web3=web3)} from position {user_position.id=}."
1279
1239
  )
1280
1240
 
1281
1241
  if auto_withdraw:
@@ -1346,23 +1306,21 @@ def send_keeping_token_to_eoa_xdai(
1346
1306
  )
1347
1307
  return
1348
1308
 
1349
- need_to_withdraw = xDai(
1350
- (min_required_balance - current_balances_eoa.xdai) * multiplier
1351
- )
1352
- need_to_withdraw_wei = xdai_to_wei(need_to_withdraw)
1309
+ need_to_withdraw = (min_required_balance - current_balances_eoa.xdai) * multiplier
1310
+ need_to_withdraw_wei = need_to_withdraw.as_xdai_wei
1353
1311
 
1354
- if current_balances_eoa.wxdai >= need_to_withdraw:
1312
+ if current_balances_eoa.wxdai >= need_to_withdraw.as_token:
1355
1313
  # If EOA has enough of wxDai, simply withdraw it.
1356
1314
  logger.info(
1357
1315
  f"Withdrawing {need_to_withdraw} wxDai from EOA to keep the EOA's xDai balance above the minimum required balance {min_required_balance}."
1358
1316
  )
1359
1317
  wxdai_contract.withdraw(
1360
1318
  api_keys=api_keys.copy_without_safe_address(),
1361
- amount_wei=need_to_withdraw_wei,
1319
+ amount_wei=need_to_withdraw_wei.as_wei,
1362
1320
  web3=web3,
1363
1321
  )
1364
1322
 
1365
- elif current_balances_betting.wxdai >= need_to_withdraw:
1323
+ elif current_balances_betting.wxdai >= need_to_withdraw.as_token:
1366
1324
  # If Safe has enough of wxDai:
1367
1325
  # First send them to EOA's address.
1368
1326
  logger.info(
@@ -1372,7 +1330,7 @@ def send_keeping_token_to_eoa_xdai(
1372
1330
  api_keys=api_keys,
1373
1331
  sender=api_keys.bet_from_address,
1374
1332
  recipient=api_keys.public_key,
1375
- amount_wei=need_to_withdraw_wei,
1333
+ amount_wei=need_to_withdraw_wei.as_wei,
1376
1334
  web3=web3,
1377
1335
  )
1378
1336
  # And then simply withdraw it.
@@ -1381,7 +1339,7 @@ def send_keeping_token_to_eoa_xdai(
1381
1339
  )
1382
1340
  wxdai_contract.withdraw(
1383
1341
  api_keys=api_keys.copy_without_safe_address(),
1384
- amount_wei=need_to_withdraw_wei,
1342
+ amount_wei=need_to_withdraw_wei.as_wei,
1385
1343
  web3=web3,
1386
1344
  )
1387
1345
 
@@ -1392,30 +1350,37 @@ def send_keeping_token_to_eoa_xdai(
1392
1350
 
1393
1351
 
1394
1352
  def get_buy_outcome_token_amount(
1395
- investment_amount: float,
1353
+ investment_amount: Token,
1396
1354
  buy_direction: bool,
1397
- yes_outcome_pool_size: float,
1398
- no_outcome_pool_size: float,
1355
+ yes_outcome_pool_size: OutcomeToken,
1356
+ no_outcome_pool_size: OutcomeToken,
1399
1357
  fees: MarketFees,
1400
- ) -> float:
1358
+ ) -> OutcomeToken:
1401
1359
  """
1402
1360
  Calculates the amount of outcome tokens received for a given investment
1403
1361
 
1404
1362
  Taken from https://github.com/gnosis/conditional-tokens-market-makers/blob/6814c0247c745680bb13298d4f0dd7f5b574d0db/contracts/FixedProductMarketMaker.sol#L264
1405
1363
  """
1406
- investment_amount_minus_fees = fees.get_bet_size_after_fees(investment_amount)
1364
+ investment_amount_minus_fees = fees.get_after_fees(investment_amount)
1365
+ investment_amount_minus_fees_as_ot = OutcomeToken(
1366
+ investment_amount_minus_fees.value
1367
+ )
1407
1368
  buy_token_pool_balance = (
1408
1369
  yes_outcome_pool_size if buy_direction else no_outcome_pool_size
1409
1370
  )
1410
1371
 
1411
1372
  pool_balance = no_outcome_pool_size if buy_direction else yes_outcome_pool_size
1412
- denominator = pool_balance + investment_amount_minus_fees
1413
- ending_outcome_balance = buy_token_pool_balance * pool_balance / denominator
1373
+ denominator = pool_balance + investment_amount_minus_fees_as_ot
1374
+ ending_outcome_balance = OutcomeToken(
1375
+ buy_token_pool_balance * pool_balance / denominator
1376
+ )
1414
1377
 
1415
1378
  if ending_outcome_balance <= 0:
1416
1379
  raise ValueError("must have non-zero balances")
1417
1380
 
1418
1381
  result = (
1419
- buy_token_pool_balance + investment_amount_minus_fees - ending_outcome_balance
1382
+ buy_token_pool_balance
1383
+ + investment_amount_minus_fees_as_ot
1384
+ - ending_outcome_balance
1420
1385
  )
1421
1386
  return result