prediction-market-agent-tooling 0.61.2.dev479__py3-none-any.whl → 0.62.0__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 +2 -3
- 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 -53
- 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 +13 -11
- prediction_market_agent_tooling/markets/market_fees.py +6 -2
- prediction_market_agent_tooling/markets/omen/data_models.py +66 -57
- prediction_market_agent_tooling/markets/omen/omen.py +222 -250
- prediction_market_agent_tooling/markets/omen/omen_contracts.py +31 -53
- 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 +261 -0
- prediction_market_agent_tooling/tools/balances.py +14 -11
- prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +12 -10
- prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +31 -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 +51 -7
- 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 +36 -27
- prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +4 -25
- 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 +79 -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.2.dev479.dist-info → prediction_market_agent_tooling-0.62.0.dist-info}/METADATA +2 -1
- {prediction_market_agent_tooling-0.61.2.dev479.dist-info → prediction_market_agent_tooling-0.62.0.dist-info}/RECORD +49 -47
- prediction_market_agent_tooling/abis/gvp2_settlement.abi.json +0 -89
- {prediction_market_agent_tooling-0.61.2.dev479.dist-info → prediction_market_agent_tooling-0.62.0.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.61.2.dev479.dist-info → prediction_market_agent_tooling-0.62.0.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.61.2.dev479.dist-info → prediction_market_agent_tooling-0.62.0.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
|
+
CollateralToken,
|
11
12
|
HexAddress,
|
12
13
|
HexStr,
|
13
|
-
OmenOutcomeToken,
|
14
14
|
OutcomeStr,
|
15
|
+
OutcomeToken,
|
16
|
+
OutcomeWei,
|
15
17
|
Probability,
|
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) -> CollateralToken:
|
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) -> CollateralToken:
|
152
|
+
return self.get_in_token(OMEN_TINY_BET_AMOUNT)
|
163
153
|
|
164
|
-
|
165
|
-
|
166
|
-
|
154
|
+
def get_token_in_usd(self, x: CollateralToken) -> USD:
|
155
|
+
return get_token_in_usd(x, self.collateral_token_contract_address_checksummed)
|
156
|
+
|
157
|
+
def get_usd_in_token(self, x: USD) -> CollateralToken:
|
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
|
+
) -> CollateralToken:
|
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
|
-
wei_to_xdai(
|
414
|
-
KEEPING_ERC20_TOKEN.balanceOf(api_keys.bet_from_address, web3=web3)
|
415
|
-
)
|
416
|
-
+ native_token_balance
|
398
|
+
def get_trade_balance(api_keys: APIKeys, web3: Web3 | None = None) -> USD:
|
399
|
+
native_usd = get_xdai_in_usd(
|
400
|
+
get_balances(api_keys.bet_from_address, web3=web3).xdai
|
417
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,
|
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 | CollateralToken, 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 | CollateralToken,
|
756
713
|
market: OmenAgentMarket,
|
757
714
|
outcome: str,
|
758
715
|
auto_deposit: bool,
|
@@ -760,35 +717,36 @@ 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
|
727
|
+
|
728
|
+
logger.info(
|
729
|
+
f"Buying asked {amount.value=} {amount.symbol}, converted to {amount_token.value=} {amount_token.symbol} for {outcome=} in market {market.url=}."
|
730
|
+
)
|
772
731
|
|
773
732
|
# Get the index of the outcome we want to buy.
|
774
733
|
outcome_index: int = market.get_outcome_index(outcome)
|
775
734
|
|
776
735
|
# Calculate the amount of shares we will get for the given investment amount.
|
777
736
|
expected_shares = market_contract.calcBuyAmount(
|
778
|
-
|
737
|
+
amount_wei, outcome_index, web3=web3
|
779
738
|
)
|
780
739
|
# Allow small slippage.
|
781
|
-
expected_shares =
|
740
|
+
expected_shares = expected_shares.without_fraction(slippage)
|
782
741
|
# Approve the market maker to withdraw our collateral token.
|
783
742
|
collateral_token_contract.approve(
|
784
743
|
api_keys=api_keys,
|
785
744
|
for_address=market_contract.address,
|
786
|
-
amount_wei=
|
745
|
+
amount_wei=amount_wei,
|
787
746
|
web3=web3,
|
788
747
|
)
|
789
748
|
|
790
749
|
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
750
|
auto_deposit_collateral_token(
|
793
751
|
collateral_token_contract, amount_wei, api_keys, web3
|
794
752
|
)
|
@@ -796,7 +754,7 @@ def omen_buy_outcome_tx(
|
|
796
754
|
# Buy shares using the deposited xDai in the collateral token.
|
797
755
|
tx_receipt = market_contract.buy(
|
798
756
|
api_keys=api_keys,
|
799
|
-
amount_wei=
|
757
|
+
amount_wei=amount_wei,
|
800
758
|
outcome_index=outcome_index,
|
801
759
|
min_outcome_tokens_to_buy=expected_shares,
|
802
760
|
web3=web3,
|
@@ -807,7 +765,7 @@ def omen_buy_outcome_tx(
|
|
807
765
|
|
808
766
|
def binary_omen_buy_outcome_tx(
|
809
767
|
api_keys: APIKeys,
|
810
|
-
amount:
|
768
|
+
amount: USD | CollateralToken,
|
811
769
|
market: OmenAgentMarket,
|
812
770
|
binary_outcome: bool,
|
813
771
|
auto_deposit: bool,
|
@@ -825,12 +783,12 @@ def binary_omen_buy_outcome_tx(
|
|
825
783
|
|
826
784
|
def omen_sell_outcome_tx(
|
827
785
|
api_keys: APIKeys,
|
828
|
-
amount:
|
786
|
+
amount: OutcomeToken | CollateralToken | USD,
|
829
787
|
market: OmenAgentMarket,
|
830
788
|
outcome: str,
|
831
789
|
auto_withdraw: bool,
|
832
790
|
web3: Web3 | None = None,
|
833
|
-
slippage: float = 0.
|
791
|
+
slippage: float = 0.01,
|
834
792
|
) -> str:
|
835
793
|
"""
|
836
794
|
Sells the given xDai value of shares corresponding to the given outcome in
|
@@ -839,13 +797,21 @@ def omen_sell_outcome_tx(
|
|
839
797
|
The number of shares sold will depend on the share price at the time of the
|
840
798
|
transaction.
|
841
799
|
"""
|
842
|
-
amount_wei = xdai_to_wei(amount)
|
843
|
-
amount_wei = remove_fraction(amount_wei, slippage)
|
844
|
-
|
845
800
|
market_contract: OmenFixedProductMarketMakerContract = market.get_contract()
|
846
801
|
conditional_token_contract = OmenConditionalTokenContract()
|
847
802
|
collateral_token_contract = market_contract.get_collateral_token_contract(web3)
|
848
803
|
|
804
|
+
amount_token = (
|
805
|
+
market.get_sell_value_of_outcome_token(outcome, amount, web3)
|
806
|
+
if isinstance(amount, OutcomeToken)
|
807
|
+
else market.get_in_token(amount)
|
808
|
+
)
|
809
|
+
amount_wei = amount_token.as_wei
|
810
|
+
|
811
|
+
logger.info(
|
812
|
+
f"Selling asked {amount.value=} {amount.symbol}, converted to {amount_wei.as_token.value=} {amount_wei.as_token.symbol} for {outcome=} in market {market.url=}."
|
813
|
+
)
|
814
|
+
|
849
815
|
# Verify, that markets uses conditional tokens that we expect.
|
850
816
|
if (
|
851
817
|
market_contract.conditionalTokens(web3=web3)
|
@@ -855,15 +821,15 @@ def omen_sell_outcome_tx(
|
|
855
821
|
f"Market {market.id} uses conditional token that we didn't expect, {market_contract.conditionalTokens()} != {conditional_token_contract.address=}"
|
856
822
|
)
|
857
823
|
|
858
|
-
# Get the index of the outcome we want to
|
824
|
+
# Get the index of the outcome we want to sell.
|
859
825
|
outcome_index: int = market.get_outcome_index(outcome)
|
860
826
|
|
861
|
-
# Calculate the amount of shares we will sell for the given selling amount of
|
827
|
+
# Calculate the amount of shares we will sell for the given selling amount of collateral.
|
862
828
|
max_outcome_tokens_to_sell = market_contract.calcSellAmount(
|
863
829
|
amount_wei, outcome_index, web3=web3
|
864
830
|
)
|
865
831
|
# Allow small slippage.
|
866
|
-
max_outcome_tokens_to_sell =
|
832
|
+
max_outcome_tokens_to_sell = max_outcome_tokens_to_sell.with_fraction(slippage)
|
867
833
|
|
868
834
|
# Approve the market maker to move our (all) conditional tokens.
|
869
835
|
conditional_token_contract.setApprovalForAll(
|
@@ -893,7 +859,7 @@ def omen_sell_outcome_tx(
|
|
893
859
|
|
894
860
|
def binary_omen_sell_outcome_tx(
|
895
861
|
api_keys: APIKeys,
|
896
|
-
amount:
|
862
|
+
amount: OutcomeToken | CollateralToken | USD,
|
897
863
|
market: OmenAgentMarket,
|
898
864
|
binary_outcome: bool,
|
899
865
|
auto_withdraw: bool,
|
@@ -911,16 +877,16 @@ def binary_omen_sell_outcome_tx(
|
|
911
877
|
|
912
878
|
def omen_create_market_tx(
|
913
879
|
api_keys: APIKeys,
|
914
|
-
initial_funds:
|
880
|
+
initial_funds: USD | CollateralToken,
|
915
881
|
question: str,
|
916
882
|
closing_time: DatetimeUTC,
|
917
883
|
category: str,
|
918
884
|
language: str,
|
919
|
-
outcomes:
|
885
|
+
outcomes: t.Sequence[str],
|
920
886
|
auto_deposit: bool,
|
921
887
|
finalization_timeout: timedelta = REALITY_DEFAULT_FINALIZATION_TIMEOUT,
|
922
888
|
fee_perc: float = OMEN_DEFAULT_MARKET_FEE_PERC,
|
923
|
-
distribution_hint: list[
|
889
|
+
distribution_hint: list[OutcomeWei] | None = None,
|
924
890
|
collateral_token_address: ChecksumAddress = WrappedxDaiContract().address,
|
925
891
|
arbitrator: Arbitrator = Arbitrator.KLEROS_31_JURORS_WITH_APPEAL,
|
926
892
|
web3: Web3 | None = None,
|
@@ -931,7 +897,12 @@ def omen_create_market_tx(
|
|
931
897
|
web3 = (
|
932
898
|
web3 or OmenFixedProductMarketMakerFactoryContract.get_web3()
|
933
899
|
) # Default to Gnosis web3.
|
934
|
-
|
900
|
+
initial_funds_in_collateral = (
|
901
|
+
get_usd_in_token(initial_funds, collateral_token_address)
|
902
|
+
if isinstance(initial_funds, USD)
|
903
|
+
else initial_funds
|
904
|
+
)
|
905
|
+
initial_funds_in_collateral_wei = initial_funds_in_collateral.as_wei
|
935
906
|
|
936
907
|
realitio_contract = OmenRealitioContract()
|
937
908
|
conditional_token_contract = OmenConditionalTokenContract()
|
@@ -955,9 +926,9 @@ def omen_create_market_tx(
|
|
955
926
|
|
956
927
|
if auto_deposit:
|
957
928
|
auto_deposit_collateral_token(
|
958
|
-
collateral_token_contract
|
929
|
+
collateral_token_contract,
|
930
|
+
initial_funds_in_collateral_wei,
|
959
931
|
api_keys=api_keys,
|
960
|
-
amount_wei=initial_funds_wei,
|
961
932
|
web3=web3,
|
962
933
|
)
|
963
934
|
|
@@ -991,21 +962,16 @@ def omen_create_market_tx(
|
|
991
962
|
web3=web3,
|
992
963
|
)
|
993
964
|
|
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
965
|
# Approve the market maker to withdraw our collateral token.
|
1000
966
|
collateral_token_contract.approve(
|
1001
967
|
api_keys=api_keys,
|
1002
968
|
for_address=factory_contract.address,
|
1003
|
-
amount_wei=
|
969
|
+
amount_wei=initial_funds_in_collateral_wei,
|
1004
970
|
web3=web3,
|
1005
971
|
)
|
1006
972
|
|
1007
973
|
# Create the market.
|
1008
|
-
fee =
|
974
|
+
fee = CollateralToken(fee_perc).as_wei
|
1009
975
|
(
|
1010
976
|
market_event,
|
1011
977
|
funding_event,
|
@@ -1015,7 +981,7 @@ def omen_create_market_tx(
|
|
1015
981
|
condition_id=condition_id,
|
1016
982
|
fee=fee,
|
1017
983
|
distribution_hint=distribution_hint,
|
1018
|
-
initial_funds_wei=
|
984
|
+
initial_funds_wei=initial_funds_in_collateral_wei,
|
1019
985
|
collateral_token_address=collateral_token_contract.address,
|
1020
986
|
web3=web3,
|
1021
987
|
)
|
@@ -1032,7 +998,7 @@ def omen_create_market_tx(
|
|
1032
998
|
condition_id=condition_id,
|
1033
999
|
question_event=question_event,
|
1034
1000
|
condition_event=cond_event,
|
1035
|
-
initial_funds=
|
1001
|
+
initial_funds=initial_funds_in_collateral_wei,
|
1036
1002
|
fee=fee,
|
1037
1003
|
distribution_hint=distribution_hint,
|
1038
1004
|
)
|
@@ -1041,27 +1007,28 @@ def omen_create_market_tx(
|
|
1041
1007
|
def omen_fund_market_tx(
|
1042
1008
|
api_keys: APIKeys,
|
1043
1009
|
market: OmenAgentMarket,
|
1044
|
-
funds:
|
1010
|
+
funds: USD | CollateralToken,
|
1045
1011
|
auto_deposit: bool,
|
1046
1012
|
web3: Web3 | None = None,
|
1047
1013
|
) -> None:
|
1014
|
+
funds_in_collateral = market.get_in_token(funds)
|
1015
|
+
funds_in_collateral_wei = funds_in_collateral.as_wei
|
1048
1016
|
market_contract = market.get_contract()
|
1049
1017
|
collateral_token_contract = market_contract.get_collateral_token_contract(web3=web3)
|
1050
1018
|
|
1051
|
-
amount_to_fund = collateral_token_contract.get_in_shares(funds, web3)
|
1052
|
-
|
1053
1019
|
collateral_token_contract.approve(
|
1054
1020
|
api_keys=api_keys,
|
1055
1021
|
for_address=market_contract.address,
|
1056
|
-
amount_wei=
|
1022
|
+
amount_wei=funds_in_collateral_wei,
|
1057
1023
|
web3=web3,
|
1058
1024
|
)
|
1059
1025
|
|
1060
1026
|
if auto_deposit:
|
1061
|
-
|
1062
|
-
|
1027
|
+
auto_deposit_collateral_token(
|
1028
|
+
collateral_token_contract, funds_in_collateral_wei, api_keys, web3
|
1029
|
+
)
|
1063
1030
|
|
1064
|
-
market_contract.addFunding(api_keys,
|
1031
|
+
market_contract.addFunding(api_keys, funds_in_collateral_wei, web3=web3)
|
1065
1032
|
|
1066
1033
|
|
1067
1034
|
def omen_redeem_full_position_tx(
|
@@ -1094,7 +1061,7 @@ def omen_redeem_full_position_tx(
|
|
1094
1061
|
amount_per_index = get_conditional_tokens_balance_for_market(
|
1095
1062
|
market, from_address, web3
|
1096
1063
|
)
|
1097
|
-
amount_wei = sum(amount_per_index.values())
|
1064
|
+
amount_wei = sum(amount_per_index.values(), start=OutcomeWei.zero())
|
1098
1065
|
if amount_wei == 0:
|
1099
1066
|
logger.debug("No balance to claim. Exiting.")
|
1100
1067
|
return
|
@@ -1112,10 +1079,10 @@ def omen_redeem_full_position_tx(
|
|
1112
1079
|
web3=web3,
|
1113
1080
|
)
|
1114
1081
|
new_balance = collateral_token_contract.balanceOf(from_address, web3=web3)
|
1115
|
-
balance_diff =
|
1082
|
+
balance_diff = new_balance - original_balance
|
1116
1083
|
|
1117
1084
|
logger.info(
|
1118
|
-
f"Redeemed {
|
1085
|
+
f"Redeemed {balance_diff.as_token} {collateral_token_contract.symbol_cached(web3=web3)} from market {market.question=} ({market.url})."
|
1119
1086
|
)
|
1120
1087
|
|
1121
1088
|
if auto_withdraw:
|
@@ -1131,12 +1098,12 @@ def get_conditional_tokens_balance_for_market(
|
|
1131
1098
|
market: OmenAgentMarket,
|
1132
1099
|
from_address: ChecksumAddress,
|
1133
1100
|
web3: Web3 | None = None,
|
1134
|
-
) -> dict[int,
|
1101
|
+
) -> dict[int, OutcomeWei]:
|
1135
1102
|
"""
|
1136
1103
|
We derive the withdrawable balance from the ConditionalTokens contract through CollectionId -> PositionId (which
|
1137
1104
|
also serves as tokenId) -> TokenBalances.
|
1138
1105
|
"""
|
1139
|
-
balance_per_index_set: dict[int,
|
1106
|
+
balance_per_index_set: dict[int, OutcomeWei] = {}
|
1140
1107
|
conditional_token_contract = OmenConditionalTokenContract()
|
1141
1108
|
parent_collection_id = build_parent_collection_id()
|
1142
1109
|
|
@@ -1153,7 +1120,7 @@ def get_conditional_tokens_balance_for_market(
|
|
1153
1120
|
balance_for_position = conditional_token_contract.balanceOf(
|
1154
1121
|
from_address=from_address, position_id=position_id, web3=web3
|
1155
1122
|
)
|
1156
|
-
balance_per_index_set[index_set] =
|
1123
|
+
balance_per_index_set[index_set] = balance_for_position
|
1157
1124
|
|
1158
1125
|
return balance_per_index_set
|
1159
1126
|
|
@@ -1214,11 +1181,11 @@ def omen_remove_fund_market_tx(
|
|
1214
1181
|
)
|
1215
1182
|
|
1216
1183
|
new_balance = market_collateral_token_contract.balanceOf(from_address, web3=web3)
|
1217
|
-
balance_diff =
|
1184
|
+
balance_diff = new_balance - original_balance
|
1218
1185
|
|
1219
1186
|
logger.debug(f"Result from merge positions {result}")
|
1220
1187
|
logger.info(
|
1221
|
-
f"Withdrawn {
|
1188
|
+
f"Withdrawn {balance_diff.as_token} {market_collateral_token_contract.symbol_cached(web3=web3)} from liquidity at {market.url=}."
|
1222
1189
|
)
|
1223
1190
|
|
1224
1191
|
if auto_withdraw:
|
@@ -1244,7 +1211,7 @@ def redeem_from_all_user_positions(
|
|
1244
1211
|
user_positions = OmenSubgraphHandler().get_user_positions(
|
1245
1212
|
public_key,
|
1246
1213
|
# After redeem, this will became zero and we won't re-process it.
|
1247
|
-
total_balance_bigger_than=
|
1214
|
+
total_balance_bigger_than=OutcomeWei(0),
|
1248
1215
|
)
|
1249
1216
|
|
1250
1217
|
for index, user_position in enumerate(user_positions):
|
@@ -1272,10 +1239,10 @@ def redeem_from_all_user_positions(
|
|
1272
1239
|
web3=web3,
|
1273
1240
|
)
|
1274
1241
|
new_balance = collateral_token_contract.balanceOf(public_key, web3=web3)
|
1275
|
-
balance_diff =
|
1242
|
+
balance_diff = new_balance - original_balance
|
1276
1243
|
|
1277
1244
|
logger.info(
|
1278
|
-
f"Redeemed {
|
1245
|
+
f"Redeemed {balance_diff.as_token} {collateral_token_contract.symbol_cached(web3=web3)} from position {user_position.id=}."
|
1279
1246
|
)
|
1280
1247
|
|
1281
1248
|
if auto_withdraw:
|
@@ -1346,23 +1313,21 @@ def send_keeping_token_to_eoa_xdai(
|
|
1346
1313
|
)
|
1347
1314
|
return
|
1348
1315
|
|
1349
|
-
need_to_withdraw =
|
1350
|
-
|
1351
|
-
)
|
1352
|
-
need_to_withdraw_wei = xdai_to_wei(need_to_withdraw)
|
1316
|
+
need_to_withdraw = (min_required_balance - current_balances_eoa.xdai) * multiplier
|
1317
|
+
need_to_withdraw_wei = need_to_withdraw.as_xdai_wei
|
1353
1318
|
|
1354
|
-
if current_balances_eoa.wxdai >= need_to_withdraw:
|
1319
|
+
if current_balances_eoa.wxdai >= need_to_withdraw.as_token:
|
1355
1320
|
# If EOA has enough of wxDai, simply withdraw it.
|
1356
1321
|
logger.info(
|
1357
1322
|
f"Withdrawing {need_to_withdraw} wxDai from EOA to keep the EOA's xDai balance above the minimum required balance {min_required_balance}."
|
1358
1323
|
)
|
1359
1324
|
wxdai_contract.withdraw(
|
1360
1325
|
api_keys=api_keys.copy_without_safe_address(),
|
1361
|
-
amount_wei=need_to_withdraw_wei,
|
1326
|
+
amount_wei=need_to_withdraw_wei.as_wei,
|
1362
1327
|
web3=web3,
|
1363
1328
|
)
|
1364
1329
|
|
1365
|
-
elif current_balances_betting.wxdai >= need_to_withdraw:
|
1330
|
+
elif current_balances_betting.wxdai >= need_to_withdraw.as_token:
|
1366
1331
|
# If Safe has enough of wxDai:
|
1367
1332
|
# First send them to EOA's address.
|
1368
1333
|
logger.info(
|
@@ -1372,7 +1337,7 @@ def send_keeping_token_to_eoa_xdai(
|
|
1372
1337
|
api_keys=api_keys,
|
1373
1338
|
sender=api_keys.bet_from_address,
|
1374
1339
|
recipient=api_keys.public_key,
|
1375
|
-
amount_wei=need_to_withdraw_wei,
|
1340
|
+
amount_wei=need_to_withdraw_wei.as_wei,
|
1376
1341
|
web3=web3,
|
1377
1342
|
)
|
1378
1343
|
# And then simply withdraw it.
|
@@ -1381,7 +1346,7 @@ def send_keeping_token_to_eoa_xdai(
|
|
1381
1346
|
)
|
1382
1347
|
wxdai_contract.withdraw(
|
1383
1348
|
api_keys=api_keys.copy_without_safe_address(),
|
1384
|
-
amount_wei=need_to_withdraw_wei,
|
1349
|
+
amount_wei=need_to_withdraw_wei.as_wei,
|
1385
1350
|
web3=web3,
|
1386
1351
|
)
|
1387
1352
|
|
@@ -1392,30 +1357,37 @@ def send_keeping_token_to_eoa_xdai(
|
|
1392
1357
|
|
1393
1358
|
|
1394
1359
|
def get_buy_outcome_token_amount(
|
1395
|
-
investment_amount:
|
1360
|
+
investment_amount: CollateralToken,
|
1396
1361
|
buy_direction: bool,
|
1397
|
-
yes_outcome_pool_size:
|
1398
|
-
no_outcome_pool_size:
|
1362
|
+
yes_outcome_pool_size: OutcomeToken,
|
1363
|
+
no_outcome_pool_size: OutcomeToken,
|
1399
1364
|
fees: MarketFees,
|
1400
|
-
) ->
|
1365
|
+
) -> OutcomeToken:
|
1401
1366
|
"""
|
1402
1367
|
Calculates the amount of outcome tokens received for a given investment
|
1403
1368
|
|
1404
1369
|
Taken from https://github.com/gnosis/conditional-tokens-market-makers/blob/6814c0247c745680bb13298d4f0dd7f5b574d0db/contracts/FixedProductMarketMaker.sol#L264
|
1405
1370
|
"""
|
1406
|
-
investment_amount_minus_fees = fees.
|
1371
|
+
investment_amount_minus_fees = fees.get_after_fees(investment_amount)
|
1372
|
+
investment_amount_minus_fees_as_ot = OutcomeToken(
|
1373
|
+
investment_amount_minus_fees.value
|
1374
|
+
)
|
1407
1375
|
buy_token_pool_balance = (
|
1408
1376
|
yes_outcome_pool_size if buy_direction else no_outcome_pool_size
|
1409
1377
|
)
|
1410
1378
|
|
1411
1379
|
pool_balance = no_outcome_pool_size if buy_direction else yes_outcome_pool_size
|
1412
|
-
denominator = pool_balance +
|
1413
|
-
ending_outcome_balance =
|
1380
|
+
denominator = pool_balance + investment_amount_minus_fees_as_ot
|
1381
|
+
ending_outcome_balance = OutcomeToken(
|
1382
|
+
buy_token_pool_balance * pool_balance / denominator
|
1383
|
+
)
|
1414
1384
|
|
1415
1385
|
if ending_outcome_balance <= 0:
|
1416
1386
|
raise ValueError("must have non-zero balances")
|
1417
1387
|
|
1418
1388
|
result = (
|
1419
|
-
buy_token_pool_balance
|
1389
|
+
buy_token_pool_balance
|
1390
|
+
+ investment_amount_minus_fees_as_ot
|
1391
|
+
- ending_outcome_balance
|
1420
1392
|
)
|
1421
1393
|
return result
|