prediction-market-agent-tooling 0.68.0.dev999__py3-none-any.whl → 0.69.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/chains.py +1 -0
- prediction_market_agent_tooling/config.py +37 -2
- prediction_market_agent_tooling/deploy/agent.py +26 -21
- prediction_market_agent_tooling/deploy/betting_strategy.py +133 -22
- prediction_market_agent_tooling/jobs/jobs_models.py +2 -2
- prediction_market_agent_tooling/jobs/omen/omen_jobs.py +17 -20
- prediction_market_agent_tooling/markets/agent_market.py +27 -9
- prediction_market_agent_tooling/markets/blockchain_utils.py +3 -3
- prediction_market_agent_tooling/markets/markets.py +16 -0
- prediction_market_agent_tooling/markets/omen/data_models.py +3 -18
- prediction_market_agent_tooling/markets/omen/omen.py +26 -11
- prediction_market_agent_tooling/markets/omen/omen_contracts.py +2 -196
- prediction_market_agent_tooling/markets/omen/omen_resolving.py +2 -2
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +13 -11
- prediction_market_agent_tooling/markets/polymarket/api.py +35 -1
- prediction_market_agent_tooling/markets/polymarket/clob_manager.py +156 -0
- prediction_market_agent_tooling/markets/polymarket/constants.py +15 -0
- prediction_market_agent_tooling/markets/polymarket/data_models.py +33 -5
- prediction_market_agent_tooling/markets/polymarket/polymarket.py +247 -18
- prediction_market_agent_tooling/markets/polymarket/polymarket_contracts.py +35 -0
- prediction_market_agent_tooling/markets/polymarket/polymarket_subgraph_handler.py +2 -1
- prediction_market_agent_tooling/markets/seer/data_models.py +41 -6
- prediction_market_agent_tooling/markets/seer/price_manager.py +69 -1
- prediction_market_agent_tooling/markets/seer/seer.py +77 -26
- prediction_market_agent_tooling/markets/seer/seer_api.py +28 -0
- prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +71 -20
- prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +67 -0
- prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +17 -22
- prediction_market_agent_tooling/tools/contract.py +236 -4
- prediction_market_agent_tooling/tools/cow/cow_order.py +13 -8
- prediction_market_agent_tooling/tools/datetime_utc.py +14 -2
- prediction_market_agent_tooling/tools/hexbytes_custom.py +3 -9
- prediction_market_agent_tooling/tools/langfuse_client_utils.py +17 -5
- prediction_market_agent_tooling/tools/tokens/auto_deposit.py +2 -2
- prediction_market_agent_tooling/tools/tokens/usd.py +5 -2
- prediction_market_agent_tooling/tools/web3_utils.py +9 -4
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/METADATA +8 -7
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/RECORD +41 -38
- prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -366
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.69.0.dist-info}/entry_points.txt +0 -0
@@ -23,6 +23,7 @@ from prediction_market_agent_tooling.gtypes import (
|
|
23
23
|
OutcomeWei,
|
24
24
|
Probability,
|
25
25
|
Wei,
|
26
|
+
xDai,
|
26
27
|
)
|
27
28
|
from prediction_market_agent_tooling.markets.data_models import (
|
28
29
|
USD,
|
@@ -44,9 +45,6 @@ from prediction_market_agent_tooling.tools.utils import (
|
|
44
45
|
|
45
46
|
class ProcessedMarket(BaseModel):
|
46
47
|
answer: CategoricalProbabilisticAnswer
|
47
|
-
|
48
|
-
|
49
|
-
class ProcessedTradedMarket(ProcessedMarket):
|
50
48
|
trades: list[PlacedTrade]
|
51
49
|
|
52
50
|
|
@@ -190,6 +188,17 @@ class AgentMarket(BaseModel):
|
|
190
188
|
f"Could not find probability for market outcome {market_outcome}"
|
191
189
|
)
|
192
190
|
|
191
|
+
@property
|
192
|
+
def question_type(self) -> QuestionType:
|
193
|
+
if self.is_binary:
|
194
|
+
return QuestionType.BINARY
|
195
|
+
|
196
|
+
elif self.is_scalar:
|
197
|
+
return QuestionType.SCALAR
|
198
|
+
|
199
|
+
else:
|
200
|
+
return QuestionType.CATEGORICAL
|
201
|
+
|
193
202
|
@property
|
194
203
|
def is_binary(self) -> bool:
|
195
204
|
# 3 outcomes can also be binary if 3rd outcome is invalid (Seer)
|
@@ -450,7 +459,7 @@ class AgentMarket(BaseModel):
|
|
450
459
|
|
451
460
|
def store_trades(
|
452
461
|
self,
|
453
|
-
traded_market:
|
462
|
+
traded_market: ProcessedMarket | None,
|
454
463
|
keys: APIKeys,
|
455
464
|
agent_name: str,
|
456
465
|
web3: Web3 | None = None,
|
@@ -509,11 +518,20 @@ class AgentMarket(BaseModel):
|
|
509
518
|
)
|
510
519
|
|
511
520
|
def get_outcome_index(self, outcome: OutcomeStr) -> int:
|
512
|
-
|
521
|
+
"""Get the index of the given outcome in the market's outcomes."""
|
513
522
|
try:
|
514
|
-
return
|
515
|
-
except ValueError:
|
516
|
-
raise ValueError(
|
523
|
+
return [o.lower() for o in self.outcomes].index(outcome.lower())
|
524
|
+
except ValueError as e:
|
525
|
+
raise ValueError(
|
526
|
+
f"Outcome '{outcome}' not found in market outcomes: {self.outcomes}"
|
527
|
+
) from e
|
528
|
+
|
529
|
+
def ensure_min_native_balance(
|
530
|
+
self,
|
531
|
+
min_required_balance: xDai,
|
532
|
+
multiplier: float = 3.0,
|
533
|
+
) -> None:
|
534
|
+
raise NotImplementedError("Subclass must implement this method")
|
517
535
|
|
518
536
|
def get_token_balance(self, user_id: str, outcome: OutcomeStr) -> OutcomeToken:
|
519
537
|
raise NotImplementedError("Subclasses must implement this method")
|
@@ -562,7 +580,7 @@ class AgentMarket(BaseModel):
|
|
562
580
|
|
563
581
|
@staticmethod
|
564
582
|
def get_user_id(api_keys: APIKeys) -> str:
|
565
|
-
|
583
|
+
return api_keys.bet_from_address
|
566
584
|
|
567
585
|
def get_most_recent_trade_datetime(self, user_id: str) -> DatetimeUTC | None:
|
568
586
|
raise NotImplementedError("Subclasses must implement this method")
|
@@ -11,7 +11,7 @@ from prediction_market_agent_tooling.gtypes import (
|
|
11
11
|
OutcomeStr,
|
12
12
|
)
|
13
13
|
from prediction_market_agent_tooling.loggers import logger
|
14
|
-
from prediction_market_agent_tooling.markets.agent_market import
|
14
|
+
from prediction_market_agent_tooling.markets.agent_market import ProcessedMarket
|
15
15
|
from prediction_market_agent_tooling.markets.omen.data_models import (
|
16
16
|
ContractPrediction,
|
17
17
|
IPFSAgentResult,
|
@@ -28,7 +28,7 @@ def store_trades(
|
|
28
28
|
contract: _AgentResultMappingContract,
|
29
29
|
market_id: ChecksumAddress,
|
30
30
|
outcomes: Sequence[OutcomeStr],
|
31
|
-
traded_market:
|
31
|
+
traded_market: ProcessedMarket | None,
|
32
32
|
keys: APIKeys,
|
33
33
|
agent_name: str,
|
34
34
|
web3: Web3 | None = None,
|
@@ -83,5 +83,5 @@ def store_trades(
|
|
83
83
|
web3=web3,
|
84
84
|
)
|
85
85
|
logger.info(
|
86
|
-
f"Added prediction to market {market_id}. - receipt {tx_receipt['transactionHash'].
|
86
|
+
f"Added prediction to market {market_id}. - receipt {tx_receipt['transactionHash'].to_0x_hex()}."
|
87
87
|
)
|
@@ -31,6 +31,10 @@ class MarketType(str, Enum):
|
|
31
31
|
METACULUS = "metaculus"
|
32
32
|
SEER = "seer"
|
33
33
|
|
34
|
+
@staticmethod
|
35
|
+
def from_market(market: AgentMarket) -> "MarketType":
|
36
|
+
return AGENT_MARKET_TO_MARKET_TYPE[type(market)]
|
37
|
+
|
34
38
|
@property
|
35
39
|
def market_class(self) -> type[AgentMarket]:
|
36
40
|
if self not in MARKET_TYPE_TO_AGENT_MARKET:
|
@@ -43,6 +47,15 @@ class MarketType(str, Enum):
|
|
43
47
|
raise ValueError(f"Unknown market type: {self}")
|
44
48
|
return JOB_MARKET_TYPE_TO_JOB_AGENT_MARKET[self]
|
45
49
|
|
50
|
+
@property
|
51
|
+
def is_trading_market(self) -> bool:
|
52
|
+
return self in [
|
53
|
+
MarketType.OMEN,
|
54
|
+
MarketType.POLYMARKET,
|
55
|
+
MarketType.SEER,
|
56
|
+
MarketType.MANIFOLD,
|
57
|
+
]
|
58
|
+
|
46
59
|
@property
|
47
60
|
def is_blockchain_market(self) -> bool:
|
48
61
|
return self in [MarketType.OMEN, MarketType.POLYMARKET, MarketType.SEER]
|
@@ -56,6 +69,9 @@ MARKET_TYPE_TO_AGENT_MARKET: dict[MarketType, type[AgentMarket]] = {
|
|
56
69
|
MarketType.SEER: SeerAgentMarket,
|
57
70
|
}
|
58
71
|
|
72
|
+
AGENT_MARKET_TO_MARKET_TYPE: dict[type[AgentMarket], MarketType] = {
|
73
|
+
v: k for k, v in MARKET_TYPE_TO_AGENT_MARKET.items()
|
74
|
+
}
|
59
75
|
|
60
76
|
JOB_MARKET_TYPE_TO_JOB_AGENT_MARKET: dict[MarketType, type[JobAgentMarket]] = {
|
61
77
|
MarketType.OMEN: OmenJobAgentMarket,
|
@@ -28,6 +28,7 @@ from prediction_market_agent_tooling.markets.omen.omen_constants import (
|
|
28
28
|
OMEN_TRUE_OUTCOME,
|
29
29
|
)
|
30
30
|
from prediction_market_agent_tooling.tools.contract import (
|
31
|
+
ConditionPreparationEvent,
|
31
32
|
ContractERC20OnGnosisChain,
|
32
33
|
init_collateral_token_contract,
|
33
34
|
to_gnosis_chain_contract,
|
@@ -47,7 +48,7 @@ OMEN_BINARY_MARKET_OUTCOMES: t.Sequence[OutcomeStr] = [
|
|
47
48
|
]
|
48
49
|
INVALID_ANSWER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
49
50
|
INVALID_ANSWER_HEX_BYTES = HexBytes(INVALID_ANSWER)
|
50
|
-
INVALID_ANSWER_STR = HexStr(INVALID_ANSWER_HEX_BYTES.
|
51
|
+
INVALID_ANSWER_STR = HexStr(INVALID_ANSWER_HEX_BYTES.to_0x_hex())
|
51
52
|
OMEN_BASE_URL = "https://aiomen.eth.limo"
|
52
53
|
PRESAGIO_BASE_URL = "https://presagio.pages.dev"
|
53
54
|
TEST_CATEGORY = "test" # This category is hidden on Presagio for testing purposes.
|
@@ -594,7 +595,7 @@ class OmenBet(BaseModel):
|
|
594
595
|
)
|
595
596
|
|
596
597
|
return ResolvedBet(
|
597
|
-
id=self.transactionHash.
|
598
|
+
id=self.transactionHash.to_0x_hex(),
|
598
599
|
# Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
|
599
600
|
amount=self.collateral_amount_token,
|
600
601
|
outcome=self.fpmm.outcomes[self.outcomeIndex],
|
@@ -795,13 +796,6 @@ class OmenFixedProductMarketMakerCreationEvent(BaseModel):
|
|
795
796
|
return Web3.to_checksum_address(self.collateralToken)
|
796
797
|
|
797
798
|
|
798
|
-
class ConditionPreparationEvent(BaseModel):
|
799
|
-
conditionId: HexBytes
|
800
|
-
oracle: HexAddress
|
801
|
-
questionId: HexBytes
|
802
|
-
outcomeSlotCount: int
|
803
|
-
|
804
|
-
|
805
799
|
class FPMMFundingAddedEvent(BaseModel):
|
806
800
|
funder: HexAddress
|
807
801
|
amountsAdded: list[Wei]
|
@@ -895,12 +889,3 @@ class IPFSAgentResult(BaseModel):
|
|
895
889
|
model_config = ConfigDict(
|
896
890
|
extra="forbid",
|
897
891
|
)
|
898
|
-
|
899
|
-
|
900
|
-
class PayoutRedemptionEvent(BaseModel):
|
901
|
-
redeemer: HexAddress
|
902
|
-
collateralToken: HexAddress
|
903
|
-
parentCollectionId: HexBytes
|
904
|
-
conditionId: HexBytes
|
905
|
-
indexSets: list[int]
|
906
|
-
payout: Wei
|
@@ -6,6 +6,7 @@ import tenacity
|
|
6
6
|
from pydantic import BaseModel
|
7
7
|
from tqdm import tqdm
|
8
8
|
from web3 import Web3
|
9
|
+
from web3.constants import HASH_ZERO
|
9
10
|
|
10
11
|
from prediction_market_agent_tooling.config import APIKeys
|
11
12
|
from prediction_market_agent_tooling.gtypes import (
|
@@ -28,7 +29,6 @@ from prediction_market_agent_tooling.markets.agent_market import (
|
|
28
29
|
FilterBy,
|
29
30
|
MarketFees,
|
30
31
|
ProcessedMarket,
|
31
|
-
ProcessedTradedMarket,
|
32
32
|
QuestionType,
|
33
33
|
SortBy,
|
34
34
|
)
|
@@ -43,7 +43,6 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
|
|
43
43
|
OMEN_TRUE_OUTCOME,
|
44
44
|
PRESAGIO_BASE_URL,
|
45
45
|
Condition,
|
46
|
-
ConditionPreparationEvent,
|
47
46
|
CreatedMarket,
|
48
47
|
OmenBet,
|
49
48
|
OmenMarket,
|
@@ -60,13 +59,13 @@ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
|
|
60
59
|
OmenOracleContract,
|
61
60
|
OmenRealitioContract,
|
62
61
|
WrappedxDaiContract,
|
63
|
-
build_parent_collection_id,
|
64
62
|
)
|
65
63
|
from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
|
66
64
|
OmenSubgraphHandler,
|
67
65
|
)
|
68
66
|
from prediction_market_agent_tooling.tools.balances import get_balances
|
69
67
|
from prediction_market_agent_tooling.tools.contract import (
|
68
|
+
ConditionPreparationEvent,
|
70
69
|
init_collateral_token_contract,
|
71
70
|
to_gnosis_chain_contract,
|
72
71
|
)
|
@@ -411,6 +410,26 @@ class OmenAgentMarket(AgentMarket):
|
|
411
410
|
def redeem_winnings(api_keys: APIKeys) -> None:
|
412
411
|
redeem_from_all_user_positions(api_keys)
|
413
412
|
|
413
|
+
def ensure_min_native_balance(
|
414
|
+
self,
|
415
|
+
min_required_balance: xDai,
|
416
|
+
multiplier: float = 3.0,
|
417
|
+
) -> None:
|
418
|
+
"""
|
419
|
+
Ensure the EOA has at least the minimum required native token balance.
|
420
|
+
If not, transfer wrapped native tokens from the betting address and unwrap them.
|
421
|
+
|
422
|
+
Args:
|
423
|
+
min_required_balance: Minimum required native token balance to maintain
|
424
|
+
multiplier: Multiplier to apply to the required balance to keep as a buffer
|
425
|
+
"""
|
426
|
+
|
427
|
+
send_keeping_token_to_eoa_xdai(
|
428
|
+
api_keys=APIKeys(),
|
429
|
+
min_required_balance=min_required_balance,
|
430
|
+
multiplier=multiplier,
|
431
|
+
)
|
432
|
+
|
414
433
|
@staticmethod
|
415
434
|
def get_trade_balance(api_keys: APIKeys, web3: Web3 | None = None) -> USD:
|
416
435
|
native_usd = get_xdai_in_usd(
|
@@ -438,7 +457,7 @@ class OmenAgentMarket(AgentMarket):
|
|
438
457
|
|
439
458
|
def store_trades(
|
440
459
|
self,
|
441
|
-
traded_market:
|
460
|
+
traded_market: ProcessedMarket | None,
|
442
461
|
keys: APIKeys,
|
443
462
|
agent_name: str,
|
444
463
|
web3: Web3 | None = None,
|
@@ -653,10 +672,6 @@ class OmenAgentMarket(AgentMarket):
|
|
653
672
|
def get_user_balance(user_id: str) -> float:
|
654
673
|
return float(get_balances(Web3.to_checksum_address(user_id)).total)
|
655
674
|
|
656
|
-
@staticmethod
|
657
|
-
def get_user_id(api_keys: APIKeys) -> str:
|
658
|
-
return api_keys.bet_from_address
|
659
|
-
|
660
675
|
def get_most_recent_trade_datetime(self, user_id: str) -> DatetimeUTC | None:
|
661
676
|
sgh = OmenSubgraphHandler()
|
662
677
|
trades = sgh.get_trades(
|
@@ -734,7 +749,7 @@ def omen_buy_outcome_tx(
|
|
734
749
|
web3=web3,
|
735
750
|
)
|
736
751
|
|
737
|
-
return tx_receipt["transactionHash"].
|
752
|
+
return tx_receipt["transactionHash"].to_0x_hex()
|
738
753
|
|
739
754
|
|
740
755
|
def binary_omen_buy_outcome_tx(
|
@@ -828,7 +843,7 @@ def omen_sell_outcome_tx(
|
|
828
843
|
web3=web3,
|
829
844
|
)
|
830
845
|
|
831
|
-
return tx_receipt["transactionHash"].
|
846
|
+
return tx_receipt["transactionHash"].to_0x_hex()
|
832
847
|
|
833
848
|
|
834
849
|
def binary_omen_sell_outcome_tx(
|
@@ -1076,7 +1091,7 @@ def get_conditional_tokens_balance_for_market(
|
|
1076
1091
|
"""
|
1077
1092
|
balance_per_index_set: dict[int, OutcomeWei] = {}
|
1078
1093
|
conditional_token_contract = OmenConditionalTokenContract()
|
1079
|
-
parent_collection_id =
|
1094
|
+
parent_collection_id = HASH_ZERO
|
1080
1095
|
|
1081
1096
|
for index_set in market.condition.index_sets:
|
1082
1097
|
collection_id = conditional_token_contract.getCollectionId(
|
@@ -5,7 +5,6 @@ from datetime import timedelta
|
|
5
5
|
from enum import Enum
|
6
6
|
|
7
7
|
from web3 import Web3
|
8
|
-
from web3.constants import HASH_ZERO
|
9
8
|
|
10
9
|
from prediction_market_agent_tooling.config import APIKeys
|
11
10
|
from prediction_market_agent_tooling.gtypes import (
|
@@ -13,7 +12,6 @@ from prediction_market_agent_tooling.gtypes import (
|
|
13
12
|
ChecksumAddress,
|
14
13
|
HexAddress,
|
15
14
|
HexBytes,
|
16
|
-
HexStr,
|
17
15
|
IPFSCIDVersion0,
|
18
16
|
OutcomeWei,
|
19
17
|
TxParams,
|
@@ -24,11 +22,9 @@ from prediction_market_agent_tooling.gtypes import (
|
|
24
22
|
)
|
25
23
|
from prediction_market_agent_tooling.markets.omen.data_models import (
|
26
24
|
INVALID_ANSWER_HEX_BYTES,
|
27
|
-
ConditionPreparationEvent,
|
28
25
|
ContractPrediction,
|
29
26
|
FPMMFundingAddedEvent,
|
30
27
|
OmenFixedProductMarketMakerCreationEvent,
|
31
|
-
PayoutRedemptionEvent,
|
32
28
|
RealitioLogNewQuestionEvent,
|
33
29
|
format_realitio_question,
|
34
30
|
)
|
@@ -38,6 +34,7 @@ from prediction_market_agent_tooling.markets.omen.omen_constants import (
|
|
38
34
|
WRAPPED_XDAI_CONTRACT_ADDRESS,
|
39
35
|
)
|
40
36
|
from prediction_market_agent_tooling.tools.contract import (
|
37
|
+
ConditionalTokenContract,
|
41
38
|
ContractDepositableWrapperERC20OnGnosisChain,
|
42
39
|
ContractERC20OnGnosisChain,
|
43
40
|
ContractERC4626OnGnosisChain,
|
@@ -96,202 +93,11 @@ class OmenOracleContract(ContractOnGnosisChain):
|
|
96
93
|
)
|
97
94
|
|
98
95
|
|
99
|
-
|
100
|
-
return HASH_ZERO # Taken from Olas
|
101
|
-
|
102
|
-
|
103
|
-
class OmenConditionalTokenContract(ContractOnGnosisChain):
|
104
|
-
# Contract ABI taken from https://gnosisscan.io/address/0xCeAfDD6bc0bEF976fdCd1112955828E00543c0Ce#code.
|
105
|
-
abi: ABI = abi_field_validator(
|
106
|
-
os.path.join(
|
107
|
-
os.path.dirname(os.path.realpath(__file__)),
|
108
|
-
"../../abis/omen_fpmm_conditionaltokens.abi.json",
|
109
|
-
)
|
110
|
-
)
|
96
|
+
class OmenConditionalTokenContract(ConditionalTokenContract, ContractOnGnosisChain):
|
111
97
|
address: ChecksumAddress = Web3.to_checksum_address(
|
112
98
|
"0xCeAfDD6bc0bEF976fdCd1112955828E00543c0Ce"
|
113
99
|
)
|
114
100
|
|
115
|
-
def getConditionId(
|
116
|
-
self,
|
117
|
-
question_id: HexBytes,
|
118
|
-
oracle_address: ChecksumAddress,
|
119
|
-
outcomes_slot_count: int,
|
120
|
-
web3: Web3 | None = None,
|
121
|
-
) -> HexBytes:
|
122
|
-
id_ = HexBytes(
|
123
|
-
self.call(
|
124
|
-
"getConditionId",
|
125
|
-
[oracle_address, question_id, outcomes_slot_count],
|
126
|
-
web3=web3,
|
127
|
-
)
|
128
|
-
)
|
129
|
-
return id_
|
130
|
-
|
131
|
-
def balanceOf(
|
132
|
-
self, from_address: ChecksumAddress, position_id: int, web3: Web3 | None = None
|
133
|
-
) -> OutcomeWei:
|
134
|
-
balance = OutcomeWei(
|
135
|
-
self.call("balanceOf", [from_address, position_id], web3=web3)
|
136
|
-
)
|
137
|
-
return balance
|
138
|
-
|
139
|
-
def getCollectionId(
|
140
|
-
self,
|
141
|
-
parent_collection_id: HexStr,
|
142
|
-
condition_id: HexBytes,
|
143
|
-
index_set: int,
|
144
|
-
web3: Web3 | None = None,
|
145
|
-
) -> HexBytes:
|
146
|
-
collection_id = HexBytes(
|
147
|
-
self.call(
|
148
|
-
"getCollectionId",
|
149
|
-
[parent_collection_id, condition_id, index_set],
|
150
|
-
web3=web3,
|
151
|
-
)
|
152
|
-
)
|
153
|
-
return collection_id
|
154
|
-
|
155
|
-
def getPositionId(
|
156
|
-
self,
|
157
|
-
collateral_token_address: ChecksumAddress,
|
158
|
-
collection_id: HexBytes,
|
159
|
-
web3: Web3 | None = None,
|
160
|
-
) -> int:
|
161
|
-
position_id: int = self.call(
|
162
|
-
"getPositionId",
|
163
|
-
[collateral_token_address, collection_id],
|
164
|
-
web3=web3,
|
165
|
-
)
|
166
|
-
return position_id
|
167
|
-
|
168
|
-
def mergePositions(
|
169
|
-
self,
|
170
|
-
api_keys: APIKeys,
|
171
|
-
collateral_token_address: ChecksumAddress,
|
172
|
-
conditionId: HexBytes,
|
173
|
-
index_sets: t.List[int],
|
174
|
-
amount: OutcomeWei,
|
175
|
-
parent_collection_id: HexStr = build_parent_collection_id(),
|
176
|
-
web3: Web3 | None = None,
|
177
|
-
) -> TxReceipt:
|
178
|
-
return self.send(
|
179
|
-
api_keys=api_keys,
|
180
|
-
function_name="mergePositions",
|
181
|
-
function_params=[
|
182
|
-
collateral_token_address,
|
183
|
-
parent_collection_id,
|
184
|
-
conditionId,
|
185
|
-
index_sets,
|
186
|
-
amount,
|
187
|
-
],
|
188
|
-
web3=web3,
|
189
|
-
)
|
190
|
-
|
191
|
-
def redeemPositions(
|
192
|
-
self,
|
193
|
-
api_keys: APIKeys,
|
194
|
-
collateral_token_address: HexAddress,
|
195
|
-
condition_id: HexBytes,
|
196
|
-
index_sets: t.List[int],
|
197
|
-
parent_collection_id: HexStr = build_parent_collection_id(),
|
198
|
-
web3: Web3 | None = None,
|
199
|
-
) -> PayoutRedemptionEvent:
|
200
|
-
receipt_tx = self.send(
|
201
|
-
api_keys=api_keys,
|
202
|
-
function_name="redeemPositions",
|
203
|
-
function_params=[
|
204
|
-
collateral_token_address,
|
205
|
-
parent_collection_id,
|
206
|
-
condition_id,
|
207
|
-
index_sets,
|
208
|
-
],
|
209
|
-
web3=web3,
|
210
|
-
)
|
211
|
-
redeem_event_logs = (
|
212
|
-
self.get_web3_contract(web3=web3)
|
213
|
-
.events.PayoutRedemption()
|
214
|
-
.process_receipt(receipt_tx)
|
215
|
-
)
|
216
|
-
redeem_event = PayoutRedemptionEvent(**redeem_event_logs[0]["args"])
|
217
|
-
return redeem_event
|
218
|
-
|
219
|
-
def getOutcomeSlotCount(
|
220
|
-
self, condition_id: HexBytes, web3: Web3 | None = None
|
221
|
-
) -> int:
|
222
|
-
count: int = self.call("getOutcomeSlotCount", [condition_id], web3=web3)
|
223
|
-
return count
|
224
|
-
|
225
|
-
def does_condition_exists(
|
226
|
-
self, condition_id: HexBytes, web3: Web3 | None = None
|
227
|
-
) -> bool:
|
228
|
-
return self.getOutcomeSlotCount(condition_id, web3=web3) > 0
|
229
|
-
|
230
|
-
def is_condition_resolved(
|
231
|
-
self, condition_id: HexBytes, web3: Web3 | None = None
|
232
|
-
) -> bool:
|
233
|
-
# from ConditionalTokens.redeemPositions:
|
234
|
-
# uint den = payoutDenominator[conditionId]; require(den > 0, "result for condition not received yet");
|
235
|
-
payout_for_condition = self.payoutDenominator(condition_id, web3=web3)
|
236
|
-
return payout_for_condition > 0
|
237
|
-
|
238
|
-
def payoutDenominator(
|
239
|
-
self, condition_id: HexBytes, web3: Web3 | None = None
|
240
|
-
) -> int:
|
241
|
-
payoutForCondition: int = self.call(
|
242
|
-
"payoutDenominator", [condition_id], web3=web3
|
243
|
-
)
|
244
|
-
return payoutForCondition
|
245
|
-
|
246
|
-
def setApprovalForAll(
|
247
|
-
self,
|
248
|
-
api_keys: APIKeys,
|
249
|
-
for_address: ChecksumAddress,
|
250
|
-
approve: bool,
|
251
|
-
tx_params: t.Optional[TxParams] = None,
|
252
|
-
web3: Web3 | None = None,
|
253
|
-
) -> TxReceipt:
|
254
|
-
return self.send(
|
255
|
-
api_keys=api_keys,
|
256
|
-
function_name="setApprovalForAll",
|
257
|
-
function_params=[
|
258
|
-
for_address,
|
259
|
-
approve,
|
260
|
-
],
|
261
|
-
tx_params=tx_params,
|
262
|
-
web3=web3,
|
263
|
-
)
|
264
|
-
|
265
|
-
def prepareCondition(
|
266
|
-
self,
|
267
|
-
api_keys: APIKeys,
|
268
|
-
oracle_address: ChecksumAddress,
|
269
|
-
question_id: HexBytes,
|
270
|
-
outcomes_slot_count: int,
|
271
|
-
tx_params: t.Optional[TxParams] = None,
|
272
|
-
web3: Web3 | None = None,
|
273
|
-
) -> ConditionPreparationEvent:
|
274
|
-
receipt_tx = self.send(
|
275
|
-
api_keys=api_keys,
|
276
|
-
function_name="prepareCondition",
|
277
|
-
function_params=[
|
278
|
-
oracle_address,
|
279
|
-
question_id,
|
280
|
-
outcomes_slot_count,
|
281
|
-
],
|
282
|
-
tx_params=tx_params,
|
283
|
-
web3=web3,
|
284
|
-
)
|
285
|
-
|
286
|
-
event_logs = (
|
287
|
-
self.get_web3_contract(web3=web3)
|
288
|
-
.events.ConditionPreparation()
|
289
|
-
.process_receipt(receipt_tx)
|
290
|
-
)
|
291
|
-
cond_event = ConditionPreparationEvent(**event_logs[0]["args"])
|
292
|
-
|
293
|
-
return cond_event
|
294
|
-
|
295
101
|
|
296
102
|
class OmenFixedProductMarketMakerContract(ContractOnGnosisChain):
|
297
103
|
# File content taken from https://github.com/protofire/omen-exchange/blob/master/app/src/abi/marketMaker.json.
|
@@ -85,10 +85,10 @@ def claim_bonds_on_realitio_question(
|
|
85
85
|
responses = sorted(responses, key=lambda x: x.timestamp)
|
86
86
|
|
87
87
|
if not responses:
|
88
|
-
raise ValueError(f"No answers found for {question.questionId.
|
88
|
+
raise ValueError(f"No answers found for {question.questionId.to_0x_hex()=}")
|
89
89
|
|
90
90
|
if responses[-1].question.historyHash == ZERO_BYTES:
|
91
|
-
raise ValueError(f"Already claimed {question.questionId.
|
91
|
+
raise ValueError(f"Already claimed {question.questionId.to_0x_hex()=}.")
|
92
92
|
|
93
93
|
history_hashes: list[HexBytes] = []
|
94
94
|
addresses: list[ChecksumAddress] = []
|
@@ -285,7 +285,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
285
285
|
where_stms["liquidityParameter_gt"] = liquidity_bigger_than
|
286
286
|
|
287
287
|
if condition_id_in is not None:
|
288
|
-
where_stms["condition_"]["id_in"] = [x.
|
288
|
+
where_stms["condition_"]["id_in"] = [x.to_0x_hex() for x in condition_id_in]
|
289
289
|
|
290
290
|
if id_in is not None:
|
291
291
|
where_stms["id_in"] = [i.lower() for i in id_in]
|
@@ -513,7 +513,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
513
513
|
where_stms: dict[str, t.Any] = {}
|
514
514
|
|
515
515
|
if condition_id is not None:
|
516
|
-
where_stms["conditionIds_contains"] = [condition_id.
|
516
|
+
where_stms["conditionIds_contains"] = [condition_id.to_0x_hex()]
|
517
517
|
|
518
518
|
positions = self.conditional_tokens_subgraph.Query.positions(
|
519
519
|
first=sys.maxsize, where=unwrap_generic_value(where_stms)
|
@@ -541,10 +541,12 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
541
541
|
where_stms["totalBalance_gt"] = total_balance_bigger_than
|
542
542
|
|
543
543
|
if user_position_id_in is not None:
|
544
|
-
where_stms["id_in"] = [x.
|
544
|
+
where_stms["id_in"] = [x.to_0x_hex() for x in user_position_id_in]
|
545
545
|
|
546
546
|
if position_id_in is not None:
|
547
|
-
where_stms["position_"]["positionId_in"] = [
|
547
|
+
where_stms["position_"]["positionId_in"] = [
|
548
|
+
x.to_0x_hex() for x in position_id_in
|
549
|
+
]
|
548
550
|
|
549
551
|
positions = self.conditional_tokens_subgraph.Query.userPositions(
|
550
552
|
first=sys.maxsize, where=unwrap_generic_value(where_stms)
|
@@ -710,13 +712,13 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
710
712
|
where_stms["user"] = user.lower()
|
711
713
|
|
712
714
|
if question_id is not None:
|
713
|
-
where_stms["questionId"] = question_id.
|
715
|
+
where_stms["questionId"] = question_id.to_0x_hex()
|
714
716
|
|
715
717
|
if claimed is not None:
|
716
718
|
if claimed:
|
717
|
-
where_stms["historyHash"] = ZERO_BYTES.
|
719
|
+
where_stms["historyHash"] = ZERO_BYTES.to_0x_hex()
|
718
720
|
else:
|
719
|
-
where_stms["historyHash_not"] = ZERO_BYTES.
|
721
|
+
where_stms["historyHash_not"] = ZERO_BYTES.to_0x_hex()
|
720
722
|
|
721
723
|
if current_answer_before is not None:
|
722
724
|
where_stms["currentAnswerTimestamp_lt"] = to_int_timestamp(
|
@@ -750,7 +752,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
750
752
|
|
751
753
|
if question_id_in is not None:
|
752
754
|
# Be aware: On Omen subgraph, question's `id` represents `questionId` on reality subgraph. And `id` on reality subraph is just a weird concat of multiple things from the question.
|
753
|
-
where_stms["questionId_in"] = [x.
|
755
|
+
where_stms["questionId_in"] = [x.to_0x_hex() for x in question_id_in]
|
754
756
|
|
755
757
|
if excluded_titles:
|
756
758
|
# Be aware: This is called `title_not_in` on Omen subgraph.
|
@@ -777,7 +779,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
777
779
|
where_stms: dict[str, t.Any] = {}
|
778
780
|
|
779
781
|
if question_id is not None:
|
780
|
-
where_stms["id"] = question_id.
|
782
|
+
where_stms["id"] = question_id.to_0x_hex()
|
781
783
|
|
782
784
|
if current_answer_before is not None:
|
783
785
|
where_stms["currentAnswerTimestamp_lt"] = to_int_timestamp(
|
@@ -811,7 +813,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
811
813
|
|
812
814
|
if question_id_in is not None:
|
813
815
|
# Be aware: On Omen subgraph, question's `id` represents `questionId` on reality subgraph. And `id` on reality subraph is just a weird concat of multiple things from the question.
|
814
|
-
where_stms["id_in"] = [x.
|
816
|
+
where_stms["id_in"] = [x.to_0x_hex() for x in question_id_in]
|
815
817
|
|
816
818
|
if excluded_titles:
|
817
819
|
# Be aware: This is called `qTitle_not_in` on Omen subgraph.
|
@@ -864,7 +866,7 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
864
866
|
answer = self.realityeth_subgraph.Answer
|
865
867
|
# subgrounds complains if bytes is passed, hence we convert it to HexStr
|
866
868
|
where_stms = [
|
867
|
-
answer.question.questionId == question_id.
|
869
|
+
answer.question.questionId == question_id.to_0x_hex(),
|
868
870
|
]
|
869
871
|
|
870
872
|
answers = self.realityeth_subgraph.Query.answers(
|