prediction-market-agent-tooling 0.68.0.dev999__py3-none-any.whl → 0.68.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/chains.py +1 -0
- prediction_market_agent_tooling/config.py +37 -2
- prediction_market_agent_tooling/deploy/agent.py +13 -19
- prediction_market_agent_tooling/deploy/betting_strategy.py +11 -3
- prediction_market_agent_tooling/jobs/jobs_models.py +2 -2
- prediction_market_agent_tooling/jobs/omen/omen_jobs.py +3 -3
- prediction_market_agent_tooling/markets/agent_market.py +16 -9
- prediction_market_agent_tooling/markets/blockchain_utils.py +3 -3
- 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 +1 -1
- prediction_market_agent_tooling/markets/seer/price_manager.py +69 -1
- prediction_market_agent_tooling/markets/seer/seer.py +35 -20
- prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +7 -3
- prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +2 -0
- 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/hexbytes_custom.py +3 -9
- prediction_market_agent_tooling/tools/tokens/auto_deposit.py +1 -1
- 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.68.1.dist-info}/METADATA +8 -7
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.68.1.dist-info}/RECORD +36 -34
- 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.68.1.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.68.1.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.68.0.dev999.dist-info → prediction_market_agent_tooling-0.68.1.dist-info}/entry_points.txt +0 -0
@@ -155,7 +155,7 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
|
|
155
155
|
raise ValueError(f"Unknown filter {filter_by}")
|
156
156
|
|
157
157
|
if parent_market_id:
|
158
|
-
and_stms["parentMarket"] = parent_market_id.
|
158
|
+
and_stms["parentMarket"] = parent_market_id.to_0x_hex().lower()
|
159
159
|
|
160
160
|
outcome_filters: list[dict[str, t.Any]] = []
|
161
161
|
|
@@ -294,7 +294,7 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
|
|
294
294
|
self, market_ids: list[HexBytes]
|
295
295
|
) -> list[SeerMarketQuestions]:
|
296
296
|
where = unwrap_generic_value(
|
297
|
-
{"market_in": [market_id.
|
297
|
+
{"market_in": [market_id.to_0x_hex().lower() for market_id in market_ids]}
|
298
298
|
)
|
299
299
|
markets_field = self.seer_subgraph.Query.marketQuestions(where=where)
|
300
300
|
fields = self._get_fields_for_questions(markets_field)
|
@@ -302,7 +302,9 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
|
|
302
302
|
return questions
|
303
303
|
|
304
304
|
def get_market_by_id(self, market_id: HexBytes) -> SeerMarketWithQuestions:
|
305
|
-
markets_field = self.seer_subgraph.Query.market(
|
305
|
+
markets_field = self.seer_subgraph.Query.market(
|
306
|
+
id=market_id.to_0x_hex().lower()
|
307
|
+
)
|
306
308
|
fields = self._get_fields_for_markets(markets_field)
|
307
309
|
markets = self.do_query(fields=fields, pydantic_model=SeerMarket)
|
308
310
|
if len(markets) != 1:
|
@@ -352,6 +354,8 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
|
|
352
354
|
pools_field.token1.id,
|
353
355
|
pools_field.token1.name,
|
354
356
|
pools_field.token1.symbol,
|
357
|
+
pools_field.totalValueLockedToken0,
|
358
|
+
pools_field.totalValueLockedToken1,
|
355
359
|
]
|
356
360
|
return fields
|
357
361
|
|
@@ -8,16 +8,21 @@ import eth_abi
|
|
8
8
|
from eth_abi.exceptions import DecodingError
|
9
9
|
from pydantic import BaseModel, field_validator
|
10
10
|
from web3 import Web3
|
11
|
-
from web3.constants import CHECKSUM_ADDRESSS_ZERO
|
11
|
+
from web3.constants import CHECKSUM_ADDRESSS_ZERO, HASH_ZERO
|
12
12
|
from web3.contract.contract import Contract as Web3Contract
|
13
13
|
|
14
|
+
from prediction_market_agent_tooling.chains import POLYGON_CHAIN_ID
|
14
15
|
from prediction_market_agent_tooling.config import APIKeys, RPCConfig
|
15
16
|
from prediction_market_agent_tooling.gtypes import (
|
16
17
|
ABI,
|
17
18
|
ChainID,
|
18
19
|
ChecksumAddress,
|
19
20
|
CollateralToken,
|
21
|
+
HexAddress,
|
22
|
+
HexBytes,
|
23
|
+
HexStr,
|
20
24
|
Nonce,
|
25
|
+
OutcomeWei,
|
21
26
|
TxParams,
|
22
27
|
TxReceipt,
|
23
28
|
Wei,
|
@@ -516,9 +521,19 @@ class ContractOnGnosisChain(ContractBaseClass):
|
|
516
521
|
Contract base class with Gnosis Chain configuration.
|
517
522
|
"""
|
518
523
|
|
524
|
+
# This is defined like so because other chains (like Ethereum) rely on contracts that inherit
|
525
|
+
# from ContractOnGnosisChain. To be re-evaluated on https://github.com/gnosis/prediction-market-agent-tooling/issues/845
|
519
526
|
CHAIN_ID = RPCConfig().chain_id
|
520
527
|
|
521
528
|
|
529
|
+
class ContractOnPolygonChain(ContractBaseClass):
|
530
|
+
"""
|
531
|
+
Contract base class with Gnosis Chain configuration.
|
532
|
+
"""
|
533
|
+
|
534
|
+
CHAIN_ID = POLYGON_CHAIN_ID
|
535
|
+
|
536
|
+
|
522
537
|
class ContractProxyOnGnosisChain(ContractProxyBaseClass, ContractOnGnosisChain):
|
523
538
|
"""
|
524
539
|
Proxy contract base class with Gnosis Chain configuration.
|
@@ -566,6 +581,223 @@ class ContractERC4626OnGnosisChain(
|
|
566
581
|
return to_gnosis_chain_contract(super().get_asset_token_contract(web3=web3))
|
567
582
|
|
568
583
|
|
584
|
+
class PayoutRedemptionEvent(BaseModel):
|
585
|
+
redeemer: HexAddress
|
586
|
+
collateralToken: HexAddress
|
587
|
+
parentCollectionId: HexBytes
|
588
|
+
conditionId: HexBytes
|
589
|
+
indexSets: list[int]
|
590
|
+
payout: Wei
|
591
|
+
|
592
|
+
|
593
|
+
class ConditionPreparationEvent(BaseModel):
|
594
|
+
conditionId: HexBytes
|
595
|
+
oracle: HexAddress
|
596
|
+
questionId: HexBytes
|
597
|
+
outcomeSlotCount: int
|
598
|
+
|
599
|
+
|
600
|
+
class ConditionalTokenContract(ContractBaseClass):
|
601
|
+
# Contract ABI taken from https://gnosisscan.io/address/0xCeAfDD6bc0bEF976fdCd1112955828E00543c0Ce#code.
|
602
|
+
abi: ABI = abi_field_validator(
|
603
|
+
os.path.join(
|
604
|
+
os.path.dirname(os.path.realpath(__file__)),
|
605
|
+
"../abis/omen_fpmm_conditionaltokens.abi.json",
|
606
|
+
)
|
607
|
+
)
|
608
|
+
|
609
|
+
def getConditionId(
|
610
|
+
self,
|
611
|
+
question_id: HexBytes,
|
612
|
+
oracle_address: ChecksumAddress,
|
613
|
+
outcomes_slot_count: int,
|
614
|
+
web3: Web3 | None = None,
|
615
|
+
) -> HexBytes:
|
616
|
+
id_ = HexBytes(
|
617
|
+
self.call(
|
618
|
+
"getConditionId",
|
619
|
+
[oracle_address, question_id, outcomes_slot_count],
|
620
|
+
web3=web3,
|
621
|
+
)
|
622
|
+
)
|
623
|
+
return id_
|
624
|
+
|
625
|
+
def balanceOf(
|
626
|
+
self, from_address: ChecksumAddress, position_id: int, web3: Web3 | None = None
|
627
|
+
) -> OutcomeWei:
|
628
|
+
balance = OutcomeWei(
|
629
|
+
self.call("balanceOf", [from_address, position_id], web3=web3)
|
630
|
+
)
|
631
|
+
return balance
|
632
|
+
|
633
|
+
def isApprovedForAll(
|
634
|
+
self,
|
635
|
+
owner: ChecksumAddress,
|
636
|
+
for_address: ChecksumAddress,
|
637
|
+
web3: Web3 | None = None,
|
638
|
+
) -> bool:
|
639
|
+
is_approved: bool = self.call(
|
640
|
+
"isApprovedForAll", [owner, for_address], web3=web3
|
641
|
+
)
|
642
|
+
return is_approved
|
643
|
+
|
644
|
+
def getCollectionId(
|
645
|
+
self,
|
646
|
+
parent_collection_id: HexStr,
|
647
|
+
condition_id: HexBytes,
|
648
|
+
index_set: int,
|
649
|
+
web3: Web3 | None = None,
|
650
|
+
) -> HexBytes:
|
651
|
+
collection_id = HexBytes(
|
652
|
+
self.call(
|
653
|
+
"getCollectionId",
|
654
|
+
[parent_collection_id, condition_id, index_set],
|
655
|
+
web3=web3,
|
656
|
+
)
|
657
|
+
)
|
658
|
+
return collection_id
|
659
|
+
|
660
|
+
def getPositionId(
|
661
|
+
self,
|
662
|
+
collateral_token_address: ChecksumAddress,
|
663
|
+
collection_id: HexBytes,
|
664
|
+
web3: Web3 | None = None,
|
665
|
+
) -> int:
|
666
|
+
position_id: int = self.call(
|
667
|
+
"getPositionId",
|
668
|
+
[collateral_token_address, collection_id],
|
669
|
+
web3=web3,
|
670
|
+
)
|
671
|
+
return position_id
|
672
|
+
|
673
|
+
def mergePositions(
|
674
|
+
self,
|
675
|
+
api_keys: APIKeys,
|
676
|
+
collateral_token_address: ChecksumAddress,
|
677
|
+
conditionId: HexBytes,
|
678
|
+
index_sets: t.List[int],
|
679
|
+
amount: OutcomeWei,
|
680
|
+
parent_collection_id: HexStr = HASH_ZERO,
|
681
|
+
web3: Web3 | None = None,
|
682
|
+
) -> TxReceipt:
|
683
|
+
return self.send(
|
684
|
+
api_keys=api_keys,
|
685
|
+
function_name="mergePositions",
|
686
|
+
function_params=[
|
687
|
+
collateral_token_address,
|
688
|
+
parent_collection_id,
|
689
|
+
conditionId,
|
690
|
+
index_sets,
|
691
|
+
amount,
|
692
|
+
],
|
693
|
+
web3=web3,
|
694
|
+
)
|
695
|
+
|
696
|
+
def redeemPositions(
|
697
|
+
self,
|
698
|
+
api_keys: APIKeys,
|
699
|
+
collateral_token_address: HexAddress,
|
700
|
+
condition_id: HexBytes,
|
701
|
+
index_sets: t.List[int],
|
702
|
+
parent_collection_id: HexStr = HASH_ZERO,
|
703
|
+
web3: Web3 | None = None,
|
704
|
+
) -> PayoutRedemptionEvent:
|
705
|
+
receipt_tx = self.send(
|
706
|
+
api_keys=api_keys,
|
707
|
+
function_name="redeemPositions",
|
708
|
+
function_params=[
|
709
|
+
collateral_token_address,
|
710
|
+
parent_collection_id,
|
711
|
+
condition_id,
|
712
|
+
index_sets,
|
713
|
+
],
|
714
|
+
web3=web3,
|
715
|
+
)
|
716
|
+
redeem_event_logs = (
|
717
|
+
self.get_web3_contract(web3=web3)
|
718
|
+
.events.PayoutRedemption()
|
719
|
+
.process_receipt(receipt_tx)
|
720
|
+
)
|
721
|
+
redeem_event = PayoutRedemptionEvent(**redeem_event_logs[0]["args"])
|
722
|
+
return redeem_event
|
723
|
+
|
724
|
+
def getOutcomeSlotCount(
|
725
|
+
self, condition_id: HexBytes, web3: Web3 | None = None
|
726
|
+
) -> int:
|
727
|
+
count: int = self.call("getOutcomeSlotCount", [condition_id], web3=web3)
|
728
|
+
return count
|
729
|
+
|
730
|
+
def does_condition_exists(
|
731
|
+
self, condition_id: HexBytes, web3: Web3 | None = None
|
732
|
+
) -> bool:
|
733
|
+
return self.getOutcomeSlotCount(condition_id, web3=web3) > 0
|
734
|
+
|
735
|
+
def is_condition_resolved(
|
736
|
+
self, condition_id: HexBytes, web3: Web3 | None = None
|
737
|
+
) -> bool:
|
738
|
+
# from ConditionalTokens.redeemPositions:
|
739
|
+
# uint den = payoutDenominator[conditionId]; require(den > 0, "result for condition not received yet");
|
740
|
+
payout_for_condition = self.payoutDenominator(condition_id, web3=web3)
|
741
|
+
return payout_for_condition > 0
|
742
|
+
|
743
|
+
def payoutDenominator(
|
744
|
+
self, condition_id: HexBytes, web3: Web3 | None = None
|
745
|
+
) -> int:
|
746
|
+
payoutForCondition: int = self.call(
|
747
|
+
"payoutDenominator", [condition_id], web3=web3
|
748
|
+
)
|
749
|
+
return payoutForCondition
|
750
|
+
|
751
|
+
def setApprovalForAll(
|
752
|
+
self,
|
753
|
+
api_keys: APIKeys,
|
754
|
+
for_address: ChecksumAddress,
|
755
|
+
approve: bool,
|
756
|
+
tx_params: t.Optional[TxParams] = None,
|
757
|
+
web3: Web3 | None = None,
|
758
|
+
) -> TxReceipt:
|
759
|
+
return self.send(
|
760
|
+
api_keys=api_keys,
|
761
|
+
function_name="setApprovalForAll",
|
762
|
+
function_params=[
|
763
|
+
for_address,
|
764
|
+
approve,
|
765
|
+
],
|
766
|
+
tx_params=tx_params,
|
767
|
+
web3=web3,
|
768
|
+
)
|
769
|
+
|
770
|
+
def prepareCondition(
|
771
|
+
self,
|
772
|
+
api_keys: APIKeys,
|
773
|
+
oracle_address: ChecksumAddress,
|
774
|
+
question_id: HexBytes,
|
775
|
+
outcomes_slot_count: int,
|
776
|
+
tx_params: t.Optional[TxParams] = None,
|
777
|
+
web3: Web3 | None = None,
|
778
|
+
) -> ConditionPreparationEvent:
|
779
|
+
receipt_tx = self.send(
|
780
|
+
api_keys=api_keys,
|
781
|
+
function_name="prepareCondition",
|
782
|
+
function_params=[
|
783
|
+
oracle_address,
|
784
|
+
question_id,
|
785
|
+
outcomes_slot_count,
|
786
|
+
],
|
787
|
+
tx_params=tx_params,
|
788
|
+
web3=web3,
|
789
|
+
)
|
790
|
+
|
791
|
+
event_logs = (
|
792
|
+
self.get_web3_contract(web3=web3)
|
793
|
+
.events.ConditionPreparation()
|
794
|
+
.process_receipt(receipt_tx)
|
795
|
+
)
|
796
|
+
cond_event = ConditionPreparationEvent(**event_logs[0]["args"])
|
797
|
+
|
798
|
+
return cond_event
|
799
|
+
|
800
|
+
|
569
801
|
class DebuggingContract(ContractOnGnosisChain):
|
570
802
|
# Contract ABI taken from https://gnosisscan.io/address/0x5Aa82E068aE6a6a1C26c42E5a59520a74Cdb8998#code.
|
571
803
|
abi: ABI = abi_field_validator(
|
@@ -614,12 +846,12 @@ def contract_implements_function(
|
|
614
846
|
look_for_proxy_contract: bool = True,
|
615
847
|
) -> bool:
|
616
848
|
function_signature = f"{function_name}({','.join(function_arg_types or [])})"
|
617
|
-
function_selector = web3.keccak(text=function_signature)[0:4].
|
849
|
+
function_selector = web3.keccak(text=function_signature)[0:4].to_0x_hex()[2:]
|
618
850
|
# 1. Check directly in bytecode
|
619
|
-
bytecode = web3.eth.get_code(contract_address).
|
851
|
+
bytecode = web3.eth.get_code(contract_address).to_0x_hex()
|
620
852
|
if function_selector in bytecode:
|
621
853
|
return True
|
622
|
-
contract_code = web3.eth.get_code(contract_address).
|
854
|
+
contract_code = web3.eth.get_code(contract_address).to_0x_hex()
|
623
855
|
implements = function_selector in contract_code
|
624
856
|
|
625
857
|
# If not found directly and we should check proxies
|
@@ -48,7 +48,7 @@ from prediction_market_agent_tooling.loggers import logger
|
|
48
48
|
from prediction_market_agent_tooling.markets.omen.cow_contracts import (
|
49
49
|
CowGPv2SettlementContract,
|
50
50
|
)
|
51
|
-
from prediction_market_agent_tooling.tools.contract import
|
51
|
+
from prediction_market_agent_tooling.tools.contract import ContractERC20BaseClass
|
52
52
|
from prediction_market_agent_tooling.tools.cow.models import MinimalisticTrade, Order
|
53
53
|
from prediction_market_agent_tooling.tools.cow.semaphore import postgres_rate_limited
|
54
54
|
from prediction_market_agent_tooling.tools.utils import utcnow
|
@@ -166,7 +166,8 @@ def get_buy_token_amount_else_raise(
|
|
166
166
|
def handle_allowance(
|
167
167
|
api_keys: APIKeys,
|
168
168
|
sell_token: ChecksumAddress,
|
169
|
-
|
169
|
+
amount_to_check_wei: Wei,
|
170
|
+
amount_to_set_wei: Wei | None = None,
|
170
171
|
for_address: ChecksumAddress | None = None,
|
171
172
|
web3: Web3 | None = None,
|
172
173
|
) -> None:
|
@@ -174,16 +175,17 @@ def handle_allowance(
|
|
174
175
|
for_address = for_address or Web3.to_checksum_address(
|
175
176
|
CowContractAddress.VAULT_RELAYER.value
|
176
177
|
)
|
177
|
-
current_allowance =
|
178
|
+
current_allowance = ContractERC20BaseClass(address=sell_token).allowance(
|
178
179
|
owner=api_keys.bet_from_address,
|
179
180
|
for_address=for_address,
|
180
181
|
web3=web3,
|
181
182
|
)
|
182
|
-
if current_allowance <
|
183
|
-
|
183
|
+
if current_allowance < amount_to_check_wei:
|
184
|
+
amount_to_set_wei = amount_to_set_wei or amount_to_check_wei
|
185
|
+
ContractERC20BaseClass(address=sell_token).approve(
|
184
186
|
api_keys,
|
185
187
|
for_address=for_address,
|
186
|
-
amount_wei=
|
188
|
+
amount_wei=amount_to_set_wei,
|
187
189
|
web3=web3,
|
188
190
|
)
|
189
191
|
|
@@ -305,7 +307,10 @@ async def swap_tokens_waiting_async(
|
|
305
307
|
wait_order_complete: bool = True,
|
306
308
|
) -> tuple[OrderMetaData | None, CompletedOrder]:
|
307
309
|
handle_allowance(
|
308
|
-
api_keys=api_keys,
|
310
|
+
api_keys=api_keys,
|
311
|
+
sell_token=sell_token,
|
312
|
+
amount_to_check_wei=amount_wei,
|
313
|
+
web3=web3,
|
309
314
|
)
|
310
315
|
valid_to = (utcnow() + timeout).timestamp()
|
311
316
|
order = await place_swap_order(
|
@@ -375,7 +380,7 @@ def get_trades_by_order_uid(
|
|
375
380
|
# Using this until cowpy gets fixed (https://github.com/cowdao-grants/cow-py/issues/35)
|
376
381
|
response = httpx.get(
|
377
382
|
f"https://api.cow.fi/xdai/api/v1/trades",
|
378
|
-
params={"orderUid": order_uid.
|
383
|
+
params={"orderUid": order_uid.to_0x_hex()},
|
379
384
|
)
|
380
385
|
response.raise_for_status()
|
381
386
|
return [MinimalisticTrade.model_validate(i) for i in response.json()]
|
@@ -11,7 +11,7 @@ from pydantic_core.core_schema import (
|
|
11
11
|
with_info_before_validator_function,
|
12
12
|
)
|
13
13
|
|
14
|
-
hex_serializer = plain_serializer_function_ser_schema(function=lambda x: x.
|
14
|
+
hex_serializer = plain_serializer_function_ser_schema(function=lambda x: x.to_0x_hex())
|
15
15
|
|
16
16
|
|
17
17
|
class BaseHex:
|
@@ -60,14 +60,8 @@ class HexBytes(HexBytesBase, BaseHex):
|
|
60
60
|
value = hex_str[2:] if hex_str.startswith("0x") else hex_str
|
61
61
|
return super().fromhex(value)
|
62
62
|
|
63
|
-
def
|
64
|
-
self
|
65
|
-
sep: t.Union[str, bytes] | None = None,
|
66
|
-
bytes_per_sep: t.SupportsIndex = 1,
|
67
|
-
) -> str:
|
68
|
-
"""We enforce a 0x prefix."""
|
69
|
-
x = super().hex(sep, bytes_per_sep) # type: ignore[arg-type]
|
70
|
-
return x if x.startswith("0x") else "0x" + x
|
63
|
+
def __repr__(self) -> str:
|
64
|
+
return f'HexBytes("{self.to_0x_hex()}")'
|
71
65
|
|
72
66
|
@classmethod
|
73
67
|
def __eth_pydantic_validate__(
|
@@ -10,6 +10,9 @@ from prediction_market_agent_tooling.markets.omen.omen_constants import (
|
|
10
10
|
SDAI_CONTRACT_ADDRESS,
|
11
11
|
WRAPPED_XDAI_CONTRACT_ADDRESS,
|
12
12
|
)
|
13
|
+
from prediction_market_agent_tooling.markets.polymarket.polymarket_contracts import (
|
14
|
+
USDCeContract,
|
15
|
+
)
|
13
16
|
from prediction_market_agent_tooling.tools.contract import ContractERC4626OnGnosisChain
|
14
17
|
from prediction_market_agent_tooling.tools.cow.cow_order import (
|
15
18
|
get_buy_token_amount_else_raise,
|
@@ -39,8 +42,8 @@ def get_token_in_usd(amount: CollateralToken, token_address: ChecksumAddress) ->
|
|
39
42
|
# A short cache to not spam CoW and prevent timeouts, but still have relatively fresh data.
|
40
43
|
@cached(TTLCache(maxsize=100, ttl=5 * 60))
|
41
44
|
def get_single_token_to_usd_rate(token_address: ChecksumAddress) -> USD:
|
42
|
-
# (w)xDai
|
43
|
-
if WRAPPED_XDAI_CONTRACT_ADDRESS
|
45
|
+
# (w)xDai and USDC are stablecoins pegged to USD, so use it to estimate USD worth.
|
46
|
+
if token_address in [WRAPPED_XDAI_CONTRACT_ADDRESS, USDCeContract().address]:
|
44
47
|
return USD(1.0)
|
45
48
|
# sDai is ERC4626 with wxDai as asset, we can take the rate directly from there instead of calling CoW.
|
46
49
|
if SDAI_CONTRACT_ADDRESS == token_address:
|
@@ -9,6 +9,7 @@ from eth_typing import URI
|
|
9
9
|
from eth_utils.currency import MAX_WEI, MIN_WEI
|
10
10
|
from pydantic.types import SecretStr
|
11
11
|
from safe_eth.eth import EthereumClient
|
12
|
+
from safe_eth.eth.ethereum_client import TxSpeed
|
12
13
|
from safe_eth.safe.safe import SafeV141
|
13
14
|
from web3 import Web3
|
14
15
|
from web3.constants import HASH_ZERO
|
@@ -104,7 +105,9 @@ def call_function_on_contract(
|
|
104
105
|
function_params: Optional[list[Any] | dict[str, Any]] = None,
|
105
106
|
) -> Any:
|
106
107
|
contract = web3.eth.contract(address=contract_address, abi=contract_abi)
|
107
|
-
output = contract.functions[function_name](
|
108
|
+
output = contract.functions[function_name](
|
109
|
+
*parse_function_params(function_params)
|
110
|
+
).call()
|
108
111
|
return output
|
109
112
|
|
110
113
|
|
@@ -120,9 +123,10 @@ def prepare_tx(
|
|
120
123
|
) -> TxParams:
|
121
124
|
tx_params_new = _prepare_tx_params(web3, from_address, access_list, tx_params)
|
122
125
|
contract = web3.eth.contract(address=contract_address, abi=contract_abi)
|
123
|
-
|
124
126
|
# Build the transaction.
|
125
|
-
function_call = contract.functions[function_name](
|
127
|
+
function_call = contract.functions[function_name](
|
128
|
+
*parse_function_params(function_params)
|
129
|
+
)
|
126
130
|
built_tx_params: TxParams = function_call.build_transaction(tx_params_new)
|
127
131
|
return built_tx_params
|
128
132
|
|
@@ -269,6 +273,7 @@ def send_function_on_contract_tx_using_safe(
|
|
269
273
|
tx_hash, tx = safe_tx.execute(
|
270
274
|
from_private_key.get_secret_value(),
|
271
275
|
tx_nonce=eoa_nonce,
|
276
|
+
eip1559_speed=TxSpeed.FAST,
|
272
277
|
)
|
273
278
|
receipt_tx = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=timeout)
|
274
279
|
check_tx_receipt(receipt_tx)
|
@@ -286,7 +291,7 @@ def sign_send_and_get_receipt_tx(
|
|
286
291
|
tx_params_new, private_key=from_private_key.get_secret_value()
|
287
292
|
)
|
288
293
|
# Send the signed transaction.
|
289
|
-
send_tx = web3.eth.send_raw_transaction(signed_tx.
|
294
|
+
send_tx = web3.eth.send_raw_transaction(signed_tx.raw_transaction)
|
290
295
|
# And wait for the receipt.
|
291
296
|
receipt_tx = web3.eth.wait_for_transaction_receipt(send_tx, timeout=timeout)
|
292
297
|
# Verify it didn't fail.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: prediction-market-agent-tooling
|
3
|
-
Version: 0.68.
|
3
|
+
Version: 0.68.1
|
4
4
|
Summary: Tools to benchmark, deploy and monitor prediction market agents.
|
5
5
|
Author: Gnosis
|
6
6
|
Requires-Python: >=3.10,<3.13
|
@@ -14,11 +14,11 @@ Provides-Extra: openai
|
|
14
14
|
Provides-Extra: optuna
|
15
15
|
Requires-Dist: autoflake (>=2.2.1,<3.0.0)
|
16
16
|
Requires-Dist: base58 (>=1.0.2,<2.0)
|
17
|
-
Requires-Dist: cowdao-cowpy (==1.0.
|
17
|
+
Requires-Dist: cowdao-cowpy (==1.0.1)
|
18
18
|
Requires-Dist: cron-validator (>=1.0.8,<2.0.0)
|
19
|
-
Requires-Dist: eth-account (>=0.
|
19
|
+
Requires-Dist: eth-account (>=0.13.0,<0.14.0)
|
20
20
|
Requires-Dist: eth-keys (>=0.6.1,<0.7.0)
|
21
|
-
Requires-Dist: eth-typing (>=
|
21
|
+
Requires-Dist: eth-typing (>=5.0.0,<6.0.0)
|
22
22
|
Requires-Dist: functions-framework (>=3.5.0,<4.0.0)
|
23
23
|
Requires-Dist: google-api-python-client (==2.95.0) ; extra == "google"
|
24
24
|
Requires-Dist: google-cloud-functions (>=1.16.0,<2.0.0)
|
@@ -41,6 +41,7 @@ Requires-Dist: prompt-toolkit (>=3.0.43,<4.0.0)
|
|
41
41
|
Requires-Dist: proto-plus (>=1.0.0,<2.0.0)
|
42
42
|
Requires-Dist: protobuf (>=5.0.0,<6.0.0)
|
43
43
|
Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0)
|
44
|
+
Requires-Dist: py-clob-client (>=0.24.0,<0.25.0)
|
44
45
|
Requires-Dist: pydantic (>=2.6.1,<3.0.0)
|
45
46
|
Requires-Dist: pydantic-ai (>=0.1.9,<1.0.0)
|
46
47
|
Requires-Dist: pydantic-settings (>=2.4.0,<3.0.0)
|
@@ -48,8 +49,8 @@ Requires-Dist: pymongo (>=4.8.0,<5.0.0)
|
|
48
49
|
Requires-Dist: pytest-postgresql (>=6.1.1,<7.0.0)
|
49
50
|
Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
|
50
51
|
Requires-Dist: python-json-logger (>=3.3.0,<4.0.0)
|
51
|
-
Requires-Dist: safe-cli (>=1.
|
52
|
-
Requires-Dist: safe-eth-py (>=
|
52
|
+
Requires-Dist: safe-cli (>=1.5.0,<2.0.0)
|
53
|
+
Requires-Dist: safe-eth-py (>=7.8.0,<8.0.0)
|
53
54
|
Requires-Dist: scikit-learn (>=1.3.1,<2.0.0)
|
54
55
|
Requires-Dist: sqlmodel (>=0.0.22,<0.0.23)
|
55
56
|
Requires-Dist: streamlit (>=1.31.0,<2.0.0)
|
@@ -62,7 +63,7 @@ Requires-Dist: types-cachetools (>=5.5.0.20240820,<6.0.0.0)
|
|
62
63
|
Requires-Dist: types-python-dateutil (>=2.9.0.20240906,<3.0.0.0)
|
63
64
|
Requires-Dist: types-pytz (>=2024.1.0.20240203,<2025.0.0.0)
|
64
65
|
Requires-Dist: types-requests (>=2.31.0.0,<3.0.0.0)
|
65
|
-
Requires-Dist: web3 (>=6
|
66
|
+
Requires-Dist: web3 (>=6,<8)
|
66
67
|
Description-Content-Type: text/markdown
|
67
68
|
|
68
69
|
# Prediction Market Agent Tooling
|