prediction-market-agent-tooling 0.69.2__tar.gz → 0.69.4__tar.gz
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-0.69.2 → prediction_market_agent_tooling-0.69.4}/PKG-INFO +1 -1
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/agent.py +7 -1
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/betting_strategy.py +10 -10
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/constants.py +4 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/agent_market.py +3 -3
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/data_models.py +2 -4
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/omen.py +20 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/data_models.py +0 -7
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/price_manager.py +2 -4
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/seer.py +23 -16
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/seer_contracts.py +30 -6
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/contract.py +25 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/cow/cow_order.py +1 -1
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/cow/models.py +1 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/cow/semaphore.py +5 -2
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/utils.py +46 -1
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/web3_utils.py +36 -1
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/pyproject.toml +3 -1
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/README.md +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/agentresultmapping.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/erc1155.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/erc721.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/gvp2_settlement.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/ownable.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/ownable_erc721.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/seer_gnosis_router.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/seer_market_factory.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/abis/swapr_router.abi.json +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/chains.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/config.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/data_download/langfuse_data_downloader.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/deploy/trade_interval.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/gtypes.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/loggers.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/logprobs_parser.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/base_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/blockchain_utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/categorize.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/market_fees.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/markets.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/cow_contracts.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/data_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/omen_constants.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/clob_manager.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/constants.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/polymarket_contracts.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/polymarket_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/exceptions.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/seer_api.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/markets/seer/swap_pool_handler.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/py.typed +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/_generic_value.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/balances.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/caches/db_cache.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/caches/inmemory_cache.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/caches/serializers.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/costs.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/custom_exceptions.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/db/db_manager.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/google_utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/httpx_cached_client.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/is_invalid.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/omen/sell_positions.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/perplexity/perplexity_client.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/perplexity/perplexity_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/perplexity/perplexity_search.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/rephrase.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/safe.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/singleton.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tavily/tavily_models.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tavily/tavily_search.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tokens/auto_deposit.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tokens/main_token.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tokens/slippage.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tokens/token_utils.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/tokens/usd.py +0 -0
- {prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/prediction_market_agent_tooling/tools/transaction_cache.py +0 -0
@@ -53,6 +53,7 @@ from prediction_market_agent_tooling.tools.tokens.main_token import (
|
|
53
53
|
from prediction_market_agent_tooling.tools.utils import (
|
54
54
|
DatetimeUTC,
|
55
55
|
check_not_none,
|
56
|
+
retry_until_true,
|
56
57
|
utcnow,
|
57
58
|
)
|
58
59
|
|
@@ -645,8 +646,10 @@ class DeployableTraderAgent(DeployablePredictionAgent):
|
|
645
646
|
|
646
647
|
total_amount = market.get_in_usd(market.get_tiny_bet_amount())
|
647
648
|
existing_position = market.get_position(user_id=user_id)
|
649
|
+
|
648
650
|
if existing_position and existing_position.total_amount_current > USD(0):
|
649
651
|
total_amount += existing_position.total_amount_current
|
652
|
+
|
650
653
|
return total_amount
|
651
654
|
|
652
655
|
def get_betting_strategy(self, market: AgentMarket) -> BettingStrategy:
|
@@ -703,8 +706,11 @@ class DeployableTraderAgent(DeployablePredictionAgent):
|
|
703
706
|
)
|
704
707
|
case TradeType.SELL:
|
705
708
|
# Get actual value of the position we are going to sell, and if it's less than we wanted to sell, simply sell all of it.
|
709
|
+
# In this palce, we expect to have positions, so retry a few times if None are returned, which sometimes happens due to flaky subgraph.
|
706
710
|
current_position = check_not_none(
|
707
|
-
|
711
|
+
retry_until_true(
|
712
|
+
lambda x: x is not None and x.total_amount_ot > 0
|
713
|
+
)(market.get_position)(
|
708
714
|
market.get_user_id(api_keys=self.api_keys)
|
709
715
|
),
|
710
716
|
"Should exists if we are going to sell outcomes.",
|
@@ -5,9 +5,7 @@ import numpy as np
|
|
5
5
|
from scipy.optimize import minimize_scalar
|
6
6
|
|
7
7
|
from prediction_market_agent_tooling.benchmark.utils import get_most_probable_outcome
|
8
|
-
from prediction_market_agent_tooling.deploy.constants import
|
9
|
-
INVALID_OUTCOME_LOWERCASE_IDENTIFIER,
|
10
|
-
)
|
8
|
+
from prediction_market_agent_tooling.deploy.constants import is_invalid_outcome
|
11
9
|
from prediction_market_agent_tooling.gtypes import (
|
12
10
|
USD,
|
13
11
|
CollateralToken,
|
@@ -302,7 +300,7 @@ class CategoricalMaxAccuracyBettingStrategy(BettingStrategy):
|
|
302
300
|
) -> OutcomeStr:
|
303
301
|
# We get the first direction which is != direction.
|
304
302
|
other_direction = [i for i in outcomes if i.lower() != direction.lower()][0]
|
305
|
-
if
|
303
|
+
if is_invalid_outcome(other_direction):
|
306
304
|
raise ValueError("Invalid outcome found as opposite direction. Exitting.")
|
307
305
|
return other_direction
|
308
306
|
|
@@ -459,7 +457,7 @@ class _BinaryKellyBettingStrategy(BettingStrategy):
|
|
459
457
|
)
|
460
458
|
# We get the first direction which is != direction.
|
461
459
|
other_direction = [i for i in market.outcomes if i != direction][0]
|
462
|
-
if
|
460
|
+
if is_invalid_outcome(other_direction):
|
463
461
|
raise ValueError("Invalid outcome found as opposite direction. Exitting.")
|
464
462
|
|
465
463
|
kelly_bet = self.get_kelly_bet(
|
@@ -484,11 +482,13 @@ class _BinaryKellyBettingStrategy(BettingStrategy):
|
|
484
482
|
bet_outcome = direction if kelly_bet.direction else other_direction
|
485
483
|
|
486
484
|
amounts = {
|
487
|
-
bet_outcome:
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
485
|
+
bet_outcome: (
|
486
|
+
BettingStrategy.cap_to_profitable_bet_amount(
|
487
|
+
market, market.get_token_in_usd(kelly_bet_size), bet_outcome
|
488
|
+
)
|
489
|
+
if kelly_bet_size > 0
|
490
|
+
else USD(0)
|
491
|
+
),
|
492
492
|
}
|
493
493
|
target_position = Position(market_id=market.id, amounts_current=amounts)
|
494
494
|
trades = self._build_rebalance_trades_from_positions(
|
@@ -7,3 +7,7 @@ YES_OUTCOME_LOWERCASE_IDENTIFIER = "yes"
|
|
7
7
|
NO_OUTCOME_LOWERCASE_IDENTIFIER = "no"
|
8
8
|
UP_OUTCOME_LOWERCASE_IDENTIFIER = "up"
|
9
9
|
DOWN_OUTCOME_LOWERCASE_IDENTIFIER = "down"
|
10
|
+
|
11
|
+
|
12
|
+
def is_invalid_outcome(outcome: str) -> bool:
|
13
|
+
return INVALID_OUTCOME_LOWERCASE_IDENTIFIER in outcome.lower()
|
@@ -12,10 +12,10 @@ from prediction_market_agent_tooling.benchmark.utils import get_most_probable_ou
|
|
12
12
|
from prediction_market_agent_tooling.config import APIKeys
|
13
13
|
from prediction_market_agent_tooling.deploy.constants import (
|
14
14
|
DOWN_OUTCOME_LOWERCASE_IDENTIFIER,
|
15
|
-
INVALID_OUTCOME_LOWERCASE_IDENTIFIER,
|
16
15
|
NO_OUTCOME_LOWERCASE_IDENTIFIER,
|
17
16
|
UP_OUTCOME_LOWERCASE_IDENTIFIER,
|
18
17
|
YES_OUTCOME_LOWERCASE_IDENTIFIER,
|
18
|
+
is_invalid_outcome,
|
19
19
|
)
|
20
20
|
from prediction_market_agent_tooling.gtypes import (
|
21
21
|
OutcomeStr,
|
@@ -212,7 +212,7 @@ class AgentMarket(BaseModel):
|
|
212
212
|
|
213
213
|
if len(lowercase_outcomes) == 3:
|
214
214
|
invalid_outcome = lowercase_outcomes[-1]
|
215
|
-
has_invalid =
|
215
|
+
has_invalid = is_invalid_outcome(invalid_outcome)
|
216
216
|
return has_yes and has_no and has_invalid
|
217
217
|
|
218
218
|
return has_yes and has_no
|
@@ -230,7 +230,7 @@ class AgentMarket(BaseModel):
|
|
230
230
|
|
231
231
|
if len(lowercase_outcomes) == 3:
|
232
232
|
invalid_outcome = lowercase_outcomes[-1]
|
233
|
-
has_invalid =
|
233
|
+
has_invalid = is_invalid_outcome(invalid_outcome)
|
234
234
|
return has_up and has_down and has_invalid
|
235
235
|
|
236
236
|
return has_up and has_down
|
@@ -9,6 +9,7 @@ from prediction_market_agent_tooling.deploy.constants import (
|
|
9
9
|
NO_OUTCOME_LOWERCASE_IDENTIFIER,
|
10
10
|
UP_OUTCOME_LOWERCASE_IDENTIFIER,
|
11
11
|
YES_OUTCOME_LOWERCASE_IDENTIFIER,
|
12
|
+
is_invalid_outcome,
|
12
13
|
)
|
13
14
|
from prediction_market_agent_tooling.gtypes import (
|
14
15
|
USD,
|
@@ -224,10 +225,7 @@ class CategoricalProbabilisticAnswer(BaseModel):
|
|
224
225
|
OutcomeStr(DOWN_OUTCOME_LOWERCASE_IDENTIFIER.upper())
|
225
226
|
] = answer.p_down
|
226
227
|
|
227
|
-
if (
|
228
|
-
market_outcomes
|
229
|
-
and INVALID_OUTCOME_LOWERCASE_IDENTIFIER in lowercase_market_outcomes
|
230
|
-
):
|
228
|
+
if market_outcomes and any(is_invalid_outcome(o) for o in market_outcomes):
|
231
229
|
probabilities[
|
232
230
|
OutcomeStr(INVALID_OUTCOME_LOWERCASE_IDENTIFIER.capitalize())
|
233
231
|
] = Probability(1 - answer.p_up - answer.p_down)
|
@@ -704,6 +704,26 @@ def omen_buy_outcome_tx(
|
|
704
704
|
auto_deposit: bool,
|
705
705
|
web3: Web3 | None = None,
|
706
706
|
slippage: float = 0.01,
|
707
|
+
) -> str:
|
708
|
+
return omen_buy_outcome_tx_no_retry(
|
709
|
+
api_keys=api_keys,
|
710
|
+
amount=amount,
|
711
|
+
market=market,
|
712
|
+
outcome=outcome,
|
713
|
+
auto_deposit=auto_deposit,
|
714
|
+
web3=web3,
|
715
|
+
slippage=slippage,
|
716
|
+
)
|
717
|
+
|
718
|
+
|
719
|
+
def omen_buy_outcome_tx_no_retry(
|
720
|
+
api_keys: APIKeys,
|
721
|
+
amount: USD | CollateralToken,
|
722
|
+
market: OmenAgentMarket,
|
723
|
+
outcome: OutcomeStr,
|
724
|
+
auto_deposit: bool,
|
725
|
+
web3: Web3 | None = None,
|
726
|
+
slippage: float = 0.01,
|
707
727
|
) -> str:
|
708
728
|
"""
|
709
729
|
Bets the given amount for the given outcome in the given market.
|
@@ -163,13 +163,6 @@ class SeerMarketWithQuestions(SeerMarket):
|
|
163
163
|
questions: list[SeerMarketQuestions]
|
164
164
|
|
165
165
|
|
166
|
-
class RedeemParams(BaseModel):
|
167
|
-
model_config = ConfigDict(populate_by_name=True)
|
168
|
-
market: ChecksumAddress
|
169
|
-
outcome_indices: list[int] = Field(alias="outcomeIndexes")
|
170
|
-
amounts: list[OutcomeWei]
|
171
|
-
|
172
|
-
|
173
166
|
class ExactInputSingleParams(BaseModel):
|
174
167
|
# from https://gnosisscan.io/address/0xffb643e73f280b97809a8b41f7232ab401a04ee1#code
|
175
168
|
model_config = ConfigDict(populate_by_name=True)
|
@@ -2,9 +2,7 @@ from cachetools import TTLCache, cached
|
|
2
2
|
from pydantic import BaseModel
|
3
3
|
from web3 import Web3
|
4
4
|
|
5
|
-
from prediction_market_agent_tooling.deploy.constants import
|
6
|
-
INVALID_OUTCOME_LOWERCASE_IDENTIFIER,
|
7
|
-
)
|
5
|
+
from prediction_market_agent_tooling.deploy.constants import is_invalid_outcome
|
8
6
|
from prediction_market_agent_tooling.gtypes import (
|
9
7
|
ChecksumAddress,
|
10
8
|
CollateralToken,
|
@@ -243,7 +241,7 @@ class PriceManager:
|
|
243
241
|
f"Outcome {outcome} not found in outcome_token_pool for market {self.seer_market.url}."
|
244
242
|
)
|
245
243
|
if outcome not in probability_map:
|
246
|
-
if
|
244
|
+
if not is_invalid_outcome(outcome):
|
247
245
|
raise PriceCalculationError(
|
248
246
|
f"Couldn't get probability for {outcome} for market {self.seer_market.url}."
|
249
247
|
)
|
@@ -49,7 +49,6 @@ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
|
|
49
49
|
SeerAgentResultMappingContract,
|
50
50
|
)
|
51
51
|
from prediction_market_agent_tooling.markets.seer.data_models import (
|
52
|
-
RedeemParams,
|
53
52
|
SeerMarket,
|
54
53
|
SeerMarketWithQuestions,
|
55
54
|
)
|
@@ -83,6 +82,7 @@ from prediction_market_agent_tooling.tools.cow.cow_order import (
|
|
83
82
|
OrderStatusError,
|
84
83
|
get_orders_by_owner,
|
85
84
|
get_trades_by_order_uid,
|
85
|
+
handle_allowance,
|
86
86
|
swap_tokens_waiting,
|
87
87
|
wait_for_order_completion,
|
88
88
|
)
|
@@ -234,7 +234,9 @@ class SeerAgentMarket(AgentMarket):
|
|
234
234
|
def get_tiny_bet_amount(self) -> CollateralToken:
|
235
235
|
return self.get_in_token(SEER_TINY_BET_AMOUNT)
|
236
236
|
|
237
|
-
def get_position(
|
237
|
+
def get_position(
|
238
|
+
self, user_id: str, web3: Web3 | None = None
|
239
|
+
) -> ExistingPosition | None:
|
238
240
|
"""
|
239
241
|
Fetches position from the user in a given market.
|
240
242
|
We ignore the INVALID balances since we are only interested in binary outcomes.
|
@@ -251,6 +253,10 @@ class SeerAgentMarket(AgentMarket):
|
|
251
253
|
|
252
254
|
amounts_ot[outcome_str] = outcome_token_balance_wei.as_outcome_token
|
253
255
|
|
256
|
+
# Adhere to convenience from other markets, where we return None if user doesn't have any position.
|
257
|
+
if all(v == 0 for v in amounts_ot.values()):
|
258
|
+
return None
|
259
|
+
|
254
260
|
amounts_current = {
|
255
261
|
k: self.get_token_in_usd(self.get_sell_value_of_outcome_token(k, v))
|
256
262
|
for k, v in amounts_ot.items()
|
@@ -273,6 +279,7 @@ class SeerAgentMarket(AgentMarket):
|
|
273
279
|
"""
|
274
280
|
We filter the markets using previous trades by the user so that we don't have to process all Seer markets.
|
275
281
|
"""
|
282
|
+
|
276
283
|
trades_by_user = get_seer_transactions(
|
277
284
|
api_keys.bet_from_address, RPCConfig().CHAIN_ID
|
278
285
|
)
|
@@ -293,10 +300,12 @@ class SeerAgentMarket(AgentMarket):
|
|
293
300
|
return filtered_markets
|
294
301
|
|
295
302
|
@staticmethod
|
296
|
-
def redeem_winnings(api_keys: APIKeys) -> None:
|
297
|
-
web3 = RPCConfig().get_web3()
|
303
|
+
def redeem_winnings(api_keys: APIKeys, web3: Web3 | None = None) -> None:
|
304
|
+
web3 = web3 or RPCConfig().get_web3()
|
298
305
|
subgraph = SeerSubgraphHandler()
|
299
306
|
|
307
|
+
# ToDo - Find open positions by user directly
|
308
|
+
|
300
309
|
closed_markets = subgraph.get_markets(
|
301
310
|
filter_by=FilterBy.RESOLVED, sort_by=SortBy.NEWEST
|
302
311
|
)
|
@@ -305,8 +314,8 @@ class SeerAgentMarket(AgentMarket):
|
|
305
314
|
)
|
306
315
|
|
307
316
|
market_balances = {
|
308
|
-
market.id:
|
309
|
-
api_keys.bet_from_address, web3
|
317
|
+
market.id: list(
|
318
|
+
market.get_outcome_token_balances(api_keys.bet_from_address, web3)
|
310
319
|
)
|
311
320
|
for market in filtered_markets
|
312
321
|
}
|
@@ -323,17 +332,15 @@ class SeerAgentMarket(AgentMarket):
|
|
323
332
|
try:
|
324
333
|
# GnosisRouter needs approval to use our outcome tokens
|
325
334
|
for i, token in enumerate(market.wrapped_tokens):
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
335
|
+
handle_allowance(
|
336
|
+
api_keys=api_keys,
|
337
|
+
sell_token=Web3.to_checksum_address(token),
|
338
|
+
amount_to_check_wei=market_balances[market.id][i].as_wei,
|
330
339
|
for_address=gnosis_router.address,
|
331
|
-
amount_wei=market_balances[market.id][i].as_wei,
|
332
340
|
web3=web3,
|
333
341
|
)
|
334
342
|
|
335
343
|
# We can only ask for redeem of outcome tokens on correct outcomes
|
336
|
-
# TODO: Implement more complex use-cases: https://github.com/gnosis/prediction-market-agent-tooling/issues/850
|
337
344
|
amounts_to_redeem = [
|
338
345
|
(amount if numerator > 0 else OutcomeWei(0))
|
339
346
|
for amount, numerator in zip(
|
@@ -341,13 +348,13 @@ class SeerAgentMarket(AgentMarket):
|
|
341
348
|
)
|
342
349
|
]
|
343
350
|
|
344
|
-
|
345
|
-
|
351
|
+
gnosis_router.redeem_to_base(
|
352
|
+
api_keys,
|
346
353
|
market=Web3.to_checksum_address(market.id),
|
347
|
-
|
354
|
+
outcome_indexes=list(range(len(market.payout_numerators))),
|
348
355
|
amounts=amounts_to_redeem,
|
356
|
+
web3=web3,
|
349
357
|
)
|
350
|
-
gnosis_router.redeem_to_base(api_keys, params=params, web3=web3)
|
351
358
|
logger.info(f"Redeemed market {market.url}.")
|
352
359
|
except Exception:
|
353
360
|
logger.exception(
|
@@ -8,13 +8,13 @@ from prediction_market_agent_tooling.gtypes import (
|
|
8
8
|
ABI,
|
9
9
|
ChecksumAddress,
|
10
10
|
OutcomeStr,
|
11
|
+
OutcomeWei,
|
11
12
|
TxReceipt,
|
12
13
|
Wei,
|
13
14
|
xDai,
|
14
15
|
)
|
15
16
|
from prediction_market_agent_tooling.markets.seer.data_models import (
|
16
17
|
ExactInputSingleParams,
|
17
|
-
RedeemParams,
|
18
18
|
)
|
19
19
|
from prediction_market_agent_tooling.markets.seer.subgraph_data_models import (
|
20
20
|
CreateCategoricalMarketsParams,
|
@@ -88,7 +88,7 @@ class SeerMarketFactory(ContractOnGnosisChain):
|
|
88
88
|
|
89
89
|
|
90
90
|
class GnosisRouter(ContractOnGnosisChain):
|
91
|
-
# https://gnosisscan.io/address/
|
91
|
+
# https://gnosisscan.io/address/0xeC9048b59b3467415b1a38F63416407eA0c70fB8#code.
|
92
92
|
abi: ABI = abi_field_validator(
|
93
93
|
os.path.join(
|
94
94
|
os.path.dirname(os.path.realpath(__file__)),
|
@@ -102,12 +102,18 @@ class GnosisRouter(ContractOnGnosisChain):
|
|
102
102
|
def redeem_to_base(
|
103
103
|
self,
|
104
104
|
api_keys: APIKeys,
|
105
|
-
|
105
|
+
market: ChecksumAddress,
|
106
|
+
outcome_indexes: list[int],
|
107
|
+
amounts: list[OutcomeWei],
|
106
108
|
web3: Web3 | None = None,
|
107
109
|
) -> TxReceipt:
|
108
|
-
params_dict = params.model_dump(by_alias=True)
|
109
110
|
# We explicity set amounts since OutcomeWei gets serialized as dict
|
110
|
-
params_dict
|
111
|
+
params_dict = {
|
112
|
+
"market": market,
|
113
|
+
"outcomeIndexes": outcome_indexes,
|
114
|
+
"amounts": [amount.value for amount in amounts],
|
115
|
+
}
|
116
|
+
|
111
117
|
receipt_tx = self.send(
|
112
118
|
api_keys=api_keys,
|
113
119
|
function_name="redeemToBase",
|
@@ -116,6 +122,22 @@ class GnosisRouter(ContractOnGnosisChain):
|
|
116
122
|
)
|
117
123
|
return receipt_tx
|
118
124
|
|
125
|
+
def split_from_base(
|
126
|
+
self,
|
127
|
+
api_keys: APIKeys,
|
128
|
+
market_id: ChecksumAddress,
|
129
|
+
amount_wei: Wei,
|
130
|
+
web3: Web3 | None = None,
|
131
|
+
) -> TxReceipt:
|
132
|
+
"""Splits using xDAI and receives outcome tokens"""
|
133
|
+
return self.send_with_value(
|
134
|
+
api_keys=api_keys,
|
135
|
+
function_name="splitFromBase",
|
136
|
+
amount_wei=amount_wei,
|
137
|
+
function_params=[market_id],
|
138
|
+
web3=web3,
|
139
|
+
)
|
140
|
+
|
119
141
|
def split_position(
|
120
142
|
self,
|
121
143
|
api_keys: APIKeys,
|
@@ -135,7 +157,6 @@ class GnosisRouter(ContractOnGnosisChain):
|
|
135
157
|
|
136
158
|
|
137
159
|
class SwaprRouterContract(ContractOnGnosisChain):
|
138
|
-
# File content taken from https://github.com/protofire/omen-exchange/blob/master/app/src/abi/marketMaker.json.
|
139
160
|
abi: ABI = abi_field_validator(
|
140
161
|
os.path.join(
|
141
162
|
os.path.dirname(os.path.realpath(__file__)),
|
@@ -166,4 +187,7 @@ class SwaprRouterContract(ContractOnGnosisChain):
|
|
166
187
|
function_name="exactInputSingle",
|
167
188
|
function_params=[tuple(dict(params).values())],
|
168
189
|
web3=web3,
|
190
|
+
# Use higher gas limit for complex swap operations to avoid slow estimation
|
191
|
+
# Typical Swapr swaps use 150k-300k gas, we set conservative
|
192
|
+
default_gas=400_000,
|
169
193
|
)
|
@@ -116,6 +116,7 @@ class ContractBaseClass(BaseModel):
|
|
116
116
|
tx_params: t.Optional[TxParams] = None,
|
117
117
|
timeout: int = 180,
|
118
118
|
web3: Web3 | None = None,
|
119
|
+
default_gas: int | None = None,
|
119
120
|
) -> TxReceipt:
|
120
121
|
"""
|
121
122
|
Used for changing a state (writing) to the contract.
|
@@ -132,6 +133,7 @@ class ContractBaseClass(BaseModel):
|
|
132
133
|
function_params=function_params,
|
133
134
|
tx_params=tx_params,
|
134
135
|
timeout=timeout,
|
136
|
+
default_gas=default_gas,
|
135
137
|
)
|
136
138
|
return send_function_on_contract_tx(
|
137
139
|
web3=web3 or self.get_web3(),
|
@@ -142,6 +144,7 @@ class ContractBaseClass(BaseModel):
|
|
142
144
|
function_params=function_params,
|
143
145
|
tx_params=tx_params,
|
144
146
|
timeout=timeout,
|
147
|
+
default_gas=default_gas,
|
145
148
|
)
|
146
149
|
|
147
150
|
def send_with_value(
|
@@ -431,6 +434,25 @@ class ContractWrapped1155BaseClass(ContractERC20BaseClass):
|
|
431
434
|
)
|
432
435
|
)
|
433
436
|
|
437
|
+
def factory(self, web3: Web3 | None = None) -> ChecksumAddress:
|
438
|
+
return Web3.to_checksum_address(self.call("factory", web3=web3))
|
439
|
+
|
440
|
+
def mint(
|
441
|
+
self,
|
442
|
+
api_keys: APIKeys,
|
443
|
+
to_address: ChecksumAddress,
|
444
|
+
amount: Wei,
|
445
|
+
tx_params: t.Optional[TxParams] = None,
|
446
|
+
web3: Web3 | None = None,
|
447
|
+
) -> TxReceipt:
|
448
|
+
return self.send(
|
449
|
+
api_keys=api_keys,
|
450
|
+
function_name="mint",
|
451
|
+
function_params=[to_address, amount],
|
452
|
+
tx_params=tx_params,
|
453
|
+
web3=web3,
|
454
|
+
)
|
455
|
+
|
434
456
|
|
435
457
|
class OwnableContract(ContractBaseClass):
|
436
458
|
abi: ABI = abi_field_validator(
|
@@ -718,6 +740,9 @@ class ConditionalTokenContract(ContractBaseClass):
|
|
718
740
|
.events.PayoutRedemption()
|
719
741
|
.process_receipt(receipt_tx)
|
720
742
|
)
|
743
|
+
logger.info(
|
744
|
+
f"Receipt tx: `{receipt_tx}` Redeem event logs: `{redeem_event_logs}`"
|
745
|
+
)
|
721
746
|
redeem_event = PayoutRedemptionEvent(**redeem_event_logs[0]["args"])
|
722
747
|
return redeem_event
|
723
748
|
|
@@ -191,7 +191,7 @@ def handle_allowance(
|
|
191
191
|
|
192
192
|
|
193
193
|
@postgres_rate_limited(
|
194
|
-
api_keys=APIKeys(), rate_id="swap_tokens_waiting", interval_seconds=
|
194
|
+
api_keys=APIKeys(), rate_id="swap_tokens_waiting", interval_seconds=5.0
|
195
195
|
)
|
196
196
|
@tenacity.retry(
|
197
197
|
reraise=True,
|
@@ -18,7 +18,10 @@ FALLBACK_SQL_ENGINE = "sqlite:///rate_limit.db"
|
|
18
18
|
|
19
19
|
|
20
20
|
def postgres_rate_limited(
|
21
|
-
api_keys: APIKeys,
|
21
|
+
api_keys: APIKeys,
|
22
|
+
rate_id: str,
|
23
|
+
interval_seconds: float,
|
24
|
+
shared_db: bool = False,
|
22
25
|
) -> Callable[[F], F]:
|
23
26
|
"""rate_id is used to distinguish between different rate limits for different functions"""
|
24
27
|
limiter = RateLimiter(id=rate_id, interval_seconds=interval_seconds)
|
@@ -28,7 +31,7 @@ def postgres_rate_limited(
|
|
28
31
|
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
29
32
|
sqlalchemy_db_url = (
|
30
33
|
api_keys.sqlalchemy_db_url.get_secret_value()
|
31
|
-
if
|
34
|
+
if shared_db
|
32
35
|
else FALLBACK_SQL_ENGINE
|
33
36
|
)
|
34
37
|
|
@@ -1,8 +1,10 @@
|
|
1
|
+
import functools
|
1
2
|
import os
|
2
3
|
import subprocess
|
4
|
+
import time
|
3
5
|
from datetime import datetime
|
4
6
|
from math import prod
|
5
|
-
from typing import Any, NoReturn, Optional, Type, TypeVar
|
7
|
+
from typing import Any, Callable, NoReturn, Optional, Type, TypeVar, cast
|
6
8
|
|
7
9
|
import httpx
|
8
10
|
import pytz
|
@@ -56,6 +58,49 @@ def check_not_none(
|
|
56
58
|
return value
|
57
59
|
|
58
60
|
|
61
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
62
|
+
|
63
|
+
|
64
|
+
def retry_until_true(
|
65
|
+
condition: Callable[[Any], bool],
|
66
|
+
max_retries: int = 3,
|
67
|
+
delay: float = 1.0,
|
68
|
+
) -> Callable[[F], F]:
|
69
|
+
"""
|
70
|
+
Decorator that retries a function if the condition on its result evaluates to False.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
condition: Function that takes the result and returns True if acceptable, False to retry
|
74
|
+
max_retries: Maximum number of retry attempts
|
75
|
+
delay: Delay between retries in seconds
|
76
|
+
"""
|
77
|
+
|
78
|
+
def decorator(func: F) -> F:
|
79
|
+
@functools.wraps(func)
|
80
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
81
|
+
for attempt in range(1, max_retries + 1):
|
82
|
+
result = func(*args, **kwargs)
|
83
|
+
|
84
|
+
if condition(result):
|
85
|
+
logger.info(f"Condition met for {func.__name__} on {attempt}.")
|
86
|
+
return result
|
87
|
+
|
88
|
+
if attempt < max_retries:
|
89
|
+
logger.debug(
|
90
|
+
f"Retry {attempt + 1}/{max_retries} for {func.__name__}"
|
91
|
+
)
|
92
|
+
time.sleep(delay)
|
93
|
+
else:
|
94
|
+
logger.warning(
|
95
|
+
f"All {max_retries} retries exhausted for {func.__name__}"
|
96
|
+
)
|
97
|
+
return result
|
98
|
+
|
99
|
+
return cast(F, wrapper)
|
100
|
+
|
101
|
+
return decorator
|
102
|
+
|
103
|
+
|
59
104
|
def should_not_happen(
|
60
105
|
msg: str = "Should not happen.", exp: Type[ValueError] = ValueError
|
61
106
|
) -> NoReturn:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import binascii
|
2
|
+
import multiprocessing.context
|
2
3
|
import secrets
|
3
4
|
from typing import Any, Optional
|
4
5
|
|
@@ -7,12 +8,14 @@ import tenacity
|
|
7
8
|
from eth_account import Account
|
8
9
|
from eth_typing import URI
|
9
10
|
from eth_utils.currency import MAX_WEI, MIN_WEI
|
11
|
+
from joblib import Parallel, delayed
|
10
12
|
from pydantic.types import SecretStr
|
11
13
|
from safe_eth.eth import EthereumClient
|
12
14
|
from safe_eth.eth.ethereum_client import TxSpeed
|
13
15
|
from safe_eth.safe.safe import SafeV141
|
14
16
|
from web3 import Web3
|
15
17
|
from web3.constants import HASH_ZERO
|
18
|
+
from web3.contract.contract import ContractFunction as Web3ContractFunction
|
16
19
|
from web3.types import AccessList, AccessListEntry, Nonce, TxParams, TxReceipt
|
17
20
|
|
18
21
|
from prediction_market_agent_tooling.gtypes import (
|
@@ -76,7 +79,7 @@ def unwrap_generic_value(value: Any) -> Any:
|
|
76
79
|
|
77
80
|
|
78
81
|
def parse_function_params(
|
79
|
-
params: Optional[list[Any] | tuple[Any] | dict[str, Any]]
|
82
|
+
params: Optional[list[Any] | tuple[Any] | dict[str, Any]],
|
80
83
|
) -> list[Any] | tuple[Any]:
|
81
84
|
params = unwrap_generic_value(params)
|
82
85
|
if params is None:
|
@@ -120,6 +123,7 @@ def prepare_tx(
|
|
120
123
|
function_params: Optional[list[Any] | dict[str, Any]] = None,
|
121
124
|
access_list: Optional[AccessList] = None,
|
122
125
|
tx_params: Optional[TxParams] = None,
|
126
|
+
default_gas: int | None = None,
|
123
127
|
) -> TxParams:
|
124
128
|
tx_params_new = _prepare_tx_params(web3, from_address, access_list, tx_params)
|
125
129
|
contract = web3.eth.contract(address=contract_address, abi=contract_abi)
|
@@ -127,10 +131,37 @@ def prepare_tx(
|
|
127
131
|
function_call = contract.functions[function_name](
|
128
132
|
*parse_function_params(function_params)
|
129
133
|
)
|
134
|
+
if default_gas is not None and "gas" not in tx_params_new:
|
135
|
+
tx_params_new["gas"] = estimate_gas_with_timeout(
|
136
|
+
function_call, default_gas=default_gas, tx_params=tx_params_new
|
137
|
+
)
|
130
138
|
built_tx_params: TxParams = function_call.build_transaction(tx_params_new)
|
131
139
|
return built_tx_params
|
132
140
|
|
133
141
|
|
142
|
+
def estimate_gas_with_timeout(
|
143
|
+
function_call: Web3ContractFunction,
|
144
|
+
default_gas: int,
|
145
|
+
timeout: int = 15,
|
146
|
+
tx_params: Optional[TxParams] = None,
|
147
|
+
) -> int:
|
148
|
+
"""
|
149
|
+
Tries to estimate the gas, but default to the default value on timeout.
|
150
|
+
"""
|
151
|
+
try:
|
152
|
+
# We need n_jobs=-1, otherwise timeouting isn't applied.
|
153
|
+
result: list[int] = Parallel(n_jobs=-1, backend="threading", timeout=timeout)(
|
154
|
+
delayed(function_call.estimate_gas)(tx_params) for _ in range(1)
|
155
|
+
)
|
156
|
+
estimated_gas = result[0]
|
157
|
+
return int(estimated_gas * 1.2) # Add 20% buffer
|
158
|
+
except (TimeoutError, multiprocessing.context.TimeoutError):
|
159
|
+
logger.warning(
|
160
|
+
f"Gas estimation timed out after {timeout} seconds, using default: {default_gas}"
|
161
|
+
)
|
162
|
+
return default_gas
|
163
|
+
|
164
|
+
|
134
165
|
def _prepare_tx_params(
|
135
166
|
web3: Web3,
|
136
167
|
from_address: ChecksumAddress | None,
|
@@ -182,6 +213,7 @@ def send_function_on_contract_tx(
|
|
182
213
|
function_params: Optional[list[Any] | dict[str, Any]] = None,
|
183
214
|
tx_params: Optional[TxParams] = None,
|
184
215
|
timeout: int = 180,
|
216
|
+
default_gas: int | None = None,
|
185
217
|
) -> TxReceipt:
|
186
218
|
public_key = private_key_to_public_key(from_private_key)
|
187
219
|
|
@@ -193,6 +225,7 @@ def send_function_on_contract_tx(
|
|
193
225
|
function_name=function_name,
|
194
226
|
function_params=function_params,
|
195
227
|
tx_params=tx_params,
|
228
|
+
default_gas=default_gas,
|
196
229
|
)
|
197
230
|
|
198
231
|
receipt_tx = sign_send_and_get_receipt_tx(
|
@@ -221,6 +254,7 @@ def send_function_on_contract_tx_using_safe(
|
|
221
254
|
function_params: Optional[list[Any] | dict[str, Any]] = None,
|
222
255
|
tx_params: Optional[TxParams] = None,
|
223
256
|
timeout: int = 180,
|
257
|
+
default_gas: int | None = None,
|
224
258
|
) -> TxReceipt:
|
225
259
|
if not web3.provider.endpoint_uri: # type: ignore
|
226
260
|
raise EnvironmentError("RPC_URL not available in web3 object.")
|
@@ -261,6 +295,7 @@ def send_function_on_contract_tx_using_safe(
|
|
261
295
|
function_params=function_params,
|
262
296
|
access_list=access_list,
|
263
297
|
tx_params=tx_params,
|
298
|
+
default_gas=default_gas,
|
264
299
|
)
|
265
300
|
safe_tx = s.build_multisig_tx(
|
266
301
|
to=Web3.to_checksum_address(tx_params["to"]),
|
{prediction_market_agent_tooling-0.69.2 → prediction_market_agent_tooling-0.69.4}/pyproject.toml
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "prediction-market-agent-tooling"
|
3
|
-
version = "0.69.
|
3
|
+
version = "0.69.4"
|
4
4
|
description = "Tools to benchmark, deploy and monitor prediction market agents."
|
5
5
|
authors = ["Gnosis"]
|
6
6
|
readme = "README.md"
|
@@ -77,6 +77,8 @@ black = "^23.12.1"
|
|
77
77
|
ape-foundry = "^0.8.2"
|
78
78
|
eth-ape = "^0.8.34"
|
79
79
|
diskcache = "^5.6.3"
|
80
|
+
freezegun = "^1.5.5"
|
81
|
+
pytest-line-profiler = "^0.2.1"
|
80
82
|
|
81
83
|
[build-system]
|
82
84
|
requires = ["poetry-core"]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|