prediction-market-agent-tooling 0.48.18__py3-none-any.whl → 0.49.1__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/abis/debuggingcontract.abi.json +29 -0
- prediction_market_agent_tooling/abis/omen_agentresultmapping.abi.json +171 -0
- prediction_market_agent_tooling/benchmark/benchmark.py +0 -93
- prediction_market_agent_tooling/config.py +16 -0
- prediction_market_agent_tooling/deploy/agent.py +86 -13
- prediction_market_agent_tooling/deploy/betting_strategy.py +5 -35
- prediction_market_agent_tooling/jobs/omen/omen_jobs.py +2 -1
- prediction_market_agent_tooling/markets/agent_market.py +14 -6
- prediction_market_agent_tooling/markets/data_models.py +14 -0
- prediction_market_agent_tooling/markets/manifold/api.py +3 -1
- prediction_market_agent_tooling/markets/manifold/manifold.py +7 -2
- prediction_market_agent_tooling/markets/metaculus/metaculus.py +6 -1
- prediction_market_agent_tooling/markets/omen/data_models.py +247 -6
- prediction_market_agent_tooling/markets/omen/omen.py +77 -43
- prediction_market_agent_tooling/markets/omen/omen_contracts.py +179 -33
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +35 -0
- prediction_market_agent_tooling/markets/polymarket/polymarket.py +1 -1
- prediction_market_agent_tooling/monitor/markets/polymarket.py +4 -0
- prediction_market_agent_tooling/monitor/monitor.py +3 -3
- prediction_market_agent_tooling/monitor/monitor_app.py +2 -2
- prediction_market_agent_tooling/tools/contract.py +50 -1
- prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +33 -0
- prediction_market_agent_tooling/tools/langfuse_client_utils.py +27 -12
- prediction_market_agent_tooling/tools/utils.py +28 -4
- prediction_market_agent_tooling/tools/web3_utils.py +7 -0
- {prediction_market_agent_tooling-0.48.18.dist-info → prediction_market_agent_tooling-0.49.1.dist-info}/METADATA +2 -1
- {prediction_market_agent_tooling-0.48.18.dist-info → prediction_market_agent_tooling-0.49.1.dist-info}/RECORD +30 -27
- {prediction_market_agent_tooling-0.48.18.dist-info → prediction_market_agent_tooling-0.49.1.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.48.18.dist-info → prediction_market_agent_tooling-0.49.1.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.48.18.dist-info → prediction_market_agent_tooling-0.49.1.dist-info}/entry_points.txt +0 -0
@@ -1,16 +1,16 @@
|
|
1
1
|
import sys
|
2
2
|
import typing as t
|
3
|
-
from datetime import datetime
|
3
|
+
from datetime import datetime, timedelta
|
4
4
|
|
5
5
|
import tenacity
|
6
6
|
from web3 import Web3
|
7
|
-
from web3.constants import HASH_ZERO
|
8
7
|
|
9
8
|
from prediction_market_agent_tooling.config import APIKeys
|
10
9
|
from prediction_market_agent_tooling.gtypes import (
|
11
10
|
ChecksumAddress,
|
12
11
|
HexAddress,
|
13
12
|
HexStr,
|
13
|
+
OmenOutcomeToken,
|
14
14
|
OutcomeStr,
|
15
15
|
Probability,
|
16
16
|
Wei,
|
@@ -37,6 +37,8 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
|
|
37
37
|
OMEN_TRUE_OUTCOME,
|
38
38
|
PRESAGIO_BASE_URL,
|
39
39
|
Condition,
|
40
|
+
ConditionPreparationEvent,
|
41
|
+
CreatedMarket,
|
40
42
|
OmenBet,
|
41
43
|
OmenMarket,
|
42
44
|
OmenUserPosition,
|
@@ -44,7 +46,7 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
|
|
44
46
|
get_boolean_outcome,
|
45
47
|
)
|
46
48
|
from prediction_market_agent_tooling.markets.omen.omen_contracts import (
|
47
|
-
|
49
|
+
OMEN_DEFAULT_MARKET_FEE_PERC,
|
48
50
|
Arbitrator,
|
49
51
|
OmenConditionalTokenContract,
|
50
52
|
OmenFixedProductMarketMakerContract,
|
@@ -52,6 +54,7 @@ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
|
|
52
54
|
OmenOracleContract,
|
53
55
|
OmenRealitioContract,
|
54
56
|
WrappedxDaiContract,
|
57
|
+
build_parent_collection_id,
|
55
58
|
)
|
56
59
|
from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
|
57
60
|
OmenSubgraphHandler,
|
@@ -71,6 +74,7 @@ from prediction_market_agent_tooling.tools.utils import (
|
|
71
74
|
)
|
72
75
|
from prediction_market_agent_tooling.tools.web3_utils import (
|
73
76
|
add_fraction,
|
77
|
+
get_receipt_block_timestamp,
|
74
78
|
remove_fraction,
|
75
79
|
wei_to_xdai,
|
76
80
|
xdai_to_wei,
|
@@ -189,7 +193,7 @@ class OmenAgentMarket(AgentMarket):
|
|
189
193
|
omen_auto_deposit: bool = True,
|
190
194
|
web3: Web3 | None = None,
|
191
195
|
api_keys: APIKeys | None = None,
|
192
|
-
) ->
|
196
|
+
) -> str:
|
193
197
|
if not self.can_be_traded():
|
194
198
|
raise ValueError(
|
195
199
|
f"Market {self.id} is not open for trading. Cannot place bet."
|
@@ -197,7 +201,7 @@ class OmenAgentMarket(AgentMarket):
|
|
197
201
|
if amount.currency != self.currency:
|
198
202
|
raise ValueError(f"Omen bets are made in xDai. Got {amount.currency}.")
|
199
203
|
amount_xdai = xDai(amount.amount)
|
200
|
-
binary_omen_buy_outcome_tx(
|
204
|
+
return binary_omen_buy_outcome_tx(
|
201
205
|
api_keys=api_keys if api_keys is not None else APIKeys(),
|
202
206
|
amount=amount_xdai,
|
203
207
|
market=self,
|
@@ -212,7 +216,7 @@ class OmenAgentMarket(AgentMarket):
|
|
212
216
|
amount: TokenAmount,
|
213
217
|
web3: Web3 | None = None,
|
214
218
|
api_keys: APIKeys | None = None,
|
215
|
-
) ->
|
219
|
+
) -> str:
|
216
220
|
return self.place_bet(
|
217
221
|
outcome=outcome,
|
218
222
|
amount=amount,
|
@@ -245,7 +249,7 @@ class OmenAgentMarket(AgentMarket):
|
|
245
249
|
auto_withdraw: bool = False,
|
246
250
|
api_keys: APIKeys | None = None,
|
247
251
|
web3: Web3 | None = None,
|
248
|
-
) ->
|
252
|
+
) -> str:
|
249
253
|
if not self.can_be_traded():
|
250
254
|
raise ValueError(
|
251
255
|
f"Market {self.id} is not open for trading. Cannot sell tokens."
|
@@ -258,7 +262,7 @@ class OmenAgentMarket(AgentMarket):
|
|
258
262
|
outcome=outcome,
|
259
263
|
web3=web3,
|
260
264
|
)
|
261
|
-
binary_omen_sell_outcome_tx(
|
265
|
+
return binary_omen_sell_outcome_tx(
|
262
266
|
amount=collateral,
|
263
267
|
api_keys=api_keys if api_keys is not None else APIKeys(),
|
264
268
|
market=self,
|
@@ -325,6 +329,10 @@ class OmenAgentMarket(AgentMarket):
|
|
325
329
|
|
326
330
|
omen_redeem_full_position_tx(api_keys=api_keys, market=self)
|
327
331
|
|
332
|
+
@staticmethod
|
333
|
+
def from_created_market(model: "CreatedMarket") -> "OmenAgentMarket":
|
334
|
+
return OmenAgentMarket.from_data_model(OmenMarket.from_created_market(model))
|
335
|
+
|
328
336
|
@staticmethod
|
329
337
|
def from_data_model(model: OmenMarket) -> "OmenAgentMarket":
|
330
338
|
return OmenAgentMarket(
|
@@ -633,6 +641,14 @@ class OmenAgentMarket(AgentMarket):
|
|
633
641
|
)
|
634
642
|
return Probability(new_p_yes)
|
635
643
|
|
644
|
+
@staticmethod
|
645
|
+
def get_user_balance(user_id: str) -> float:
|
646
|
+
return float(get_balances(Web3.to_checksum_address(user_id)).total)
|
647
|
+
|
648
|
+
@staticmethod
|
649
|
+
def get_user_id(api_keys: APIKeys) -> str:
|
650
|
+
return api_keys.bet_from_address
|
651
|
+
|
636
652
|
|
637
653
|
def get_omen_user_url(address: ChecksumAddress) -> str:
|
638
654
|
return f"https://gnosisscan.io/address/{address}"
|
@@ -659,14 +675,14 @@ def omen_buy_outcome_tx(
|
|
659
675
|
outcome: str,
|
660
676
|
auto_deposit: bool,
|
661
677
|
web3: Web3 | None = None,
|
662
|
-
) ->
|
678
|
+
) -> str:
|
663
679
|
"""
|
664
680
|
Bets the given amount of xDai for the given outcome in the given market.
|
665
681
|
"""
|
666
682
|
amount_wei = xdai_to_wei(amount)
|
667
683
|
|
668
684
|
market_contract: OmenFixedProductMarketMakerContract = market.get_contract()
|
669
|
-
collateral_token_contract = market_contract.get_collateral_token_contract()
|
685
|
+
collateral_token_contract = market_contract.get_collateral_token_contract(web3)
|
670
686
|
|
671
687
|
# In case of ERC4626, obtained (for example) sDai out of xDai could be lower than the `amount_wei`, so we need to handle it.
|
672
688
|
amount_wei_to_buy = collateral_token_contract.get_in_shares(amount_wei, web3)
|
@@ -695,7 +711,7 @@ def omen_buy_outcome_tx(
|
|
695
711
|
)
|
696
712
|
|
697
713
|
# Buy shares using the deposited xDai in the collateral token.
|
698
|
-
market_contract.buy(
|
714
|
+
tx_receipt = market_contract.buy(
|
699
715
|
api_keys=api_keys,
|
700
716
|
amount_wei=amount_wei_to_buy,
|
701
717
|
outcome_index=outcome_index,
|
@@ -703,6 +719,8 @@ def omen_buy_outcome_tx(
|
|
703
719
|
web3=web3,
|
704
720
|
)
|
705
721
|
|
722
|
+
return tx_receipt["transactionHash"].hex()
|
723
|
+
|
706
724
|
|
707
725
|
def binary_omen_buy_outcome_tx(
|
708
726
|
api_keys: APIKeys,
|
@@ -711,8 +729,8 @@ def binary_omen_buy_outcome_tx(
|
|
711
729
|
binary_outcome: bool,
|
712
730
|
auto_deposit: bool,
|
713
731
|
web3: Web3 | None = None,
|
714
|
-
) ->
|
715
|
-
omen_buy_outcome_tx(
|
732
|
+
) -> str:
|
733
|
+
return omen_buy_outcome_tx(
|
716
734
|
api_keys=api_keys,
|
717
735
|
amount=amount,
|
718
736
|
market=market,
|
@@ -729,7 +747,7 @@ def omen_sell_outcome_tx(
|
|
729
747
|
outcome: str,
|
730
748
|
auto_withdraw: bool,
|
731
749
|
web3: Web3 | None = None,
|
732
|
-
) ->
|
750
|
+
) -> str:
|
733
751
|
"""
|
734
752
|
Sells the given xDai value of shares corresponding to the given outcome in
|
735
753
|
the given market.
|
@@ -741,7 +759,7 @@ def omen_sell_outcome_tx(
|
|
741
759
|
|
742
760
|
market_contract: OmenFixedProductMarketMakerContract = market.get_contract()
|
743
761
|
conditional_token_contract = OmenConditionalTokenContract()
|
744
|
-
collateral_token_contract = market_contract.get_collateral_token_contract()
|
762
|
+
collateral_token_contract = market_contract.get_collateral_token_contract(web3)
|
745
763
|
|
746
764
|
# Verify, that markets uses conditional tokens that we expect.
|
747
765
|
if (
|
@@ -770,7 +788,7 @@ def omen_sell_outcome_tx(
|
|
770
788
|
web3=web3,
|
771
789
|
)
|
772
790
|
# Sell the shares.
|
773
|
-
market_contract.sell(
|
791
|
+
tx_receipt = market_contract.sell(
|
774
792
|
api_keys,
|
775
793
|
amount_wei,
|
776
794
|
outcome_index,
|
@@ -792,6 +810,8 @@ def omen_sell_outcome_tx(
|
|
792
810
|
web3,
|
793
811
|
)
|
794
812
|
|
813
|
+
return tx_receipt["transactionHash"].hex()
|
814
|
+
|
795
815
|
|
796
816
|
def binary_omen_sell_outcome_tx(
|
797
817
|
api_keys: APIKeys,
|
@@ -800,8 +820,8 @@ def binary_omen_sell_outcome_tx(
|
|
800
820
|
binary_outcome: bool,
|
801
821
|
auto_withdraw: bool,
|
802
822
|
web3: Web3 | None = None,
|
803
|
-
) ->
|
804
|
-
omen_sell_outcome_tx(
|
823
|
+
) -> str:
|
824
|
+
return omen_sell_outcome_tx(
|
805
825
|
api_keys=api_keys,
|
806
826
|
amount=amount,
|
807
827
|
market=market,
|
@@ -820,10 +840,13 @@ def omen_create_market_tx(
|
|
820
840
|
language: str,
|
821
841
|
outcomes: list[str],
|
822
842
|
auto_deposit: bool,
|
823
|
-
|
843
|
+
finalization_timeout: timedelta = timedelta(days=1),
|
844
|
+
fee_perc: float = OMEN_DEFAULT_MARKET_FEE_PERC,
|
845
|
+
distribution_hint: list[OmenOutcomeToken] | None = None,
|
824
846
|
collateral_token_address: ChecksumAddress = WrappedxDaiContract().address,
|
847
|
+
arbitrator: Arbitrator = Arbitrator.KLEROS_31_JURORS_WITH_APPEAL,
|
825
848
|
web3: Web3 | None = None,
|
826
|
-
) ->
|
849
|
+
) -> CreatedMarket:
|
827
850
|
"""
|
828
851
|
Based on omen-exchange TypeScript code: https://github.com/protofire/omen-exchange/blob/b0b9a3e71b415d6becf21fe428e1c4fc0dad2e80/app/src/services/cpk/cpk.ts#L308
|
829
852
|
"""
|
@@ -861,28 +884,30 @@ def omen_create_market_tx(
|
|
861
884
|
)
|
862
885
|
|
863
886
|
# Create the question on Realitio.
|
864
|
-
|
887
|
+
question_event = realitio_contract.askQuestion(
|
865
888
|
api_keys=api_keys,
|
866
889
|
question=question,
|
867
890
|
category=category,
|
868
891
|
outcomes=outcomes,
|
869
892
|
language=language,
|
870
|
-
arbitrator=
|
893
|
+
arbitrator=arbitrator,
|
871
894
|
opening=closing_time, # The question is opened at the closing time of the market.
|
895
|
+
timeout=finalization_timeout,
|
872
896
|
web3=web3,
|
873
897
|
)
|
874
898
|
|
875
899
|
# Construct the condition id.
|
900
|
+
cond_event: ConditionPreparationEvent | None = None
|
876
901
|
condition_id = conditional_token_contract.getConditionId(
|
877
|
-
question_id=question_id,
|
902
|
+
question_id=question_event.question_id,
|
878
903
|
oracle_address=oracle_contract.address,
|
879
904
|
outcomes_slot_count=len(outcomes),
|
880
905
|
web3=web3,
|
881
906
|
)
|
882
907
|
if not conditional_token_contract.does_condition_exists(condition_id, web3=web3):
|
883
|
-
conditional_token_contract.prepareCondition(
|
908
|
+
cond_event = conditional_token_contract.prepareCondition(
|
884
909
|
api_keys=api_keys,
|
885
|
-
question_id=question_id,
|
910
|
+
question_id=question_event.question_id,
|
886
911
|
oracle_address=oracle_contract.address,
|
887
912
|
outcomes_slot_count=len(outcomes),
|
888
913
|
web3=web3,
|
@@ -902,10 +927,16 @@ def omen_create_market_tx(
|
|
902
927
|
)
|
903
928
|
|
904
929
|
# Create the market.
|
905
|
-
|
930
|
+
fee = xdai_to_wei(xdai_type(fee_perc))
|
931
|
+
(
|
932
|
+
market_event,
|
933
|
+
funding_event,
|
934
|
+
receipt_tx,
|
935
|
+
) = factory_contract.create2FixedProductMarketMaker(
|
906
936
|
api_keys=api_keys,
|
907
937
|
condition_id=condition_id,
|
908
938
|
fee=fee,
|
939
|
+
distribution_hint=distribution_hint,
|
909
940
|
initial_funds_wei=initial_funds_in_shares,
|
910
941
|
collateral_token_address=collateral_token_contract.address,
|
911
942
|
web3=web3,
|
@@ -916,10 +947,17 @@ def omen_create_market_tx(
|
|
916
947
|
# but address of stakingRewardsFactoryAddress on xDai/Gnosis is 0x0000000000000000000000000000000000000000,
|
917
948
|
# so skipping it here.
|
918
949
|
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
950
|
+
return CreatedMarket(
|
951
|
+
market_creation_timestamp=get_receipt_block_timestamp(receipt_tx, web3),
|
952
|
+
market_event=market_event,
|
953
|
+
funding_event=funding_event,
|
954
|
+
condition_id=condition_id,
|
955
|
+
question_event=question_event,
|
956
|
+
condition_event=cond_event,
|
957
|
+
initial_funds=initial_funds_wei,
|
958
|
+
fee=fee,
|
959
|
+
distribution_hint=distribution_hint,
|
960
|
+
)
|
923
961
|
|
924
962
|
|
925
963
|
def omen_fund_market_tx(
|
@@ -930,7 +968,7 @@ def omen_fund_market_tx(
|
|
930
968
|
web3: Web3 | None = None,
|
931
969
|
) -> None:
|
932
970
|
market_contract = market.get_contract()
|
933
|
-
collateral_token_contract = market_contract.get_collateral_token_contract()
|
971
|
+
collateral_token_contract = market_contract.get_collateral_token_contract(web3=web3)
|
934
972
|
|
935
973
|
amount_to_fund = collateral_token_contract.get_in_shares(funds, web3)
|
936
974
|
|
@@ -948,10 +986,6 @@ def omen_fund_market_tx(
|
|
948
986
|
market_contract.addFunding(api_keys, amount_to_fund, web3=web3)
|
949
987
|
|
950
988
|
|
951
|
-
def build_parent_collection_id() -> HexStr:
|
952
|
-
return HASH_ZERO # Taken from Olas
|
953
|
-
|
954
|
-
|
955
989
|
def omen_redeem_full_position_tx(
|
956
990
|
api_keys: APIKeys,
|
957
991
|
market: OmenAgentMarket,
|
@@ -973,8 +1007,6 @@ def omen_redeem_full_position_tx(
|
|
973
1007
|
f"Market {market.id} uses conditional token that we didn't expect, {market_contract.conditionalTokens()} != {conditional_token_contract.address=}"
|
974
1008
|
)
|
975
1009
|
|
976
|
-
parent_collection_id = build_parent_collection_id()
|
977
|
-
|
978
1010
|
if not market.is_resolved():
|
979
1011
|
logger.debug("Cannot redeem winnings if market is not yet resolved. Exiting.")
|
980
1012
|
return
|
@@ -995,7 +1027,6 @@ def omen_redeem_full_position_tx(
|
|
995
1027
|
api_keys=api_keys,
|
996
1028
|
collateral_token_address=market.collateral_token_contract_address_checksummed,
|
997
1029
|
condition_id=market.condition.id,
|
998
|
-
parent_collection_id=parent_collection_id,
|
999
1030
|
index_sets=market.condition.index_sets,
|
1000
1031
|
web3=web3,
|
1001
1032
|
)
|
@@ -1048,8 +1079,12 @@ def omen_remove_fund_market_tx(
|
|
1048
1079
|
"""
|
1049
1080
|
from_address = api_keys.bet_from_address
|
1050
1081
|
market_contract = market.get_contract()
|
1051
|
-
market_collateral_token_contract = market_contract.get_collateral_token_contract(
|
1052
|
-
|
1082
|
+
market_collateral_token_contract = market_contract.get_collateral_token_contract(
|
1083
|
+
web3=web3
|
1084
|
+
)
|
1085
|
+
original_balance = market_collateral_token_contract.balanceOf(
|
1086
|
+
from_address, web3=web3
|
1087
|
+
)
|
1053
1088
|
|
1054
1089
|
total_shares = market_contract.balanceOf(from_address, web3=web3)
|
1055
1090
|
if total_shares == 0:
|
@@ -1084,11 +1119,11 @@ def omen_remove_fund_market_tx(
|
|
1084
1119
|
web3=web3,
|
1085
1120
|
)
|
1086
1121
|
|
1087
|
-
new_balance = market_collateral_token_contract.balanceOf(from_address)
|
1122
|
+
new_balance = market_collateral_token_contract.balanceOf(from_address, web3=web3)
|
1088
1123
|
|
1089
1124
|
logger.debug(f"Result from merge positions {result}")
|
1090
1125
|
logger.info(
|
1091
|
-
f"Withdrawn {new_balance - original_balance} {market_collateral_token_contract.symbol_cached()} from liquidity at {market.url=}."
|
1126
|
+
f"Withdrawn {new_balance - original_balance} {market_collateral_token_contract.symbol_cached(web3=web3)} from liquidity at {market.url=}."
|
1092
1127
|
)
|
1093
1128
|
|
1094
1129
|
|
@@ -1126,7 +1161,6 @@ def redeem_from_all_user_positions(
|
|
1126
1161
|
api_keys=api_keys,
|
1127
1162
|
collateral_token_address=user_position.position.collateral_token_contract_address_checksummed,
|
1128
1163
|
condition_id=condition_id,
|
1129
|
-
parent_collection_id=build_parent_collection_id(),
|
1130
1164
|
index_sets=user_position.position.indexSets,
|
1131
1165
|
web3=web3,
|
1132
1166
|
)
|