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.
- prediction_market_agent_tooling/config.py +3 -0
- prediction_market_agent_tooling/deploy/agent.py +4 -5
- prediction_market_agent_tooling/deploy/betting_strategy.py +53 -69
- prediction_market_agent_tooling/gtypes.py +105 -27
- prediction_market_agent_tooling/jobs/jobs_models.py +5 -7
- prediction_market_agent_tooling/jobs/omen/omen_jobs.py +13 -17
- prediction_market_agent_tooling/markets/agent_market.py +96 -52
- prediction_market_agent_tooling/markets/blockchain_utils.py +1 -27
- prediction_market_agent_tooling/markets/data_models.py +40 -44
- prediction_market_agent_tooling/markets/manifold/api.py +2 -6
- prediction_market_agent_tooling/markets/manifold/data_models.py +33 -25
- prediction_market_agent_tooling/markets/manifold/manifold.py +8 -11
- prediction_market_agent_tooling/markets/market_fees.py +4 -2
- prediction_market_agent_tooling/markets/omen/data_models.py +66 -57
- prediction_market_agent_tooling/markets/omen/omen.py +214 -249
- prediction_market_agent_tooling/markets/omen/omen_contracts.py +31 -29
- prediction_market_agent_tooling/markets/omen/omen_resolving.py +7 -14
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +20 -14
- 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 +3 -5
- prediction_market_agent_tooling/markets/seer/data_models.py +8 -8
- prediction_market_agent_tooling/markets/seer/seer.py +85 -71
- prediction_market_agent_tooling/markets/seer/seer_contracts.py +10 -5
- prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +5 -2
- prediction_market_agent_tooling/monitor/monitor.py +2 -2
- prediction_market_agent_tooling/tools/_generic_value.py +246 -0
- prediction_market_agent_tooling/tools/balances.py +9 -11
- prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +12 -10
- prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +27 -24
- prediction_market_agent_tooling/tools/betting_strategies/utils.py +3 -1
- prediction_market_agent_tooling/tools/contract.py +14 -10
- prediction_market_agent_tooling/tools/cow/cow_manager.py +3 -4
- prediction_market_agent_tooling/tools/cow/cow_order.py +3 -4
- prediction_market_agent_tooling/tools/langfuse_client_utils.py +13 -1
- prediction_market_agent_tooling/tools/omen/sell_positions.py +6 -3
- prediction_market_agent_tooling/tools/safe.py +5 -6
- prediction_market_agent_tooling/tools/tokens/auto_deposit.py +32 -30
- prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +5 -22
- prediction_market_agent_tooling/tools/tokens/main_token.py +2 -2
- prediction_market_agent_tooling/tools/tokens/token_utils.py +46 -0
- prediction_market_agent_tooling/tools/tokens/usd.py +63 -0
- prediction_market_agent_tooling/tools/utils.py +14 -8
- prediction_market_agent_tooling/tools/web3_utils.py +24 -41
- {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/METADATA +2 -1
- {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/RECORD +49 -46
- {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.61.0.dist-info → prediction_market_agent_tooling-0.61.1.dev461.dist-info}/WHEEL +0 -0
- {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
|
-
|
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 =
|
98
|
-
OMEN_TINY_BET_AMOUNT =
|
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
|
156
|
-
return
|
148
|
+
def get_liquidity(self, web3: Web3 | None = None) -> Token:
|
149
|
+
return self.get_liquidity_in_wei(web3).as_token
|
157
150
|
|
158
|
-
def
|
159
|
-
return
|
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
|
-
|
165
|
-
|
166
|
-
|
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:
|
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.
|
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:
|
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=
|
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:
|
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
|
241
|
-
self,
|
242
|
-
) ->
|
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
|
248
|
-
other_str = self.outcomes[self.no_index if
|
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
|
252
|
-
holdings=
|
253
|
-
other_holdings=
|
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
|
-
|
251
|
+
|
252
|
+
return collateral
|
257
253
|
|
258
254
|
def sell_tokens(
|
259
255
|
self,
|
260
256
|
outcome: bool,
|
261
|
-
amount:
|
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=
|
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=
|
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=
|
352
|
+
volume=model.collateralVolume.as_token,
|
365
353
|
close_time=model.close_time,
|
366
354
|
fees=MarketFees(
|
367
355
|
bet_proportion=(
|
368
|
-
|
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]:
|
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) ->
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
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
|
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
|
-
|
425
|
-
) >
|
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
|
-
) ->
|
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
|
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) ->
|
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
|
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:
|
528
|
-
) ->
|
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=
|
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
|
-
|
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
|
561
|
+
if outecome_str in amounts_ot:
|
574
562
|
raise ValueError(
|
575
|
-
f"Outcome {outecome_str} already exists in {
|
563
|
+
f"Outcome {outecome_str} already exists in {amounts_ot=}"
|
576
564
|
)
|
577
565
|
|
578
|
-
|
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
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
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
|
-
|
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:
|
654
|
-
) ->
|
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
|
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
|
610
|
+
return amount
|
668
611
|
|
669
612
|
def _get_buy_token_amount_from_smart_contract(
|
670
|
-
self, bet_amount:
|
671
|
-
) ->
|
672
|
-
|
673
|
-
self.
|
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
|
-
|
681
|
-
|
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:
|
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
|
-
|
692
|
-
|
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.
|
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.
|
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).
|
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,
|
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,
|
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:
|
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
|
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
|
-
|
771
|
-
|
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
|
-
|
733
|
+
amount_wei, outcome_index, web3=web3
|
779
734
|
)
|
780
735
|
# Allow small slippage.
|
781
|
-
expected_shares =
|
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=
|
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=
|
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:
|
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:
|
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
|
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
|
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 =
|
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:
|
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:
|
873
|
+
initial_funds: USD | Token,
|
915
874
|
question: str,
|
916
875
|
closing_time: DatetimeUTC,
|
917
876
|
category: str,
|
918
877
|
language: str,
|
919
|
-
outcomes:
|
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[
|
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
|
-
|
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
|
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=
|
962
|
+
amount_wei=initial_funds_in_collateral_wei,
|
1004
963
|
web3=web3,
|
1005
964
|
)
|
1006
965
|
|
1007
966
|
# Create the market.
|
1008
|
-
fee =
|
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=
|
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=
|
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:
|
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=
|
1015
|
+
amount_wei=funds_in_collateral_wei,
|
1057
1016
|
web3=web3,
|
1058
1017
|
)
|
1059
1018
|
|
1060
1019
|
if auto_deposit:
|
1061
|
-
|
1062
|
-
|
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,
|
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 =
|
1075
|
+
balance_diff = new_balance - original_balance
|
1116
1076
|
|
1117
1077
|
logger.info(
|
1118
|
-
f"Redeemed {
|
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,
|
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,
|
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] =
|
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 =
|
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 {
|
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=
|
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 =
|
1235
|
+
balance_diff = new_balance - original_balance
|
1276
1236
|
|
1277
1237
|
logger.info(
|
1278
|
-
f"Redeemed {
|
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 =
|
1350
|
-
|
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:
|
1353
|
+
investment_amount: Token,
|
1396
1354
|
buy_direction: bool,
|
1397
|
-
yes_outcome_pool_size:
|
1398
|
-
no_outcome_pool_size:
|
1355
|
+
yes_outcome_pool_size: OutcomeToken,
|
1356
|
+
no_outcome_pool_size: OutcomeToken,
|
1399
1357
|
fees: MarketFees,
|
1400
|
-
) ->
|
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.
|
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 +
|
1413
|
-
ending_outcome_balance =
|
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
|
1382
|
+
buy_token_pool_balance
|
1383
|
+
+ investment_amount_minus_fees_as_ot
|
1384
|
+
- ending_outcome_balance
|
1420
1385
|
)
|
1421
1386
|
return result
|