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