-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
496 seer market creation on pmat (#606)
* WIP * Added test for create Seer market * Fixed Seer subgraph invocations * Bumped version * Added script for creating seer markets * Script working * Fixed isort * Tried to fix tests * Adding more logs to debug test * Fetching market from event logs * Adding PR comments * Trying magic for fixing tests * Trying to make test pass * Trying to make test pass (2) * Sending to a differente agent * Trying test again * Contract reverted to old state * Removed optional fields
- Loading branch information
1 parent
38443ef
commit 231c5c3
Showing
12 changed files
with
1,327 additions
and
418 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
609 changes: 609 additions & 0 deletions
609
prediction_market_agent_tooling/abis/seer_market_factory.abi.json
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
from eth_typing import ChecksumAddress | ||
from web3 import Web3 | ||
from web3.types import TxReceipt | ||
|
||
from prediction_market_agent_tooling.config import APIKeys | ||
from prediction_market_agent_tooling.gtypes import xDai | ||
from prediction_market_agent_tooling.markets.seer.data_models import NewMarketEvent | ||
from prediction_market_agent_tooling.markets.seer.seer_contracts import ( | ||
SeerMarketFactory, | ||
) | ||
from prediction_market_agent_tooling.tools.contract import ( | ||
auto_deposit_collateral_token, | ||
init_collateral_token_contract, | ||
to_gnosis_chain_contract, | ||
) | ||
from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC | ||
from prediction_market_agent_tooling.tools.web3_utils import xdai_to_wei | ||
|
||
|
||
def seer_create_market_tx( | ||
api_keys: APIKeys, | ||
initial_funds: xDai, | ||
question: str, | ||
opening_time: DatetimeUTC, | ||
language: str, | ||
outcomes: list[str], | ||
auto_deposit: bool, | ||
category: str, | ||
min_bond_xdai: xDai, | ||
web3: Web3 | None = None, | ||
) -> ChecksumAddress: | ||
web3 = web3 or SeerMarketFactory.get_web3() # Default to Gnosis web3. | ||
initial_funds_wei = xdai_to_wei(initial_funds) | ||
|
||
factory_contract = SeerMarketFactory() | ||
collateral_token_address = factory_contract.collateral_token(web3=web3) | ||
collateral_token_contract = to_gnosis_chain_contract( | ||
init_collateral_token_contract(collateral_token_address, web3) | ||
) | ||
|
||
if auto_deposit: | ||
auto_deposit_collateral_token( | ||
collateral_token_contract=collateral_token_contract, | ||
api_keys=api_keys, | ||
amount_wei=initial_funds_wei, | ||
web3=web3, | ||
) | ||
|
||
# In case of ERC4626, obtained (for example) sDai out of xDai could be lower than the `amount_wei`, so we need to handle it. | ||
initial_funds_in_shares = collateral_token_contract.get_in_shares( | ||
amount=initial_funds_wei, web3=web3 | ||
) | ||
|
||
# Approve the market maker to withdraw our collateral token. | ||
collateral_token_contract.approve( | ||
api_keys=api_keys, | ||
for_address=factory_contract.address, | ||
amount_wei=initial_funds_in_shares, | ||
web3=web3, | ||
) | ||
|
||
# Create the market. | ||
params = factory_contract.build_market_params( | ||
market_question=question, | ||
outcomes=outcomes, | ||
opening_time=opening_time, | ||
language=language, | ||
category=category, | ||
min_bond_xdai=min_bond_xdai, | ||
) | ||
tx_receipt = factory_contract.create_categorical_market( | ||
api_keys=api_keys, params=params, web3=web3 | ||
) | ||
|
||
# ToDo - Add liquidity to market on Swapr (https://github.com/gnosis/prediction-market-agent-tooling/issues/497) | ||
market_address = extract_market_address_from_tx( | ||
factory_contract=factory_contract, tx_receipt=tx_receipt, web3=web3 | ||
) | ||
return market_address | ||
|
||
|
||
def extract_market_address_from_tx( | ||
factory_contract: SeerMarketFactory, tx_receipt: TxReceipt, web3: Web3 | ||
) -> ChecksumAddress: | ||
"""We extract the newly created market from the NewMarket event emitted in the transaction.""" | ||
event_logs = ( | ||
factory_contract.get_web3_contract(web3=web3) | ||
.events.NewMarket() | ||
.process_receipt(tx_receipt) | ||
) | ||
new_market_event = NewMarketEvent(**event_logs[0]["args"]) | ||
return Web3.to_checksum_address(new_market_event.market) |
76 changes: 76 additions & 0 deletions
76
prediction_market_agent_tooling/markets/seer/seer_contracts.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import os | ||
|
||
from web3 import Web3 | ||
from web3.types import TxReceipt | ||
|
||
from prediction_market_agent_tooling.config import APIKeys | ||
from prediction_market_agent_tooling.gtypes import ABI, ChecksumAddress, xDai | ||
from prediction_market_agent_tooling.markets.seer.data_models import ( | ||
CreateCategoricalMarketsParams, | ||
) | ||
from prediction_market_agent_tooling.tools.contract import ( | ||
ContractOnGnosisChain, | ||
abi_field_validator, | ||
) | ||
from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC | ||
from prediction_market_agent_tooling.tools.web3_utils import xdai_to_wei | ||
|
||
|
||
class SeerMarketFactory(ContractOnGnosisChain): | ||
# https://gnosisscan.io/address/0x83183da839ce8228e31ae41222ead9edbb5cdcf1#code. | ||
abi: ABI = abi_field_validator( | ||
os.path.join( | ||
os.path.dirname(os.path.realpath(__file__)), | ||
"../../abis/seer_market_factory.abi.json", | ||
) | ||
) | ||
address: ChecksumAddress = Web3.to_checksum_address( | ||
"0x83183da839ce8228e31ae41222ead9edbb5cdcf1" | ||
) | ||
|
||
@staticmethod | ||
def build_market_params( | ||
market_question: str, | ||
outcomes: list[str], | ||
opening_time: DatetimeUTC, | ||
min_bond_xdai: xDai, | ||
language: str = "en_US", | ||
category: str = "misc", | ||
) -> CreateCategoricalMarketsParams: | ||
return CreateCategoricalMarketsParams( | ||
market_name=market_question, | ||
token_names=[ | ||
o.upper() for o in outcomes | ||
], # Following usual token names on Seer (YES,NO). | ||
min_bond=xdai_to_wei(min_bond_xdai), | ||
opening_time=int(opening_time.timestamp()), | ||
outcomes=outcomes, | ||
lang=language, | ||
category=category, | ||
) | ||
|
||
def market_count(self, web3: Web3 | None = None) -> int: | ||
count: int = self.call("marketCount", web3=web3) | ||
return count | ||
|
||
def market_at_index(self, index: int, web3: Web3 | None = None) -> ChecksumAddress: | ||
market_address: str = self.call("markets", function_params=[index], web3=web3) | ||
return Web3.to_checksum_address(market_address) | ||
|
||
def collateral_token(self, web3: Web3 | None = None) -> ChecksumAddress: | ||
collateral_token_address: str = self.call("collateralToken", web3=web3) | ||
return Web3.to_checksum_address(collateral_token_address) | ||
|
||
def create_categorical_market( | ||
self, | ||
api_keys: APIKeys, | ||
params: CreateCategoricalMarketsParams, | ||
web3: Web3 | None = None, | ||
) -> TxReceipt: | ||
receipt_tx = self.send( | ||
api_keys=api_keys, | ||
function_name="createCategoricalMarket", | ||
function_params=[params.model_dump(by_alias=True)], | ||
web3=web3, | ||
) | ||
return receipt_tx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from datetime import datetime | ||
|
||
import typer | ||
from web3 import Web3 | ||
|
||
from prediction_market_agent_tooling.config import APIKeys | ||
from prediction_market_agent_tooling.gtypes import private_key_type, xdai_type | ||
from prediction_market_agent_tooling.loggers import logger | ||
from prediction_market_agent_tooling.markets.omen.data_models import ( | ||
OMEN_BINARY_MARKET_OUTCOMES, | ||
) | ||
from prediction_market_agent_tooling.markets.seer.seer import seer_create_market_tx | ||
from prediction_market_agent_tooling.tools.utils import DatetimeUTC | ||
|
||
|
||
def main( | ||
question: str = typer.Option(), | ||
opening_time: datetime = typer.Option(), | ||
category: str = typer.Option(), | ||
initial_funds: str = typer.Option(), | ||
from_private_key: str = typer.Option(), | ||
safe_address: str = typer.Option(None), | ||
min_bond_xdai: int = typer.Option(0.01), | ||
language: str = typer.Option("en_US"), | ||
outcomes: list[str] = typer.Option(OMEN_BINARY_MARKET_OUTCOMES), | ||
auto_deposit: bool = typer.Option(False), | ||
) -> None: | ||
""" | ||
Creates a market on Seer. | ||
Args: | ||
question (str): The question for the market. | ||
opening_time (datetime): The opening time for the market. | ||
category (str): The category of the market. | ||
initial_funds (str): The initial funds for the market. | ||
from_private_key (str): The private key to use for transactions. | ||
safe_address (str, optional): The safe address for transactions. Defaults to None. | ||
min_bond_xdai (int, optional): The minimum bond in xDai. Defaults to 0.01 xDai. | ||
language (str, optional): The language of the market. Defaults to "en". | ||
outcomes (list[str], optional): The outcomes for the market. Defaults to OMEN_BINARY_MARKET_OUTCOMES. | ||
auto_deposit (bool, optional): Whether to automatically deposit funds. Defaults to False. | ||
Returns: | ||
None | ||
""" | ||
safe_address_checksum = ( | ||
Web3.to_checksum_address(safe_address) if safe_address else None | ||
) | ||
api_keys = APIKeys( | ||
BET_FROM_PRIVATE_KEY=private_key_type(from_private_key), | ||
SAFE_ADDRESS=safe_address_checksum, | ||
) | ||
market = seer_create_market_tx( | ||
api_keys=api_keys, | ||
initial_funds=xdai_type(initial_funds), | ||
question=question, | ||
opening_time=DatetimeUTC.from_datetime(opening_time), | ||
category=category, | ||
language=language, | ||
outcomes=outcomes, | ||
auto_deposit=auto_deposit, | ||
min_bond_xdai=xdai_type(min_bond_xdai), | ||
) | ||
logger.info(f"Market created: {market}") | ||
|
||
|
||
if __name__ == "__main__": | ||
typer.run(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
tests_integration_with_local_chain/markets/seer/test_seer_contracts.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from web3 import Web3 | ||
|
||
from prediction_market_agent_tooling.config import APIKeys | ||
from prediction_market_agent_tooling.gtypes import xDai, xdai_type | ||
from prediction_market_agent_tooling.markets.seer.data_models import ( | ||
CreateCategoricalMarketsParams, | ||
) | ||
from prediction_market_agent_tooling.markets.seer.seer_contracts import ( | ||
SeerMarketFactory, | ||
) | ||
from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC | ||
|
||
|
||
def build_params() -> CreateCategoricalMarketsParams: | ||
return SeerMarketFactory.build_market_params( | ||
market_question="test test test", | ||
outcomes=["Yes", "No"], | ||
opening_time=DatetimeUTC.now(), | ||
language="en_US", | ||
category="misc", | ||
min_bond_xdai=xdai_type(xDai(0.01)), | ||
) | ||
|
||
|
||
def test_create_market(local_web3: Web3, test_keys: APIKeys) -> None: | ||
factory = SeerMarketFactory() | ||
num_initial_markets = factory.market_count(web3=local_web3) | ||
params = build_params() | ||
factory.create_categorical_market( | ||
api_keys=test_keys, params=params, web3=local_web3 | ||
) | ||
|
||
num_final_markets = factory.market_count(web3=local_web3) | ||
assert num_initial_markets + 1 == num_final_markets |
Oops, something went wrong.