prediction-market-agent-tooling 0.66.0.dev791__tar.gz → 0.66.2__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.
Files changed (131) hide show
  1. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/PKG-INFO +2 -2
  2. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/agent.py +3 -1
  3. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/betting_strategy.py +98 -15
  4. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +1 -1
  5. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/data_models.py +1 -1
  6. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/metaculus/data_models.py +3 -3
  7. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/cow_contracts.py +5 -1
  8. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/data_models.py +4 -2
  9. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/omen.py +2 -2
  10. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/omen_constants.py +5 -0
  11. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/seer.py +20 -16
  12. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/cow/cow_order.py +14 -6
  13. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/cow/models.py +8 -0
  14. prediction_market_agent_tooling-0.66.2/prediction_market_agent_tooling/tools/cow/semaphore.py +101 -0
  15. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/pyproject.toml +2 -2
  16. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/LICENSE +0 -0
  17. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/README.md +0 -0
  18. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/agentresultmapping.abi.json +0 -0
  19. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
  20. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  21. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  22. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  23. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/erc721.abi.json +0 -0
  24. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/gvp2_settlement.abi.json +0 -0
  25. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  26. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  27. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  28. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  29. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  30. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  31. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  32. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  33. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/ownable.abi.json +0 -0
  34. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/ownable_erc721.abi.json +0 -0
  35. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  36. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/seer_gnosis_router.abi.json +0 -0
  37. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/seer_market_factory.abi.json +0 -0
  38. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/abis/swapr_router.abi.json +0 -0
  39. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  40. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  41. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  42. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  43. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/chains.py +0 -0
  44. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/config.py +0 -0
  45. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/data_download/langfuse_data_downloader.py +0 -0
  46. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  47. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  48. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  49. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  50. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  51. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/deploy/trade_interval.py +0 -0
  52. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/gtypes.py +0 -0
  53. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
  54. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
  55. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/loggers.py +0 -0
  56. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/logprobs_parser.py +0 -0
  57. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
  58. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/base_subgraph_handler.py +0 -0
  59. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/blockchain_utils.py +0 -0
  60. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  61. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  62. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  63. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  64. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  65. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  66. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/market_fees.py +0 -0
  67. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/markets.py +0 -0
  68. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  69. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
  70. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  71. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
  72. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
  73. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +0 -0
  74. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
  75. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  76. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  77. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  78. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  79. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/data_models.py +0 -0
  80. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/exceptions.py +0 -0
  81. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/price_manager.py +0 -0
  82. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/seer_contracts.py +0 -0
  83. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +0 -0
  84. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +0 -0
  85. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/markets/seer/swap_pool_handler.py +0 -0
  86. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/py.typed +0 -0
  87. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/_generic_value.py +0 -0
  88. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/balances.py +0 -0
  89. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
  90. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  91. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +0 -0
  92. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/caches/db_cache.py +0 -0
  93. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/caches/inmemory_cache.py +0 -0
  94. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/caches/serializers.py +0 -0
  95. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/contract.py +0 -0
  96. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/costs.py +0 -0
  97. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/custom_exceptions.py +0 -0
  98. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
  99. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/db/db_manager.py +0 -0
  100. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/google_utils.py +0 -0
  101. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  102. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/httpx_cached_client.py +0 -0
  103. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  104. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  105. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
  106. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/is_invalid.py +0 -0
  107. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  108. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  109. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +0 -0
  110. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
  111. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/omen/sell_positions.py +0 -0
  112. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  113. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/perplexity/perplexity_client.py +0 -0
  114. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/perplexity/perplexity_models.py +0 -0
  115. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/perplexity/perplexity_search.py +0 -0
  116. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py +0 -0
  117. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py +0 -0
  118. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py +0 -0
  119. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/safe.py +0 -0
  120. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  121. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  122. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/tavily/tavily_models.py +0 -0
  123. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/tavily/tavily_search.py +0 -0
  124. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/tokens/auto_deposit.py +0 -0
  125. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +0 -0
  126. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/tokens/main_token.py +0 -0
  127. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/tokens/token_utils.py +0 -0
  128. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/tokens/usd.py +0 -0
  129. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/transaction_cache.py +0 -0
  130. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/utils.py +0 -0
  131. {prediction_market_agent_tooling-0.66.0.dev791 → prediction_market_agent_tooling-0.66.2}/prediction_market_agent_tooling/tools/web3_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.66.0.dev791
3
+ Version: 0.66.2
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,7 +14,7 @@ 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-kongzii (==1.0.0rc2)
17
+ Requires-Dist: cowdao-cowpy (==1.0.0rc5)
18
18
  Requires-Dist: cron-validator (>=1.0.8,<2.0.0)
19
19
  Requires-Dist: eth-account (>=0.8.0,<0.12.0)
20
20
  Requires-Dist: eth-keys (>=0.6.1,<0.7.0)
@@ -571,7 +571,9 @@ class DeployableTraderAgent(DeployablePredictionAgent):
571
571
  Given the market and prediction, agent uses this method to calculate optimal outcome and bet size.
572
572
  """
573
573
  total_amount = self.get_total_amount_to_bet(market)
574
- return MultiCategoricalMaxAccuracyBettingStrategy(bet_amount=total_amount)
574
+ return MultiCategoricalMaxAccuracyBettingStrategy(
575
+ max_position_amount=total_amount
576
+ )
575
577
 
576
578
  def build_trades(
577
579
  self,
@@ -1,6 +1,7 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from typing import Sequence
3
3
 
4
+ import numpy as np
4
5
  from scipy.optimize import minimize_scalar
5
6
 
6
7
  from prediction_market_agent_tooling.benchmark.utils import get_most_probable_outcome
@@ -94,6 +95,76 @@ class BettingStrategy(ABC):
94
95
  )
95
96
  return trades
96
97
 
98
+ @staticmethod
99
+ def cap_to_profitable_bet_amount(
100
+ market: AgentMarket,
101
+ bet_amount: USD,
102
+ outcome: OutcomeStr,
103
+ iters: int = 10,
104
+ ) -> USD:
105
+ """
106
+ Use a binary search (tree-based search) to efficiently find the largest profitable bet amount.
107
+ """
108
+ # First, try it with the desired amount right away.
109
+ if (
110
+ market.get_in_usd(
111
+ check_not_none(
112
+ market.get_buy_token_amount(bet_amount, outcome)
113
+ ).as_token
114
+ )
115
+ > bet_amount
116
+ ):
117
+ return bet_amount
118
+
119
+ # If it wasn't profitable, try binary search to find the highest, but profitable, amount.
120
+ lower = USD(0)
121
+ # It doesn't make sense to try to bet more than the liquidity itself, so override it as maximal value if it's lower.
122
+ upper = min(bet_amount, market.get_in_usd(market.get_liquidity()))
123
+ best_profitable = USD(0)
124
+
125
+ for _ in range(iters):
126
+ mid = (lower + upper) / 2
127
+ potential_outcome_value = market.get_in_usd(
128
+ check_not_none(market.get_buy_token_amount(mid, outcome)).as_token
129
+ )
130
+
131
+ if potential_outcome_value > mid:
132
+ # Profitable, try higher
133
+ best_profitable = mid
134
+ lower = mid
135
+
136
+ else:
137
+ # Not profitable, try lower
138
+ upper = mid
139
+
140
+ # If the search interval is very small, break early
141
+ if float(upper - lower) < 1e-8:
142
+ break
143
+
144
+ if np.isclose(best_profitable.value, 0):
145
+ best_profitable = USD(0)
146
+
147
+ return best_profitable
148
+
149
+ @staticmethod
150
+ def cap_to_profitable_position(
151
+ market: AgentMarket,
152
+ existing_position: USD,
153
+ wanted_position: USD,
154
+ outcome_to_bet_on: OutcomeStr,
155
+ ) -> USD:
156
+ # If the wanted position is lower, it means the agent is gonna sell and that's profitable always.
157
+ if wanted_position > existing_position:
158
+ difference = wanted_position - existing_position
159
+ # Cap the difference we would like to buy to a profitable one.
160
+ capped_difference = BettingStrategy.cap_to_profitable_bet_amount(
161
+ market, difference, outcome_to_bet_on
162
+ )
163
+ # Lowered the actual wanted position such that it remains profitable.
164
+ wanted_position = existing_position + capped_difference
165
+
166
+ return wanted_position
167
+
97
168
  def _build_rebalance_trades_from_positions(
98
169
  self,
99
170
  existing_position: ExistingPosition | None,
@@ -160,12 +231,12 @@ class BettingStrategy(ABC):
160
231
 
161
232
 
162
233
  class MultiCategoricalMaxAccuracyBettingStrategy(BettingStrategy):
163
- def __init__(self, bet_amount: USD):
164
- self.bet_amount = bet_amount
234
+ def __init__(self, max_position_amount: USD):
235
+ self.max_position_amount = max_position_amount
165
236
 
166
237
  @property
167
238
  def maximum_possible_bet_amount(self) -> USD:
168
- return self.bet_amount
239
+ return self.max_position_amount
169
240
 
170
241
  @staticmethod
171
242
  def calculate_direction(
@@ -196,11 +267,23 @@ class MultiCategoricalMaxAccuracyBettingStrategy(BettingStrategy):
196
267
  market: AgentMarket,
197
268
  ) -> list[Trade]:
198
269
  """We place bet on only one outcome."""
199
-
200
270
  outcome_to_bet_on = self.calculate_direction(market, answer)
201
271
 
272
+ # Will be lowered if the amount that we would need to buy would be unprofitable.
273
+ actual_wanted_position = BettingStrategy.cap_to_profitable_position(
274
+ market,
275
+ (
276
+ existing_position.amounts_current.get(outcome_to_bet_on, USD(0))
277
+ if existing_position
278
+ else USD(0)
279
+ ),
280
+ self.max_position_amount,
281
+ outcome_to_bet_on,
282
+ )
283
+
202
284
  target_position = Position(
203
- market_id=market.id, amounts_current={outcome_to_bet_on: self.bet_amount}
285
+ market_id=market.id,
286
+ amounts_current={outcome_to_bet_on: actual_wanted_position},
204
287
  )
205
288
  trades = self._build_rebalance_trades_from_positions(
206
289
  existing_position=existing_position,
@@ -253,13 +336,13 @@ class MaxExpectedValueBettingStrategy(MultiCategoricalMaxAccuracyBettingStrategy
253
336
 
254
337
 
255
338
  class KellyBettingStrategy(BettingStrategy):
256
- def __init__(self, max_bet_amount: USD, max_price_impact: float | None = None):
257
- self.max_bet_amount = max_bet_amount
339
+ def __init__(self, max_position_amount: USD, max_price_impact: float | None = None):
340
+ self.max_position_amount = max_position_amount
258
341
  self.max_price_impact = max_price_impact
259
342
 
260
343
  @property
261
344
  def maximum_possible_bet_amount(self) -> USD:
262
- return self.max_bet_amount
345
+ return self.max_position_amount
263
346
 
264
347
  @staticmethod
265
348
  def get_kelly_bet(
@@ -321,7 +404,7 @@ class KellyBettingStrategy(BettingStrategy):
321
404
 
322
405
  kelly_bet = self.get_kelly_bet(
323
406
  market=market,
324
- max_bet_amount=self.max_bet_amount,
407
+ max_bet_amount=self.max_position_amount,
325
408
  direction=direction,
326
409
  other_direction=other_direction,
327
410
  answer=answer,
@@ -405,16 +488,16 @@ class KellyBettingStrategy(BettingStrategy):
405
488
  return CollateralToken(optimized_bet_amount.x)
406
489
 
407
490
  def __repr__(self) -> str:
408
- return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount}, max_price_impact={self.max_price_impact})"
491
+ return f"{self.__class__.__name__}(max_bet_amount={self.max_position_amount}, max_price_impact={self.max_price_impact})"
409
492
 
410
493
 
411
494
  class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
412
- def __init__(self, max_bet_amount: USD):
413
- self.max_bet_amount = max_bet_amount
495
+ def __init__(self, max_position_amount: USD):
496
+ self.max_position_amount = max_position_amount
414
497
 
415
498
  @property
416
499
  def maximum_possible_bet_amount(self) -> USD:
417
- return self.max_bet_amount
500
+ return self.max_position_amount
418
501
 
419
502
  def adjust_bet_amount(
420
503
  self, existing_position: ExistingPosition | None, market: AgentMarket
@@ -422,7 +505,7 @@ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
422
505
  existing_position_total_amount = (
423
506
  existing_position.total_amount_current if existing_position else USD(0)
424
507
  )
425
- return self.max_bet_amount + existing_position_total_amount
508
+ return self.max_position_amount + existing_position_total_amount
426
509
 
427
510
  def calculate_trades(
428
511
  self,
@@ -471,4 +554,4 @@ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
471
554
  return trades
472
555
 
473
556
  def __repr__(self) -> str:
474
- return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount})"
557
+ return f"{self.__class__.__name__}(max_bet_amount={self.max_position_amount})"
@@ -93,7 +93,7 @@ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
93
93
 
94
94
  def get_job_trade(self, max_bond: USD, result: str) -> Trade:
95
95
  # Because jobs are powered by prediction markets, potentional reward depends on job's liquidity and our will to bond (bet) our xDai into our job completion.
96
- strategy = KellyBettingStrategy(max_bet_amount=max_bond)
96
+ strategy = KellyBettingStrategy(max_position_amount=max_bond)
97
97
  required_trades = strategy.calculate_trades(
98
98
  existing_position=None,
99
99
  answer=self.get_job_answer(result),
@@ -15,7 +15,7 @@ from prediction_market_agent_tooling.gtypes import (
15
15
  Probability,
16
16
  )
17
17
  from prediction_market_agent_tooling.logprobs_parser import FieldLogprobs
18
- from prediction_market_agent_tooling.markets.omen.omen import (
18
+ from prediction_market_agent_tooling.markets.omen.omen_constants import (
19
19
  OMEN_FALSE_OUTCOME,
20
20
  OMEN_TRUE_OUTCOME,
21
21
  )
@@ -14,13 +14,13 @@ class QuestionType(str, Enum):
14
14
  class AggregationItem(BaseModel):
15
15
  start_time: DatetimeUTC
16
16
  end_time: DatetimeUTC | None
17
- forecast_values: list[float] | None
17
+ forecast_values: list[float] | None = None
18
18
  forecaster_count: int
19
19
  interval_lower_bounds: list[float] | None
20
20
  centers: list[float] | None
21
21
  interval_upper_bounds: list[float] | None
22
- means: list[float] | None
23
- histogram: list[list[float]] | None
22
+ means: list[float] | None = None
23
+ histogram: list[list[float]] | None = None
24
24
 
25
25
 
26
26
  class Aggregation(BaseModel):
@@ -3,7 +3,7 @@ import os
3
3
  from web3 import Web3
4
4
 
5
5
  from prediction_market_agent_tooling.config import APIKeys
6
- from prediction_market_agent_tooling.gtypes import ABI, HexBytes
6
+ from prediction_market_agent_tooling.gtypes import ABI, ChecksumAddress, HexBytes
7
7
  from prediction_market_agent_tooling.tools.contract import (
8
8
  ContractOnGnosisChain,
9
9
  abi_field_validator,
@@ -19,6 +19,10 @@ class CowGPv2SettlementContract(ContractOnGnosisChain):
19
19
  )
20
20
  )
21
21
 
22
+ address: ChecksumAddress = Web3.to_checksum_address(
23
+ "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"
24
+ )
25
+
22
26
  def setPreSignature(
23
27
  self,
24
28
  api_keys: APIKeys,
@@ -23,6 +23,10 @@ from prediction_market_agent_tooling.markets.data_models import (
23
23
  Resolution,
24
24
  ResolvedBet,
25
25
  )
26
+ from prediction_market_agent_tooling.markets.omen.omen_constants import (
27
+ OMEN_FALSE_OUTCOME,
28
+ OMEN_TRUE_OUTCOME,
29
+ )
26
30
  from prediction_market_agent_tooling.tools.contract import (
27
31
  ContractERC20OnGnosisChain,
28
32
  init_collateral_token_contract,
@@ -37,8 +41,6 @@ from prediction_market_agent_tooling.tools.utils import (
37
41
  utcnow,
38
42
  )
39
43
 
40
- OMEN_TRUE_OUTCOME = OutcomeStr("Yes")
41
- OMEN_FALSE_OUTCOME = OutcomeStr("No")
42
44
  OMEN_BINARY_MARKET_OUTCOMES: t.Sequence[OutcomeStr] = [
43
45
  OMEN_TRUE_OUTCOME,
44
46
  OMEN_FALSE_OUTCOME,
@@ -104,6 +104,7 @@ class OmenAgentMarket(AgentMarket):
104
104
 
105
105
  collateral_token_contract_address_checksummed: ChecksumAddress
106
106
  market_maker_contract_address_checksummed: ChecksumAddress
107
+ outcome_token_pool: dict[OutcomeStr, OutcomeToken]
107
108
  condition: Condition
108
109
  finalized_time: DatetimeUTC | None
109
110
  created_time: DatetimeUTC
@@ -620,11 +621,10 @@ class OmenAgentMarket(AgentMarket):
620
621
  Note: this is only valid if the market instance's token pool is
621
622
  up-to-date with the smart contract.
622
623
  """
623
- outcome_token_pool = check_not_none(self.outcome_token_pool)
624
624
  amount = get_buy_outcome_token_amount(
625
625
  investment_amount=self.get_in_token(bet_amount),
626
626
  outcome_index=self.get_outcome_index(outcome),
627
- pool_balances=[outcome_token_pool[x] for x in self.outcomes],
627
+ pool_balances=[self.outcome_token_pool[x] for x in self.outcomes],
628
628
  fees=self.fees,
629
629
  )
630
630
  return amount
@@ -1,5 +1,10 @@
1
1
  from web3 import Web3
2
2
 
3
+ from prediction_market_agent_tooling.gtypes import OutcomeStr
4
+
5
+ OMEN_TRUE_OUTCOME = OutcomeStr("Yes")
6
+ OMEN_FALSE_OUTCOME = OutcomeStr("No")
7
+
3
8
  WRAPPED_XDAI_CONTRACT_ADDRESS = Web3.to_checksum_address(
4
9
  "0xe91d153e0b41518a2ce8dd3d7944fa863463a97d"
5
10
  )
@@ -2,6 +2,7 @@ import asyncio
2
2
  import typing as t
3
3
  from datetime import timedelta
4
4
 
5
+ from cowdao_cowpy.common.api.errors import UnexpectedResponseError
5
6
  from eth_typing import ChecksumAddress
6
7
  from web3 import Web3
7
8
  from web3.types import TxReceipt
@@ -61,7 +62,6 @@ from prediction_market_agent_tooling.tools.contract import (
61
62
  to_gnosis_chain_contract,
62
63
  )
63
64
  from prediction_market_agent_tooling.tools.cow.cow_order import (
64
- cancel_order,
65
65
  get_buy_token_amount_else_raise,
66
66
  get_orders_by_owner,
67
67
  get_trades_by_owner,
@@ -198,9 +198,7 @@ class SeerAgentMarket(AgentMarket):
198
198
  )
199
199
  )
200
200
 
201
- amounts_ot[
202
- OutcomeStr(outcome_str)
203
- ] = outcome_token_balance_wei.as_outcome_token
201
+ amounts_ot[outcome_str] = outcome_token_balance_wei.as_outcome_token
204
202
 
205
203
  amounts_current = {
206
204
  k: self.get_token_in_usd(self.get_sell_value_of_outcome_token(k, v))
@@ -481,26 +479,32 @@ class SeerAgentMarket(AgentMarket):
481
479
  Returns:
482
480
  Transaction hash of the successful swap
483
481
  """
484
- _, order = swap_tokens_waiting(
485
- amount_wei=amount_wei,
486
- sell_token=sell_token,
487
- buy_token=buy_token,
488
- api_keys=api_keys,
489
- web3=web3,
490
- wait_order_complete=False,
491
- )
492
482
 
493
483
  try:
484
+ _, order = swap_tokens_waiting(
485
+ amount_wei=amount_wei,
486
+ sell_token=sell_token,
487
+ buy_token=buy_token,
488
+ api_keys=api_keys,
489
+ web3=web3,
490
+ wait_order_complete=False,
491
+ timeout=timedelta(minutes=2),
492
+ )
494
493
  order_metadata = asyncio.run(wait_for_order_completion(order=order))
495
494
  logger.debug(
496
495
  f"Swapped {sell_token} for {buy_token}. Order details {order_metadata}"
497
496
  )
498
497
  return order_metadata.uid.root
499
498
 
500
- except TimeoutError:
501
- # Since timeout occurred, we need to cancel the order before trying to swap again.
502
- asyncio.run(cancel_order(order_uids=[order.uid.root], api_keys=api_keys))
503
- logger.info("TimeoutError. Trying to swap directly on Swapr pools.")
499
+ except (UnexpectedResponseError, TimeoutError) as e:
500
+ # We don't retry if not enough balance.
501
+ if "InsufficientBalance" in str(e):
502
+ raise e
503
+ # Note that we don't need to cancel the order because we are setting
504
+ # timeout and valid_to in the order, thus the order simply expires.
505
+ logger.info(
506
+ f"Exception occured when swapping tokens via Cowswap, doing swap via pools. {e}"
507
+ )
504
508
 
505
509
  tx_receipt = SwapPoolHandler(
506
510
  api_keys=api_keys,
@@ -55,7 +55,8 @@ from prediction_market_agent_tooling.markets.omen.cow_contracts import (
55
55
  )
56
56
  from prediction_market_agent_tooling.tools.contract import ContractERC20OnGnosisChain
57
57
  from prediction_market_agent_tooling.tools.cow.models import MinimalisticToken, Order
58
- from prediction_market_agent_tooling.tools.utils import check_not_none, utcnow
58
+ from prediction_market_agent_tooling.tools.cow.semaphore import postgres_rate_limited
59
+ from prediction_market_agent_tooling.tools.utils import utcnow
59
60
 
60
61
 
61
62
  class OrderStatusError(Exception):
@@ -190,7 +191,11 @@ def handle_allowance(
190
191
  )
191
192
 
192
193
 
194
+ @postgres_rate_limited(
195
+ api_keys=APIKeys(), rate_id="swap_tokens_waiting", interval_seconds=60.0
196
+ )
193
197
  @tenacity.retry(
198
+ reraise=True,
194
199
  stop=stop_after_attempt(3),
195
200
  wait=wait_fixed(1),
196
201
  retry=tenacity.retry_if_not_exception_type((TimeoutError, OrderStatusError)),
@@ -205,6 +210,7 @@ def swap_tokens_waiting(
205
210
  env: Envs = "prod",
206
211
  web3: Web3 | None = None,
207
212
  wait_order_complete: bool = True,
213
+ timeout: timedelta = timedelta(seconds=120),
208
214
  ) -> tuple[OrderMetaData | None, CompletedOrder]:
209
215
  # CoW library uses async, so we need to wrap the call in asyncio.run for us to use it.
210
216
  return asyncio.run(
@@ -215,6 +221,7 @@ def swap_tokens_waiting(
215
221
  api_keys,
216
222
  chain,
217
223
  env,
224
+ timeout=timeout,
218
225
  web3=web3,
219
226
  wait_order_complete=wait_order_complete,
220
227
  )
@@ -229,6 +236,7 @@ async def place_swap_order(
229
236
  chain: Chain,
230
237
  env: Envs,
231
238
  slippage_tolerance: float = 0.01,
239
+ valid_to: int | None = None,
232
240
  ) -> CompletedOrder:
233
241
  account = api_keys.get_account()
234
242
  safe_address = api_keys.safe_address_checksum
@@ -242,6 +250,7 @@ async def place_swap_order(
242
250
  chain=chain,
243
251
  env=env,
244
252
  slippage_tolerance=slippage_tolerance,
253
+ valid_to=valid_to,
245
254
  )
246
255
  logger.info(f"Order created: {order}")
247
256
 
@@ -299,6 +308,7 @@ async def swap_tokens_waiting_async(
299
308
  handle_allowance(
300
309
  api_keys=api_keys, sell_token=sell_token, amount_wei=amount_wei, web3=web3
301
310
  )
311
+ valid_to = (utcnow() + timeout).timestamp()
302
312
  order = await place_swap_order(
303
313
  api_keys=api_keys,
304
314
  amount_wei=amount_wei,
@@ -307,6 +317,7 @@ async def swap_tokens_waiting_async(
307
317
  chain=chain,
308
318
  env=env,
309
319
  slippage_tolerance=slippage_tolerance,
320
+ valid_to=int(valid_to),
310
321
  )
311
322
  if wait_order_complete:
312
323
  order_metadata = await wait_for_order_completion(order=order, timeout=timeout)
@@ -327,11 +338,8 @@ async def sign_safe_cow_swap(
327
338
  ) -> None:
328
339
  order_book_api = get_order_book_api(env, chain)
329
340
  posted_order = await order_book_api.get_order_by_uid(order.uid)
330
- CowGPv2SettlementContract(
331
- address=Web3.to_checksum_address(
332
- check_not_none(posted_order.settlementContract).root
333
- )
334
- ).setPreSignature(
341
+
342
+ CowGPv2SettlementContract().setPreSignature(
335
343
  api_keys,
336
344
  HexBytes(posted_order.uid.root),
337
345
  True,
@@ -1,7 +1,9 @@
1
1
  from pydantic import BaseModel
2
+ from sqlmodel import Field, SQLModel
2
3
 
3
4
  from prediction_market_agent_tooling.gtypes import ChecksumAddress
4
5
  from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC
6
+ from prediction_market_agent_tooling.tools.utils import utcnow
5
7
 
6
8
 
7
9
  class MinimalisticToken(BaseModel):
@@ -14,3 +16,9 @@ class Order(BaseModel):
14
16
  sellToken: str
15
17
  buyToken: str
16
18
  creationDate: DatetimeUTC
19
+
20
+
21
+ class RateLimit(SQLModel, table=True):
22
+ __tablename__ = "rate_limit"
23
+ id: str = Field(primary_key=True)
24
+ last_called_at: DatetimeUTC = Field(default_factory=utcnow)
@@ -0,0 +1,101 @@
1
+ import time
2
+ from datetime import timedelta
3
+ from functools import wraps
4
+ from typing import Any, Callable, Optional, TypeVar, cast
5
+
6
+ from sqlalchemy.exc import OperationalError
7
+ from sqlmodel import Session, select
8
+
9
+ from prediction_market_agent_tooling.config import APIKeys
10
+ from prediction_market_agent_tooling.tools.cow.models import RateLimit
11
+ from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC
12
+ from prediction_market_agent_tooling.tools.db.db_manager import DBManager
13
+ from prediction_market_agent_tooling.tools.utils import utcnow
14
+
15
+ F = TypeVar("F", bound=Callable[..., Any])
16
+
17
+ FALLBACK_SQL_ENGINE = "sqlite:///rate_limit.db"
18
+
19
+
20
+ def postgres_rate_limited(
21
+ api_keys: APIKeys, rate_id: str = "default", interval_seconds: float = 1.0
22
+ ) -> Callable[[F], F]:
23
+ """rate_id is used to distinguish between different rate limits for different functions"""
24
+ limiter = RateLimiter(id=rate_id, interval_seconds=interval_seconds)
25
+
26
+ def decorator(func: F) -> F:
27
+ @wraps(func)
28
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
29
+ sqlalchemy_db_url = (
30
+ api_keys.sqlalchemy_db_url.get_secret_value()
31
+ if api_keys.SQLALCHEMY_DB_URL
32
+ else FALLBACK_SQL_ENGINE
33
+ )
34
+
35
+ db_manager = DBManager(sqlalchemy_db_url)
36
+ db_manager.create_tables([RateLimit])
37
+
38
+ with db_manager.get_session() as session:
39
+ limiter.enforce(session)
40
+ return func(*args, **kwargs)
41
+
42
+ return cast(F, wrapper)
43
+
44
+ return decorator
45
+
46
+
47
+ class RateLimiter:
48
+ def __init__(self, id: str, interval_seconds: float = 1.0) -> None:
49
+ self.id = id
50
+ self.interval = timedelta(seconds=interval_seconds)
51
+
52
+ def enforce(self, session: Session, timeout_seconds: float = 30.0) -> None:
53
+ """
54
+ Enforces the rate limit inside a transaction.
55
+ Blocks until allowed or timeout is reached.
56
+
57
+ Args:
58
+ session: The database session to use
59
+ timeout_seconds: Maximum time in seconds to wait before giving up
60
+
61
+ Raises:
62
+ TimeoutError: If the rate limit cannot be acquired within the timeout period
63
+ """
64
+ start_time = time.monotonic()
65
+
66
+ while True:
67
+ try:
68
+ with session.begin():
69
+ stmt = (
70
+ select(RateLimit)
71
+ .where(RateLimit.id == self.id)
72
+ .with_for_update()
73
+ )
74
+ result: Optional[RateLimit] = session.exec(stmt).first()
75
+
76
+ now = utcnow()
77
+
78
+ if result is None:
79
+ # First time this limiter is used
80
+ session.add(RateLimit(id=self.id))
81
+ return
82
+
83
+ last_called_aware = DatetimeUTC.from_datetime(result.last_called_at)
84
+ elapsed = now - last_called_aware
85
+ if elapsed >= self.interval:
86
+ result.last_called_at = now
87
+ session.add(result)
88
+ return
89
+
90
+ # Not enough time passed, sleep and retry
91
+ to_sleep = (self.interval - elapsed).total_seconds()
92
+ time.sleep(to_sleep)
93
+ except OperationalError:
94
+ # Backoff if DB is under contention
95
+ elapsed_time = time.monotonic() - start_time
96
+ if elapsed_time > timeout_seconds:
97
+ raise TimeoutError(
98
+ f"Could not acquire rate limit '{self.id}' "
99
+ f"after {elapsed_time:.1f} seconds due to database contention"
100
+ )
101
+ time.sleep(0.5)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "prediction-market-agent-tooling"
3
- version = "0.66.0.dev791"
3
+ version = "0.66.2"
4
4
  description = "Tools to benchmark, deploy and monitor prediction market agents."
5
5
  authors = ["Gnosis"]
6
6
  readme = "README.md"
@@ -55,7 +55,7 @@ hishel = "^0.0.31"
55
55
  pytest-postgresql = "^6.1.1"
56
56
  optuna = { version = "^4.1.0", optional = true}
57
57
  httpx = ">=0.25.2,<1.0.0"
58
- cowdao-cowpy-kongzii = "1.0.0rc2" # Use `cowdao-cowpy` once they release latest version.
58
+ cowdao-cowpy = "1.0.0rc5"
59
59
  eth-keys = "^0.6.1"
60
60
  proto-plus = "^1.0.0"
61
61
  protobuf = "^5.0.0"