prediction-market-agent-tooling 0.61.1.dev463__py3-none-any.whl → 0.61.1.dev482__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 (48) hide show
  1. prediction_market_agent_tooling/deploy/agent.py +5 -4
  2. prediction_market_agent_tooling/deploy/betting_strategy.py +69 -53
  3. prediction_market_agent_tooling/gtypes.py +27 -105
  4. prediction_market_agent_tooling/jobs/jobs_models.py +7 -5
  5. prediction_market_agent_tooling/jobs/omen/omen_jobs.py +17 -13
  6. prediction_market_agent_tooling/markets/agent_market.py +52 -96
  7. prediction_market_agent_tooling/markets/blockchain_utils.py +27 -1
  8. prediction_market_agent_tooling/markets/data_models.py +44 -40
  9. prediction_market_agent_tooling/markets/manifold/api.py +6 -2
  10. prediction_market_agent_tooling/markets/manifold/data_models.py +25 -33
  11. prediction_market_agent_tooling/markets/manifold/manifold.py +11 -8
  12. prediction_market_agent_tooling/markets/market_fees.py +2 -4
  13. prediction_market_agent_tooling/markets/omen/data_models.py +57 -66
  14. prediction_market_agent_tooling/markets/omen/omen.py +249 -214
  15. prediction_market_agent_tooling/markets/omen/omen_contracts.py +29 -31
  16. prediction_market_agent_tooling/markets/omen/omen_resolving.py +14 -7
  17. prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +14 -20
  18. prediction_market_agent_tooling/markets/polymarket/data_models.py +3 -3
  19. prediction_market_agent_tooling/markets/polymarket/data_models_web.py +4 -4
  20. prediction_market_agent_tooling/markets/polymarket/polymarket.py +5 -3
  21. prediction_market_agent_tooling/markets/seer/data_models.py +12 -8
  22. prediction_market_agent_tooling/markets/seer/seer.py +71 -85
  23. prediction_market_agent_tooling/markets/seer/seer_contracts.py +5 -10
  24. prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +14 -9
  25. prediction_market_agent_tooling/monitor/monitor.py +2 -2
  26. prediction_market_agent_tooling/tools/balances.py +11 -9
  27. prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +10 -12
  28. prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +24 -27
  29. prediction_market_agent_tooling/tools/betting_strategies/utils.py +1 -3
  30. prediction_market_agent_tooling/tools/contract.py +10 -14
  31. prediction_market_agent_tooling/tools/cow/cow_manager.py +4 -3
  32. prediction_market_agent_tooling/tools/cow/cow_order.py +4 -3
  33. prediction_market_agent_tooling/tools/langfuse_client_utils.py +1 -13
  34. prediction_market_agent_tooling/tools/omen/sell_positions.py +3 -6
  35. prediction_market_agent_tooling/tools/safe.py +6 -5
  36. prediction_market_agent_tooling/tools/tokens/auto_deposit.py +30 -32
  37. prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +22 -5
  38. prediction_market_agent_tooling/tools/tokens/main_token.py +2 -2
  39. prediction_market_agent_tooling/tools/utils.py +8 -14
  40. prediction_market_agent_tooling/tools/web3_utils.py +41 -24
  41. {prediction_market_agent_tooling-0.61.1.dev463.dist-info → prediction_market_agent_tooling-0.61.1.dev482.dist-info}/METADATA +1 -2
  42. {prediction_market_agent_tooling-0.61.1.dev463.dist-info → prediction_market_agent_tooling-0.61.1.dev482.dist-info}/RECORD +45 -48
  43. prediction_market_agent_tooling/tools/_generic_value.py +0 -255
  44. prediction_market_agent_tooling/tools/tokens/token_utils.py +0 -46
  45. prediction_market_agent_tooling/tools/tokens/usd.py +0 -63
  46. {prediction_market_agent_tooling-0.61.1.dev463.dist-info → prediction_market_agent_tooling-0.61.1.dev482.dist-info}/LICENSE +0 -0
  47. {prediction_market_agent_tooling-0.61.1.dev463.dist-info → prediction_market_agent_tooling-0.61.1.dev482.dist-info}/WHEEL +0 -0
  48. {prediction_market_agent_tooling-0.61.1.dev463.dist-info → prediction_market_agent_tooling-0.61.1.dev482.dist-info}/entry_points.txt +0 -0
@@ -40,8 +40,8 @@ from prediction_market_agent_tooling.markets.agent_market import (
40
40
  SortBy,
41
41
  )
42
42
  from prediction_market_agent_tooling.markets.data_models import (
43
- ExistingPosition,
44
43
  PlacedTrade,
44
+ Position,
45
45
  ProbabilisticAnswer,
46
46
  Trade,
47
47
  )
@@ -582,9 +582,9 @@ class DeployableTraderAgent(DeployablePredictionAgent):
582
582
  """
583
583
  user_id = market.get_user_id(api_keys=APIKeys())
584
584
 
585
- total_amount = market.get_in_usd(market.get_tiny_bet_amount())
585
+ total_amount = market.get_tiny_bet_amount().amount
586
586
  if existing_position := market.get_position(user_id=user_id):
587
- total_amount += existing_position.total_amount_current
587
+ total_amount += existing_position.total_amount.amount
588
588
 
589
589
  return MaxAccuracyBettingStrategy(bet_amount=total_amount)
590
590
 
@@ -592,10 +592,11 @@ class DeployableTraderAgent(DeployablePredictionAgent):
592
592
  self,
593
593
  market: AgentMarket,
594
594
  answer: ProbabilisticAnswer,
595
- existing_position: ExistingPosition | None,
595
+ existing_position: Position | None,
596
596
  ) -> list[Trade]:
597
597
  strategy = self.get_betting_strategy(market=market)
598
598
  trades = strategy.calculate_trades(existing_position, answer, market)
599
+ BettingStrategy.assert_trades_currency_match_markets(market, trades)
599
600
  return trades
600
601
 
601
602
  def before_process_market(
@@ -2,13 +2,14 @@ from abc import ABC, abstractmethod
2
2
 
3
3
  from scipy.optimize import minimize_scalar
4
4
 
5
- from prediction_market_agent_tooling.gtypes import USD, OutcomeToken, Token
5
+ from prediction_market_agent_tooling.gtypes import xDai
6
6
  from prediction_market_agent_tooling.loggers import logger
7
7
  from prediction_market_agent_tooling.markets.agent_market import AgentMarket, MarketFees
8
8
  from prediction_market_agent_tooling.markets.data_models import (
9
- ExistingPosition,
9
+ Currency,
10
10
  Position,
11
11
  ProbabilisticAnswer,
12
+ TokenAmount,
12
13
  Trade,
13
14
  TradeType,
14
15
  )
@@ -30,7 +31,7 @@ class BettingStrategy(ABC):
30
31
  @abstractmethod
31
32
  def calculate_trades(
32
33
  self,
33
- existing_position: ExistingPosition | None,
34
+ existing_position: Position | None,
34
35
  answer: ProbabilisticAnswer,
35
36
  market: AgentMarket,
36
37
  ) -> list[Trade]:
@@ -38,11 +39,21 @@ class BettingStrategy(ABC):
38
39
 
39
40
  @property
40
41
  @abstractmethod
41
- def maximum_possible_bet_amount(self) -> USD:
42
+ def maximum_possible_bet_amount(self) -> float:
42
43
  raise NotImplementedError("Subclass should implement this.")
43
44
 
44
- def build_zero_usd_amount(self) -> USD:
45
- return USD(0)
45
+ def build_zero_token_amount(self, currency: Currency) -> TokenAmount:
46
+ return TokenAmount(amount=0, currency=currency)
47
+
48
+ @staticmethod
49
+ def assert_trades_currency_match_markets(
50
+ market: AgentMarket, trades: list[Trade]
51
+ ) -> None:
52
+ currencies_match = all([t.amount.currency == market.currency for t in trades])
53
+ if not currencies_match:
54
+ raise ValueError(
55
+ "Cannot handle trades with currencies that deviate from market's currency"
56
+ )
46
57
 
47
58
  @staticmethod
48
59
  def assert_buy_trade_wont_be_guaranteed_loss(
@@ -53,21 +64,20 @@ class BettingStrategy(ABC):
53
64
  outcome_tokens_to_get = market.get_buy_token_amount(
54
65
  trade.amount, trade.outcome
55
66
  )
56
- outcome_tokens_to_get_in_usd = market.get_token_in_usd(
57
- outcome_tokens_to_get.as_token
58
- )
59
- if outcome_tokens_to_get_in_usd <= trade.amount:
67
+
68
+ if outcome_tokens_to_get.amount < trade.amount.amount:
60
69
  raise GuaranteedLossError(
61
70
  f"Trade {trade=} would result in guaranteed loss by getting only {outcome_tokens_to_get=}."
62
71
  )
63
72
 
64
73
  @staticmethod
65
74
  def check_trades(market: AgentMarket, trades: list[Trade]) -> None:
75
+ BettingStrategy.assert_trades_currency_match_markets(market, trades)
66
76
  BettingStrategy.assert_buy_trade_wont_be_guaranteed_loss(market, trades)
67
77
 
68
78
  def _build_rebalance_trades_from_positions(
69
79
  self,
70
- existing_position: ExistingPosition | None,
80
+ existing_position: Position | None,
71
81
  target_position: Position,
72
82
  market: AgentMarket,
73
83
  ) -> list[Trade]:
@@ -85,20 +95,23 @@ class BettingStrategy(ABC):
85
95
  trades = []
86
96
  for outcome_bool in [True, False]:
87
97
  outcome = market.get_outcome_str_from_bool(outcome_bool)
88
- prev_amount = (
89
- existing_position.amounts_current[outcome]
90
- if existing_position and outcome in existing_position.amounts_current
91
- else self.build_zero_usd_amount()
98
+ prev_amount: TokenAmount = (
99
+ existing_position.amounts[outcome]
100
+ if existing_position and outcome in existing_position.amounts
101
+ else self.build_zero_token_amount(currency=market.currency)
92
102
  )
93
- new_amount = target_position.amounts_current.get(
94
- outcome, self.build_zero_usd_amount()
103
+ new_amount: TokenAmount = target_position.amounts.get(
104
+ outcome, self.build_zero_token_amount(currency=market.currency)
95
105
  )
96
- diff_amount = new_amount - prev_amount
106
+
107
+ if prev_amount.currency != new_amount.currency:
108
+ raise ValueError("Cannot handle positions with different currencies")
109
+ diff_amount = new_amount.amount - prev_amount.amount
97
110
  if diff_amount == 0:
98
111
  continue
99
112
  trade_type = TradeType.SELL if diff_amount < 0 else TradeType.BUY
100
113
  trade = Trade(
101
- amount=abs(diff_amount),
114
+ amount=TokenAmount(amount=abs(diff_amount), currency=market.currency),
102
115
  outcome=outcome_bool,
103
116
  trade_type=trade_type,
104
117
  )
@@ -115,25 +128,28 @@ class BettingStrategy(ABC):
115
128
 
116
129
 
117
130
  class MaxAccuracyBettingStrategy(BettingStrategy):
118
- def __init__(self, bet_amount: USD):
131
+ def __init__(self, bet_amount: float):
119
132
  self.bet_amount = bet_amount
120
133
 
121
134
  @property
122
- def maximum_possible_bet_amount(self) -> USD:
135
+ def maximum_possible_bet_amount(self) -> float:
123
136
  return self.bet_amount
124
137
 
125
138
  def calculate_trades(
126
139
  self,
127
- existing_position: ExistingPosition | None,
140
+ existing_position: Position | None,
128
141
  answer: ProbabilisticAnswer,
129
142
  market: AgentMarket,
130
143
  ) -> list[Trade]:
131
144
  direction = self.calculate_direction(market.current_p_yes, answer.p_yes)
132
145
 
133
146
  amounts = {
134
- market.get_outcome_str_from_bool(direction): self.bet_amount,
147
+ market.get_outcome_str_from_bool(direction): TokenAmount(
148
+ amount=self.bet_amount,
149
+ currency=market.currency,
150
+ ),
135
151
  }
136
- target_position = Position(market_id=market.id, amounts_current=amounts)
152
+ target_position = Position(market_id=market.id, amounts=amounts)
137
153
  trades = self._build_rebalance_trades_from_positions(
138
154
  existing_position, target_position, market=market
139
155
  )
@@ -157,17 +173,17 @@ class MaxExpectedValueBettingStrategy(MaxAccuracyBettingStrategy):
157
173
 
158
174
 
159
175
  class KellyBettingStrategy(BettingStrategy):
160
- def __init__(self, max_bet_amount: USD, max_price_impact: float | None = None):
176
+ def __init__(self, max_bet_amount: float, max_price_impact: float | None = None):
161
177
  self.max_bet_amount = max_bet_amount
162
178
  self.max_price_impact = max_price_impact
163
179
 
164
180
  @property
165
- def maximum_possible_bet_amount(self) -> USD:
181
+ def maximum_possible_bet_amount(self) -> float:
166
182
  return self.max_bet_amount
167
183
 
168
184
  def calculate_trades(
169
185
  self,
170
- existing_position: ExistingPosition | None,
186
+ existing_position: Position | None,
171
187
  answer: ProbabilisticAnswer,
172
188
  market: AgentMarket,
173
189
  ) -> list[Trade]:
@@ -180,7 +196,7 @@ class KellyBettingStrategy(BettingStrategy):
180
196
  market.get_outcome_str_from_bool(False)
181
197
  ],
182
198
  estimated_p_yes=answer.p_yes,
183
- max_bet=market.get_usd_in_token(self.max_bet_amount),
199
+ max_bet=self.max_bet_amount,
184
200
  confidence=answer.confidence,
185
201
  fees=market.fees,
186
202
  )
@@ -196,11 +212,11 @@ class KellyBettingStrategy(BettingStrategy):
196
212
  kelly_bet_size = min(kelly_bet.size, max_price_impact_bet_amount)
197
213
 
198
214
  amounts = {
199
- market.get_outcome_str_from_bool(
200
- kelly_bet.direction
201
- ): market.get_token_in_usd(kelly_bet_size),
215
+ market.get_outcome_str_from_bool(kelly_bet.direction): TokenAmount(
216
+ amount=kelly_bet_size, currency=market.currency
217
+ ),
202
218
  }
203
- target_position = Position(market_id=market.id, amounts_current=amounts)
219
+ target_position = Position(market_id=market.id, amounts=amounts)
204
220
  trades = self._build_rebalance_trades_from_positions(
205
221
  existing_position, target_position, market=market
206
222
  )
@@ -209,9 +225,9 @@ class KellyBettingStrategy(BettingStrategy):
209
225
  def calculate_price_impact_for_bet_amount(
210
226
  self,
211
227
  buy_direction: bool,
212
- bet_amount: Token,
213
- yes: OutcomeToken,
214
- no: OutcomeToken,
228
+ bet_amount: float,
229
+ yes: float,
230
+ no: float,
215
231
  fees: MarketFees,
216
232
  ) -> float:
217
233
  total_outcome_tokens = yes + no
@@ -223,7 +239,7 @@ class KellyBettingStrategy(BettingStrategy):
223
239
  bet_amount, buy_direction, yes, no, fees
224
240
  )
225
241
 
226
- actual_price = bet_amount.value / tokens_to_buy.value
242
+ actual_price = bet_amount / tokens_to_buy
227
243
  # price_impact should always be > 0
228
244
  price_impact = (actual_price - expected_price) / expected_price
229
245
  return price_impact
@@ -232,13 +248,13 @@ class KellyBettingStrategy(BettingStrategy):
232
248
  self,
233
249
  market: AgentMarket,
234
250
  kelly_bet: SimpleBet,
235
- ) -> Token:
251
+ ) -> float:
236
252
  def calculate_price_impact_deviation_from_target_price_impact(
237
- bet_amount_usd: float, # Needs to be float because it's used in minimize_scalar internally.
253
+ bet_amount: xDai,
238
254
  ) -> float:
239
255
  price_impact = self.calculate_price_impact_for_bet_amount(
240
256
  kelly_bet.direction,
241
- market.get_usd_in_token(USD(bet_amount_usd)),
257
+ bet_amount,
242
258
  yes_outcome_pool_size,
243
259
  no_outcome_pool_size,
244
260
  market.fees,
@@ -264,41 +280,40 @@ class KellyBettingStrategy(BettingStrategy):
264
280
  # The bounds below have been found to work heuristically.
265
281
  optimized_bet_amount = minimize_scalar(
266
282
  calculate_price_impact_deviation_from_target_price_impact,
267
- bounds=(0, 1000 * (yes_outcome_pool_size + no_outcome_pool_size).value),
283
+ bounds=(0, 1000 * (yes_outcome_pool_size + no_outcome_pool_size)),
268
284
  method="bounded",
269
285
  tol=1e-11,
270
286
  options={"maxiter": 10000},
271
287
  )
272
- return Token(optimized_bet_amount.x)
288
+ return float(optimized_bet_amount.x)
273
289
 
274
290
  def __repr__(self) -> str:
275
291
  return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount}, max_price_impact={self.max_price_impact})"
276
292
 
277
293
 
278
294
  class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
279
- def __init__(self, max_bet_amount: USD):
295
+ def __init__(self, max_bet_amount: float = 10):
280
296
  self.max_bet_amount = max_bet_amount
281
297
 
282
298
  @property
283
- def maximum_possible_bet_amount(self) -> USD:
299
+ def maximum_possible_bet_amount(self) -> float:
284
300
  return self.max_bet_amount
285
301
 
286
302
  def adjust_bet_amount(
287
- self, existing_position: ExistingPosition | None, market: AgentMarket
288
- ) -> USD:
303
+ self, existing_position: Position | None, market: AgentMarket
304
+ ) -> float:
289
305
  existing_position_total_amount = (
290
- existing_position.total_amount_current if existing_position else USD(0)
306
+ existing_position.total_amount.amount if existing_position else 0
291
307
  )
292
308
  return self.max_bet_amount + existing_position_total_amount
293
309
 
294
310
  def calculate_trades(
295
311
  self,
296
- existing_position: ExistingPosition | None,
312
+ existing_position: Position | None,
297
313
  answer: ProbabilisticAnswer,
298
314
  market: AgentMarket,
299
315
  ) -> list[Trade]:
300
- adjusted_bet_amount_usd = self.adjust_bet_amount(existing_position, market)
301
- adjusted_bet_amount_token = market.get_usd_in_token(adjusted_bet_amount_usd)
316
+ adjusted_bet_amount = self.adjust_bet_amount(existing_position, market)
302
317
  outcome_token_pool = check_not_none(market.outcome_token_pool)
303
318
 
304
319
  # Fixed direction of bet, only use Kelly to adjust the bet size based on market's outcome pool size.
@@ -313,16 +328,17 @@ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
313
328
  market.get_outcome_str_from_bool(False)
314
329
  ],
315
330
  estimated_p_yes=estimated_p_yes,
316
- max_bet=adjusted_bet_amount_token,
331
+ max_bet=adjusted_bet_amount,
317
332
  confidence=confidence,
318
333
  fees=market.fees,
319
334
  )
320
- kelly_bet_size_usd = market.get_token_in_usd(kelly_bet.size)
321
335
 
322
336
  amounts = {
323
- market.get_outcome_str_from_bool(kelly_bet.direction): kelly_bet_size_usd,
337
+ market.get_outcome_str_from_bool(kelly_bet.direction): TokenAmount(
338
+ amount=kelly_bet.size, currency=market.currency
339
+ ),
324
340
  }
325
- target_position = Position(market_id=market.id, amounts_current=amounts)
341
+ target_position = Position(market_id=market.id, amounts=amounts)
326
342
  trades = self._build_rebalance_trades_from_positions(
327
343
  existing_position, target_position, market=market
328
344
  )
@@ -1,6 +1,5 @@
1
1
  import typing as t
2
- from decimal import Decimal
3
- from typing import NewType
2
+ from typing import NewType, Union
4
3
 
5
4
  from eth_typing.evm import ( # noqa: F401 # Import for the sake of easy importing with others from here.
6
5
  Address,
@@ -10,15 +9,13 @@ from eth_typing.evm import ( # noqa: F401 # Import for the sake of easy import
10
9
  )
11
10
  from pydantic.types import SecretStr
12
11
  from pydantic.v1.types import SecretStr as SecretStrV1
13
- from web3 import Web3
14
12
  from web3.types import ( # noqa: F401 # Import for the sake of easy importing with others from here.
15
13
  Nonce,
16
14
  TxParams,
17
15
  TxReceipt,
16
+ Wei,
18
17
  )
19
- from web3.types import Wei as Web3Wei
20
18
 
21
- from prediction_market_agent_tooling.tools._generic_value import _GenericValue
22
19
  from prediction_market_agent_tooling.tools.datetime_utc import ( # noqa: F401 # Import for the sake of easy importing with others from here.
23
20
  DatetimeUTC,
24
21
  )
@@ -26,118 +23,43 @@ from prediction_market_agent_tooling.tools.hexbytes_custom import ( # noqa: F40
26
23
  HexBytes,
27
24
  )
28
25
 
26
+ Wad = Wei # Wei tends to be referred to as `wad` variable in contracts.
27
+ USD = NewType("USD", float)
28
+ PrivateKey = NewType("PrivateKey", SecretStr)
29
+ xDai = NewType("xDai", float)
30
+ GNO = NewType("GNO", float)
31
+ ABI = NewType("ABI", str)
32
+ OmenOutcomeToken = NewType("OmenOutcomeToken", Wei)
33
+ OutcomeStr = NewType("OutcomeStr", str)
34
+ Probability = NewType("Probability", float)
35
+ Mana = NewType("Mana", float) # Manifold's "currency"
36
+ USDC = NewType("USDC", float)
37
+ ChainID = NewType("ChainID", int)
38
+ IPFSCIDVersion0 = NewType("IPFSCIDVersion0", str)
29
39
 
30
- class Token(_GenericValue[int | float | str | Decimal, float], parser=float):
31
- """
32
- Represents any token in its decimal form, it could be 1.1 GNO, WXDAI, XDAI, Mana, whatever. We don't know the currency, just that it's in the decimal form.
33
- """
34
-
35
- @property
36
- def as_wei(self) -> "Wei":
37
- return Wei(Web3.to_wei(self.value, "ether"))
38
-
39
-
40
- class OutcomeToken(_GenericValue[int | float | str | Decimal, float], parser=float):
41
- """
42
- Represents outcome tokens in market in decimal form.
43
- After you redeem the outcome tokens, 1 OutcomeToken equals to 1 Token, but before, it's important to distinguish between them.
44
- For example, it's a big difference if you are going to sell 1 OutcomeToken, or 1 (collateral) Token.
45
- But still, Token and OutcomeToken needs to be handled together in many cases, use available properties to convert between them explicitly.
46
- """
47
-
48
- @staticmethod
49
- def from_token(token: Token) -> "OutcomeToken":
50
- return OutcomeToken(token.value)
51
-
52
- @property
53
- def as_outcome_wei(self) -> "OutcomeWei":
54
- return OutcomeWei(Web3.to_wei(self.value, "ether"))
55
-
56
- @property
57
- def as_token(self) -> Token:
58
- """
59
- OutcomeToken is essentialy Token as well, when you know you really need to convert it, you can convert it explicitly using this.
60
- """
61
- return Token(self.value)
62
-
63
-
64
- class USD(_GenericValue[int | float | str | Decimal, float], parser=float):
65
- """Represents values in USD."""
66
-
67
-
68
- class xDai(_GenericValue[int | float | str | Decimal, float], parser=float):
69
- """Represents values in xDai."""
70
-
71
- @property
72
- def as_token(self) -> Token:
73
- """
74
- xDai is essentialy Token as well, when you know you need to pass it, you can convert it using this.
75
- """
76
- return Token(self.value)
77
-
78
- @property
79
- def as_xdai_wei(self) -> "xDaiWei":
80
- return xDaiWei(Web3.to_wei(self.value, "ether"))
81
-
82
-
83
- class Mana(_GenericValue[int | float | str | Decimal, float], parser=float):
84
- """Represents values in Manifold's Mana."""
85
-
86
-
87
- class USDC(_GenericValue[int | float | str | Decimal, float], parser=float):
88
- """Represents values in USDC."""
89
-
90
-
91
- class Wei(_GenericValue[Web3Wei | int | str, Web3Wei], parser=int):
92
- """Represents values in Wei. We don't know what currency, but in its integer form called Wei."""
93
-
94
- @property
95
- def as_token(self) -> Token:
96
- return Token(Web3.from_wei(self.value, "ether"))
97
40
 
41
+ def usd_type(amount: Union[str, int, float]) -> USD:
42
+ return USD(float(amount))
98
43
 
99
- class OutcomeWei(_GenericValue[Web3Wei | int | str, Web3Wei], parser=int):
100
- """
101
- Similar to OutcomeToken, but in Wei units.
102
- """
103
44
 
104
- @staticmethod
105
- def from_wei(wei: Wei) -> "OutcomeWei":
106
- return OutcomeWei(wei.value)
45
+ def wei_type(amount: Union[str, int, float]) -> Wei:
46
+ return Wei(int(amount))
107
47
 
108
- @property
109
- def as_outcome_token(self) -> OutcomeToken:
110
- return OutcomeToken(Web3.from_wei(self.value, "ether"))
111
48
 
112
- @property
113
- def as_wei(self) -> Wei:
114
- """
115
- OutcomeWei is essentialy Wei as well, when you know you need to pass it, you can convert it using this.
116
- """
117
- return Wei(self.value)
49
+ def omen_outcome_type(amount: Union[str, int, Wei]) -> OmenOutcomeToken:
50
+ return OmenOutcomeToken(wei_type(amount))
118
51
 
119
52
 
120
- class xDaiWei(_GenericValue[Web3Wei | int | str, Web3Wei], parser=int):
121
- """Represents xDai in Wei, like 1.9 xDai is 1.9 * 10**18 Wei. In contrast to just `Wei`, we don't know what unit Wei is (Wei of GNO, sDai, or whatever), but xDaiWei is xDai converted to Wei."""
53
+ def xdai_type(amount: Union[str, int, float]) -> xDai:
54
+ return xDai(float(amount))
122
55
 
123
- @property
124
- def as_xdai(self) -> xDai:
125
- return xDai(Web3.from_wei(self.value, "ether"))
126
56
 
127
- @property
128
- def as_wei(self) -> Wei:
129
- """
130
- xDaiWei is essentialy Wei as well, when you know you need to pass it, you can convert it using this.
131
- """
132
- return Wei(self.value)
57
+ def mana_type(amount: Union[str, int, float]) -> Mana:
58
+ return Mana(float(amount))
133
59
 
134
60
 
135
- PrivateKey = NewType("PrivateKey", SecretStr)
136
- ABI = NewType("ABI", str)
137
- OutcomeStr = NewType("OutcomeStr", str)
138
- Probability = NewType("Probability", float)
139
- ChainID = NewType("ChainID", int)
140
- IPFSCIDVersion0 = NewType("IPFSCIDVersion0", str)
61
+ def usdc_type(amount: Union[str, int, float]) -> USDC:
62
+ return USDC(float(amount))
141
63
 
142
64
 
143
65
  def private_key_type(k: str) -> PrivateKey:
@@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
4
4
  from pydantic import BaseModel
5
5
 
6
6
  from prediction_market_agent_tooling.deploy.betting_strategy import ProbabilisticAnswer
7
- from prediction_market_agent_tooling.gtypes import USD, Probability
7
+ from prediction_market_agent_tooling.gtypes import Probability
8
8
  from prediction_market_agent_tooling.markets.agent_market import (
9
9
  AgentMarket,
10
10
  ProcessedTradedMarket,
@@ -19,7 +19,8 @@ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
19
19
  class SimpleJob(BaseModel):
20
20
  id: str
21
21
  job: str
22
- reward: USD
22
+ reward: float
23
+ currency: str
23
24
  deadline: DatetimeUTC
24
25
 
25
26
 
@@ -37,7 +38,7 @@ class JobAgentMarket(AgentMarket, ABC):
37
38
  """Deadline for the job completion."""
38
39
 
39
40
  @abstractmethod
40
- def get_reward(self, max_bond: USD) -> USD:
41
+ def get_reward(self, max_bond: float) -> float:
41
42
  """Reward for completing this job."""
42
43
 
43
44
  @classmethod
@@ -57,15 +58,16 @@ class JobAgentMarket(AgentMarket, ABC):
57
58
 
58
59
  @abstractmethod
59
60
  def submit_job_result(
60
- self, agent_name: str, max_bond: USD, result: str
61
+ self, agent_name: str, max_bond: float, result: str
61
62
  ) -> ProcessedTradedMarket:
62
63
  """Submit the completed result for this job."""
63
64
 
64
- def to_simple_job(self, max_bond: USD) -> SimpleJob:
65
+ def to_simple_job(self, max_bond: float) -> SimpleJob:
65
66
  return SimpleJob(
66
67
  id=self.id,
67
68
  job=self.job,
68
69
  reward=self.get_reward(max_bond),
70
+ currency=self.currency.value,
69
71
  deadline=self.deadline,
70
72
  )
71
73
 
@@ -2,14 +2,15 @@ import typing as t
2
2
 
3
3
  from prediction_market_agent_tooling.config import APIKeys
4
4
  from prediction_market_agent_tooling.deploy.betting_strategy import (
5
+ Currency,
5
6
  KellyBettingStrategy,
6
7
  TradeType,
7
8
  )
8
- from prediction_market_agent_tooling.gtypes import USD
9
9
  from prediction_market_agent_tooling.jobs.jobs_models import JobAgentMarket
10
10
  from prediction_market_agent_tooling.markets.agent_market import ProcessedTradedMarket
11
11
  from prediction_market_agent_tooling.markets.data_models import PlacedTrade, Trade
12
12
  from prediction_market_agent_tooling.markets.omen.omen import (
13
+ BetAmount,
13
14
  OmenAgentMarket,
14
15
  OmenMarket,
15
16
  )
@@ -33,21 +34,21 @@ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
33
34
  def deadline(self) -> DatetimeUTC:
34
35
  return self.close_time
35
36
 
36
- def get_reward(self, max_bond: USD) -> USD:
37
+ def get_reward(self, max_bond: float) -> float:
37
38
  trade = self.get_job_trade(
38
39
  max_bond,
39
40
  result="", # Pass empty result, as we are computing only potential reward at this point.
40
41
  )
41
- reward_usd = (
42
- self.get_token_in_usd(
43
- self.get_buy_token_amount(
44
- bet_amount=trade.amount,
45
- direction=trade.outcome,
46
- ).as_token
47
- )
48
- - trade.amount
42
+ reward = (
43
+ self.get_buy_token_amount(
44
+ bet_amount=BetAmount(
45
+ amount=trade.amount.amount, currency=trade.amount.currency
46
+ ),
47
+ direction=trade.outcome,
48
+ ).amount
49
+ - trade.amount.amount
49
50
  )
50
- return reward_usd
51
+ return reward
51
52
 
52
53
  @classmethod
53
54
  def get_jobs(
@@ -71,7 +72,7 @@ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
71
72
  )
72
73
 
73
74
  def submit_job_result(
74
- self, agent_name: str, max_bond: USD, result: str
75
+ self, agent_name: str, max_bond: float, result: str
75
76
  ) -> ProcessedTradedMarket:
76
77
  if not APIKeys().enable_ipfs_upload:
77
78
  raise RuntimeError(
@@ -91,7 +92,7 @@ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
91
92
 
92
93
  return processed_traded_market
93
94
 
94
- def get_job_trade(self, max_bond: USD, result: str) -> Trade:
95
+ def get_job_trade(self, max_bond: float, result: str) -> Trade:
95
96
  # Because jobs are powered by prediction markets, potentional reward depends on job's liquidity and our will to bond (bet) our xDai into our job completion.
96
97
  strategy = KellyBettingStrategy(max_bet_amount=max_bond)
97
98
  required_trades = strategy.calculate_trades(
@@ -105,6 +106,9 @@ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
105
106
  trade = required_trades[0]
106
107
  assert trade.trade_type == TradeType.BUY, "Should only buy on job markets."
107
108
  assert trade.outcome, "Should buy only YES on job markets."
109
+ assert (
110
+ trade.amount.currency == Currency.xDai
111
+ ), "Should work only on real-money markets."
108
112
  return required_trades[0]
109
113
 
110
114
  @staticmethod