prediction-market-agent-tooling 0.43.2__py3-none-any.whl → 0.43.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +279 -0
  2. prediction_market_agent_tooling/abis/erc20.abi.json +221 -314
  3. prediction_market_agent_tooling/abis/erc4626.abi.json +623 -0
  4. prediction_market_agent_tooling/abis/proxy.abi.json +24 -0
  5. prediction_market_agent_tooling/gtypes.py +1 -1
  6. prediction_market_agent_tooling/markets/agent_market.py +2 -1
  7. prediction_market_agent_tooling/markets/manifold/manifold.py +3 -2
  8. prediction_market_agent_tooling/markets/omen/data_models.py +2 -1
  9. prediction_market_agent_tooling/markets/omen/omen.py +73 -38
  10. prediction_market_agent_tooling/markets/omen/omen_contracts.py +43 -12
  11. prediction_market_agent_tooling/markets/omen/omen_resolving.py +15 -5
  12. prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +9 -0
  13. prediction_market_agent_tooling/markets/polymarket/polymarket.py +2 -1
  14. prediction_market_agent_tooling/tools/contract.py +303 -11
  15. {prediction_market_agent_tooling-0.43.2.dist-info → prediction_market_agent_tooling-0.43.4.dist-info}/METADATA +1 -1
  16. {prediction_market_agent_tooling-0.43.2.dist-info → prediction_market_agent_tooling-0.43.4.dist-info}/RECORD +19 -17
  17. prediction_market_agent_tooling/abis/wxdai.abi.json +0 -279
  18. {prediction_market_agent_tooling-0.43.2.dist-info → prediction_market_agent_tooling-0.43.4.dist-info}/LICENSE +0 -0
  19. {prediction_market_agent_tooling-0.43.2.dist-info → prediction_market_agent_tooling-0.43.4.dist-info}/WHEEL +0 -0
  20. {prediction_market_agent_tooling-0.43.2.dist-info → prediction_market_agent_tooling-0.43.4.dist-info}/entry_points.txt +0 -0
@@ -32,6 +32,7 @@ OMEN_TRUE_OUTCOME = "Yes"
32
32
  OMEN_FALSE_OUTCOME = "No"
33
33
  INVALID_ANSWER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
34
34
  OMEN_BASE_URL = "https://aiomen.eth.limo"
35
+ PRESAGIO_BASE_URL = "https://presagio.pages.dev"
35
36
 
36
37
 
37
38
  def get_boolean_outcome(outcome_str: str) -> bool:
@@ -325,7 +326,7 @@ class OmenMarket(BaseModel):
325
326
 
326
327
  @property
327
328
  def url(self) -> str:
328
- return f"{OMEN_BASE_URL}/#/{self.id}"
329
+ return f"{PRESAGIO_BASE_URL}/markets?id={self.id}"
329
330
 
330
331
 
331
332
  class OmenBetCreator(BaseModel):
@@ -2,6 +2,7 @@ import sys
2
2
  import typing as t
3
3
  from datetime import datetime
4
4
 
5
+ import tenacity
5
6
  from web3 import Web3
6
7
  from web3.constants import HASH_ZERO
7
8
 
@@ -32,9 +33,9 @@ from prediction_market_agent_tooling.markets.data_models import (
32
33
  TokenAmount,
33
34
  )
34
35
  from prediction_market_agent_tooling.markets.omen.data_models import (
35
- OMEN_BASE_URL,
36
36
  OMEN_FALSE_OUTCOME,
37
37
  OMEN_TRUE_OUTCOME,
38
+ PRESAGIO_BASE_URL,
38
39
  Condition,
39
40
  OmenBet,
40
41
  OmenMarket,
@@ -43,17 +44,24 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
43
44
  from prediction_market_agent_tooling.markets.omen.omen_contracts import (
44
45
  OMEN_DEFAULT_MARKET_FEE,
45
46
  Arbitrator,
46
- OmenCollateralTokenContract,
47
+ ContractDepositableWrapperERC20OnGnosisChain,
47
48
  OmenConditionalTokenContract,
48
49
  OmenFixedProductMarketMakerContract,
49
50
  OmenFixedProductMarketMakerFactoryContract,
50
51
  OmenOracleContract,
51
52
  OmenRealitioContract,
53
+ WrappedxDaiContract,
52
54
  )
53
55
  from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
54
56
  OmenSubgraphHandler,
55
57
  )
56
58
  from prediction_market_agent_tooling.tools.balances import get_balances
59
+ from prediction_market_agent_tooling.tools.contract import (
60
+ asset_or_shares,
61
+ auto_deposit_collateral_token,
62
+ init_erc4626_or_wrappererc20_or_erc20_contract,
63
+ to_gnosis_chain_contract,
64
+ )
57
65
  from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
58
66
  from prediction_market_agent_tooling.tools.utils import (
59
67
  calculate_sell_amount_in_collateral,
@@ -75,7 +83,7 @@ class OmenAgentMarket(AgentMarket):
75
83
  """
76
84
 
77
85
  currency: t.ClassVar[Currency] = Currency.xDai
78
- base_url: t.ClassVar[str] = OMEN_BASE_URL
86
+ base_url: t.ClassVar[str] = PRESAGIO_BASE_URL
79
87
  creator: HexAddress
80
88
 
81
89
  collateral_token_contract_address_checksummed: ChecksumAddress
@@ -134,11 +142,12 @@ class OmenAgentMarket(AgentMarket):
134
142
  def get_liquidity(self) -> TokenAmount:
135
143
  return TokenAmount(
136
144
  amount=self.get_liquidity_in_xdai(),
137
- currency=Currency.xDai,
145
+ currency=self.currency,
138
146
  )
139
147
 
140
- def get_tiny_bet_amount(self) -> BetAmount:
141
- return BetAmount(amount=0.00001, currency=self.currency)
148
+ @classmethod
149
+ def get_tiny_bet_amount(cls) -> BetAmount:
150
+ return BetAmount(amount=0.00001, currency=cls.currency)
142
151
 
143
152
  def place_bet(
144
153
  self,
@@ -381,7 +390,7 @@ class OmenAgentMarket(AgentMarket):
381
390
  )
382
391
  return TokenAmount(
383
392
  amount=wei_to_xdai(balances[index_set]),
384
- currency=Currency.xDai,
393
+ currency=self.currency,
385
394
  )
386
395
 
387
396
  @classmethod
@@ -437,7 +446,7 @@ class OmenAgentMarket(AgentMarket):
437
446
 
438
447
  amounts[outecome_str] = TokenAmount(
439
448
  amount=wei_to_xdai(omen_position.totalBalance),
440
- currency=Currency.xDai,
449
+ currency=cls.currency,
441
450
  )
442
451
 
443
452
  positions.append(Position(market_id=market.id, amounts=amounts))
@@ -503,7 +512,7 @@ class OmenAgentMarket(AgentMarket):
503
512
  no_price = check_not_none(market.get_last_trade_no_outcome_price())
504
513
  total_position_value += no_tokens * no_price
505
514
 
506
- return BetAmount(amount=total_position_value, currency=Currency.xDai)
515
+ return BetAmount(amount=total_position_value, currency=cls.currency)
507
516
 
508
517
  @classmethod
509
518
  def get_user_url(cls, keys: APIKeys) -> str:
@@ -523,6 +532,11 @@ def pick_binary_market(
523
532
  )[0]
524
533
 
525
534
 
535
+ @tenacity.retry(
536
+ stop=tenacity.stop_after_attempt(3),
537
+ wait=tenacity.wait_fixed(1),
538
+ after=lambda x: logger.debug(f"omen_buy_outcome_tx failed, {x.attempt_number=}."),
539
+ )
526
540
  def omen_buy_outcome_tx(
527
541
  api_keys: APIKeys,
528
542
  amount: xDai,
@@ -538,8 +552,10 @@ def omen_buy_outcome_tx(
538
552
  from_address_checksummed = api_keys.bet_from_address
539
553
 
540
554
  market_contract: OmenFixedProductMarketMakerContract = market.get_contract()
541
-
542
- collateral_token_contract = OmenCollateralTokenContract()
555
+ collateral_token_contract = market_contract.get_collateral_token_contract()
556
+ assert isinstance(
557
+ collateral_token_contract, ContractDepositableWrapperERC20OnGnosisChain
558
+ ), "TODO: Implement for the ERC-20 and ERC-4626 case."
543
559
 
544
560
  # Get the index of the outcome we want to buy.
545
561
  outcome_index: int = market.get_outcome_index(outcome)
@@ -614,7 +630,10 @@ def omen_sell_outcome_tx(
614
630
 
615
631
  market_contract: OmenFixedProductMarketMakerContract = market.get_contract()
616
632
  conditional_token_contract = OmenConditionalTokenContract()
617
- collateral_token = OmenCollateralTokenContract()
633
+ collateral_token_contract = market_contract.get_collateral_token_contract()
634
+ assert isinstance(
635
+ collateral_token_contract, ContractDepositableWrapperERC20OnGnosisChain
636
+ ), "TODO: Implement for the ERC-20 and ERC-4626 case."
618
637
 
619
638
  # Verify, that markets uses conditional tokens that we expect.
620
639
  if (
@@ -652,7 +671,9 @@ def omen_sell_outcome_tx(
652
671
  )
653
672
  if auto_withdraw:
654
673
  # Optionally, withdraw from the collateral token back to the `from_address` wallet.
655
- collateral_token.withdraw(api_keys=api_keys, amount_wei=amount_wei, web3=web3)
674
+ collateral_token_contract.withdraw(
675
+ api_keys=api_keys, amount_wei=amount_wei, web3=web3
676
+ )
656
677
 
657
678
 
658
679
  def binary_omen_sell_outcome_tx(
@@ -683,17 +704,22 @@ def omen_create_market_tx(
683
704
  outcomes: list[str],
684
705
  auto_deposit: bool,
685
706
  fee: float = OMEN_DEFAULT_MARKET_FEE,
707
+ collateral_token_address: ChecksumAddress = WrappedxDaiContract().address,
686
708
  web3: Web3 | None = None,
687
709
  ) -> ChecksumAddress:
688
710
  """
689
711
  Based on omen-exchange TypeScript code: https://github.com/protofire/omen-exchange/blob/b0b9a3e71b415d6becf21fe428e1c4fc0dad2e80/app/src/services/cpk/cpk.ts#L308
690
712
  """
691
- from_address = api_keys.bet_from_address
713
+ web3 = (
714
+ web3 or OmenFixedProductMarketMakerFactoryContract.get_web3()
715
+ ) # Default to Gnosis web3.
692
716
  initial_funds_wei = xdai_to_wei(initial_funds)
693
717
 
694
718
  realitio_contract = OmenRealitioContract()
695
719
  conditional_token_contract = OmenConditionalTokenContract()
696
- collateral_token_contract = OmenCollateralTokenContract()
720
+ collateral_token_contract = to_gnosis_chain_contract(
721
+ init_erc4626_or_wrappererc20_or_erc20_contract(collateral_token_address, web3)
722
+ )
697
723
  factory_contract = OmenFixedProductMarketMakerFactoryContract()
698
724
  oracle_contract = OmenOracleContract()
699
725
 
@@ -709,25 +735,14 @@ def omen_create_market_tx(
709
735
  "The oracle's conditional tokens address is not the same as we are using."
710
736
  )
711
737
 
712
- # Approve the market maker to withdraw our collateral token.
713
- collateral_token_contract.approve(
714
- api_keys=api_keys,
715
- for_address=factory_contract.address,
716
- amount_wei=initial_funds_wei,
717
- web3=web3,
718
- )
719
-
720
- # Deposit xDai to the collateral token,
721
- # this can be skipped, if we know we already have enough collateral tokens.
722
- collateral_token_balance = collateral_token_contract.balanceOf(
723
- for_address=from_address, web3=web3
724
- )
725
- if (
726
- auto_deposit
727
- and initial_funds_wei > 0
728
- and collateral_token_balance < initial_funds_wei
729
- ):
730
- collateral_token_contract.deposit(api_keys, initial_funds_wei, web3=web3)
738
+ # If auto deposit is enabled.
739
+ if auto_deposit:
740
+ auto_deposit_collateral_token(
741
+ collateral_token_contract=collateral_token_contract,
742
+ api_keys=api_keys,
743
+ amount_wei=initial_funds_wei,
744
+ web3=web3,
745
+ )
731
746
 
732
747
  # Create the question on Realitio.
733
748
  question_id = realitio_contract.askQuestion(
@@ -757,12 +772,29 @@ def omen_create_market_tx(
757
772
  web3=web3,
758
773
  )
759
774
 
775
+ # Use shares as the initial funds, if the collateral is erc-4626.
776
+ # We need to do this, because for example for 1 xDai in erc-20 token, we could receive <1 shares in the vault,
777
+ # and then, providing liquidity would fail, because we would not have enough shares.
778
+ initial_funds_in_asset_or_shares = wei_type(
779
+ asset_or_shares(collateral_token_contract, initial_funds_wei)
780
+ * 0.999 # Allow some slippage.
781
+ )
782
+
783
+ # Approve the market maker to withdraw our collateral token.
784
+ collateral_token_contract.approve(
785
+ api_keys=api_keys,
786
+ for_address=factory_contract.address,
787
+ amount_wei=initial_funds_in_asset_or_shares,
788
+ web3=web3,
789
+ )
790
+
760
791
  # Create the market.
761
792
  create_market_receipt_tx = factory_contract.create2FixedProductMarketMaker(
762
793
  api_keys=api_keys,
763
794
  condition_id=condition_id,
764
795
  fee=fee,
765
- initial_funds_wei=initial_funds_wei,
796
+ initial_funds_wei=initial_funds_in_asset_or_shares,
797
+ collateral_token_address=collateral_token_contract.address,
766
798
  web3=web3,
767
799
  )
768
800
 
@@ -786,7 +818,10 @@ def omen_fund_market_tx(
786
818
  ) -> None:
787
819
  from_address = api_keys.bet_from_address
788
820
  market_contract = market.get_contract()
789
- collateral_token_contract = OmenCollateralTokenContract()
821
+ collateral_token_contract = market_contract.get_collateral_token_contract()
822
+ assert isinstance(
823
+ collateral_token_contract, ContractDepositableWrapperERC20OnGnosisChain
824
+ ), "TODO: Implement for the ERC-20 and ERC-4626 case."
790
825
 
791
826
  # Deposit xDai to the collateral token,
792
827
  # this can be skipped, if we know we already have enough collateral tokens.
@@ -1052,8 +1087,8 @@ def withdraw_wxdai_to_xdai_to_keep_balance(
1052
1087
  f"Current wxDai balance {current_balances.wxdai} is less than the required minimum wxDai to withdraw {need_to_withdraw}."
1053
1088
  )
1054
1089
 
1055
- collateral_token_contract = OmenCollateralTokenContract()
1056
- collateral_token_contract.withdraw(
1090
+ wxdai_contract = WrappedxDaiContract()
1091
+ wxdai_contract.withdraw(
1057
1092
  api_keys=api_keys, amount_wei=xdai_to_wei(need_to_withdraw), web3=web3
1058
1093
  )
1059
1094
  logger.info(
@@ -23,9 +23,13 @@ from prediction_market_agent_tooling.gtypes import (
23
23
  xdai_type,
24
24
  )
25
25
  from prediction_market_agent_tooling.tools.contract import (
26
+ ContractDepositableWrapperERC20OnGnosisChain,
26
27
  ContractERC20OnGnosisChain,
28
+ ContractERC4626OnGnosisChain,
27
29
  ContractOnGnosisChain,
28
30
  abi_field_validator,
31
+ init_erc4626_or_wrappererc20_or_erc20_contract,
32
+ to_gnosis_chain_contract,
29
33
  )
30
34
  from prediction_market_agent_tooling.tools.web3_utils import (
31
35
  ZERO_BYTES,
@@ -291,9 +295,13 @@ class OmenFixedProductMarketMakerContract(ContractOnGnosisChain):
291
295
  )
292
296
  return calculated_shares
293
297
 
294
- def conditionalTokens(self, web3: Web3 | None = None) -> HexAddress:
298
+ def conditionalTokens(self, web3: Web3 | None = None) -> ChecksumAddress:
295
299
  address: HexAddress = self.call("conditionalTokens", web3=web3)
296
- return address
300
+ return Web3.to_checksum_address(address)
301
+
302
+ def collateralToken(self, web3: Web3 | None = None) -> ChecksumAddress:
303
+ address: HexAddress = self.call("collateralToken", web3=web3)
304
+ return Web3.to_checksum_address(address)
297
305
 
298
306
  def buy(
299
307
  self,
@@ -380,21 +388,32 @@ class OmenFixedProductMarketMakerContract(ContractOnGnosisChain):
380
388
  total_supply: Wei = self.call("totalSupply", web3=web3)
381
389
  return total_supply
382
390
 
383
-
384
- class WrappedxDaiContract(ContractERC20OnGnosisChain):
385
- # File content taken from https://gnosisscan.io/address/0xe91d153e0b41518a2ce8dd3d7944fa863463a97d#code.
386
- abi: ABI = abi_field_validator(
387
- os.path.join(
388
- os.path.dirname(os.path.realpath(__file__)), "../../abis/wxdai.abi.json"
391
+ def get_collateral_token_contract(
392
+ self, web3: Web3 | None = None
393
+ ) -> (
394
+ ContractERC20OnGnosisChain
395
+ | ContractERC4626OnGnosisChain
396
+ | ContractDepositableWrapperERC20OnGnosisChain
397
+ ):
398
+ web3 = web3 or self.get_web3()
399
+ return to_gnosis_chain_contract(
400
+ init_erc4626_or_wrappererc20_or_erc20_contract(
401
+ self.collateralToken(web3=web3), web3
402
+ )
389
403
  )
390
- )
404
+
405
+
406
+ class WrappedxDaiContract(ContractDepositableWrapperERC20OnGnosisChain):
391
407
  address: ChecksumAddress = Web3.to_checksum_address(
392
408
  "0xe91d153e0b41518a2ce8dd3d7944fa863463a97d"
393
409
  )
394
410
 
395
411
 
396
- # Collateral token used on Omen is wrapped xDai.
397
- OmenCollateralTokenContract = WrappedxDaiContract
412
+ class sDaiContract(ContractERC4626OnGnosisChain):
413
+ address: ChecksumAddress = Web3.to_checksum_address(
414
+ "0xaf204776c7245bF4147c2612BF6e5972Ee483701"
415
+ )
416
+
398
417
 
399
418
  OMEN_DEFAULT_MARKET_FEE = 0.02 # 2% fee from the buying shares amount.
400
419
 
@@ -416,6 +435,7 @@ class OmenFixedProductMarketMakerFactoryContract(ContractOnGnosisChain):
416
435
  api_keys: APIKeys,
417
436
  condition_id: HexBytes,
418
437
  initial_funds_wei: Wei,
438
+ collateral_token_address: ChecksumAddress,
419
439
  fee: float = OMEN_DEFAULT_MARKET_FEE,
420
440
  tx_params: t.Optional[TxParams] = None,
421
441
  web3: Web3 | None = None,
@@ -431,7 +451,7 @@ class OmenFixedProductMarketMakerFactoryContract(ContractOnGnosisChain):
431
451
  0, 1000000
432
452
  ), # See https://github.com/protofire/omen-exchange/blob/923756c3a9ac370f8e89af8193393a53531e2c0f/app/src/services/cpk/fns.ts#L942.
433
453
  conditionalTokens=OmenConditionalTokenContract().address,
434
- collateralToken=OmenCollateralTokenContract().address,
454
+ collateralToken=collateral_token_address,
435
455
  conditionIds=[condition_id],
436
456
  fee=fee_wei,
437
457
  initialFunds=initial_funds_wei,
@@ -678,3 +698,14 @@ class OmenThumbnailMapping(ContractOnGnosisChain):
678
698
  function_params=[market_address],
679
699
  web3=web3,
680
700
  )
701
+
702
+
703
+ class CollateralTokenChoice(str, Enum):
704
+ wxdai = "wxdai"
705
+ sdai = "sdai"
706
+
707
+
708
+ COLLATERAL_TOKEN_CHOICE_TO_ADDRESS = {
709
+ CollateralTokenChoice.wxdai: WrappedxDaiContract().address,
710
+ CollateralTokenChoice.sdai: sDaiContract().address,
711
+ }
@@ -40,6 +40,7 @@ def claim_bonds_on_realitio_questions(
40
40
  questions: list[RealityQuestion],
41
41
  auto_withdraw: bool,
42
42
  web3: Web3 | None = None,
43
+ silent_errors: bool = False,
43
44
  ) -> list[HexBytes]:
44
45
  claimed_questions: list[HexBytes] = []
45
46
 
@@ -47,10 +48,19 @@ def claim_bonds_on_realitio_questions(
47
48
  logger.info(
48
49
  f"[{idx+1} / {len(questions)}] Claiming bond for {question.questionId=} {question.url=}"
49
50
  )
50
- claim_bonds_on_realitio_question(
51
- api_keys, question, auto_withdraw=auto_withdraw, web3=web3
52
- )
53
- claimed_questions.append(question.questionId)
51
+ try:
52
+ claim_bonds_on_realitio_question(
53
+ api_keys, question, auto_withdraw=auto_withdraw, web3=web3
54
+ )
55
+ claimed_questions.append(question.questionId)
56
+ except Exception as e:
57
+ # TODO: This shouldn't be required once `claim_bonds_on_realitio_question` below is fixed.
58
+ if silent_errors:
59
+ logger.warning(
60
+ f"Error while claiming bond for {question.questionId=} {question.url=}: {e}"
61
+ )
62
+ else:
63
+ raise
54
64
 
55
65
  return claimed_questions
56
66
 
@@ -140,7 +150,7 @@ def finalize_markets(
140
150
  )
141
151
 
142
152
  if resolution is None:
143
- logger.error(f"No resolution provided for {market.url=}")
153
+ logger.warning(f"No resolution provided for {market.url=}")
144
154
 
145
155
  elif resolution in (Resolution.YES, Resolution.NO):
146
156
  logger.info(f"Found resolution {resolution.value=} for {market.url=}")
@@ -25,6 +25,7 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
25
25
  )
26
26
  from prediction_market_agent_tooling.markets.omen.omen_contracts import (
27
27
  OmenThumbnailMapping,
28
+ WrappedxDaiContract,
28
29
  )
29
30
  from prediction_market_agent_tooling.tools.singleton import SingletonMeta
30
31
  from prediction_market_agent_tooling.tools.utils import to_int_timestamp, utcnow
@@ -184,6 +185,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
184
185
  condition_id_in: list[HexBytes] | None = None,
185
186
  id_in: list[str] | None = None,
186
187
  excluded_questions: set[str] | None = None,
188
+ collateral_token_address: ChecksumAddress | None = None,
187
189
  ) -> dict[str, t.Any]:
188
190
  where_stms: dict[str, t.Any] = {
189
191
  "isPendingArbitration": False,
@@ -193,6 +195,9 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
193
195
  "condition_": {},
194
196
  }
195
197
 
198
+ if collateral_token_address:
199
+ where_stms["collateralToken"] = collateral_token_address.lower()
200
+
196
201
  if creator:
197
202
  where_stms["creator"] = creator
198
203
 
@@ -333,6 +338,9 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
333
338
  sort_by_field: FieldPath | None = None,
334
339
  sort_direction: str | None = None,
335
340
  outcomes: list[str] = [OMEN_TRUE_OUTCOME, OMEN_FALSE_OUTCOME],
341
+ collateral_token_address: (
342
+ ChecksumAddress | None
343
+ ) = WrappedxDaiContract().address, # TODO: Remove this default limitation once we fully support other than wxDai markets.
336
344
  ) -> t.List[OmenMarket]:
337
345
  """
338
346
  Complete method to fetch Omen binary markets with various filters, use `get_omen_binary_markets_simple` for simplified version that uses FilterBy and SortBy enums.
@@ -350,6 +358,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
350
358
  id_in=id_in,
351
359
  excluded_questions=excluded_questions,
352
360
  liquidity_bigger_than=liquidity_bigger_than,
361
+ collateral_token_address=collateral_token_address,
353
362
  )
354
363
 
355
364
  # These values can not be set to `None`, but they can be omitted.
@@ -41,7 +41,8 @@ class PolymarketAgentMarket(AgentMarket):
41
41
  volume=None,
42
42
  )
43
43
 
44
- def get_tiny_bet_amount(self) -> BetAmount:
44
+ @classmethod
45
+ def get_tiny_bet_amount(cls) -> BetAmount:
45
46
  raise NotImplementedError("TODO: Implement to allow betting on Polymarket.")
46
47
 
47
48
  def place_bet(self, outcome: bool, amount: BetAmount) -> None: