From d9d51d1a1dc32cbb6e2eabb78e5d51f99b464413 Mon Sep 17 00:00:00 2001 From: Cesare Naldi <3353250+cesarenaldi@users.noreply.github.com> Date: Mon, 25 May 2026 11:30:05 +0200 Subject: [PATCH 1/4] docs: improve Python SDK public docstrings --- src/polymarket/clients/async_public.py | 63 ++++++++++ src/polymarket/clients/async_secure.py | 142 ++++++++++++++++++++++ src/polymarket/clients/public.py | 150 +++++++++++++++++++++++ src/polymarket/clients/secure.py | 153 ++++++++++++++++++++++++ src/polymarket/models/clob/account.py | 10 ++ src/polymarket/models/data/portfolio.py | 8 ++ src/polymarket/models/gamma/market.py | 28 +++++ src/polymarket/pagination.py | 30 +++++ src/polymarket/streams/_specs.py | 22 +++- src/polymarket/transactions.py | 17 +++ 10 files changed, 622 insertions(+), 1 deletion(-) diff --git a/src/polymarket/clients/async_public.py b/src/polymarket/clients/async_public.py index 41f5165..63fc155 100644 --- a/src/polymarket/clients/async_public.py +++ b/src/polymarket/clients/async_public.py @@ -182,6 +182,15 @@ async def subscribe( self, specs: PublicSubscription | Sequence[PublicSubscription], ) -> SubscriptionHandle[MarketEvent | SportsEvent | RtdsEvent]: + """Subscribe to one or more public realtime streams. + + Pass a single subscription spec for one stream or a sequence of specs to + receive events through one merged handle. + + Returns: + A subscription handle. Iterate over it to receive events and close it + when finished. + """ items = _normalize_specs(specs) # AsyncSubscriptionHandle is invariant in T, so per-channel handles # can't widen to the union type at the type level. Cast at the @@ -288,6 +297,7 @@ async def get_market( include_tag: bool | None = None, locale: str | None = None, ) -> Market: + """Get a market by id, slug, or Polymarket URL.""" return await async_dispatch( self._ctx, _gamma_actions.get_market_spec( @@ -309,6 +319,7 @@ async def get_event( include_template: bool | None = None, locale: str | None = None, ) -> Event: + """Get an event by id, slug, or Polymarket URL.""" return await async_dispatch( self._ctx, _gamma_actions.get_event_spec( @@ -668,6 +679,18 @@ def list_events( volume_min: float | None = None, page_size: int = 20, ) -> AsyncPaginator[Event]: + """List events. + + Returns: + An async paginator over matching events. + + Examples: + Iterate over every page:: + + async for page in client.list_events(page_size=10): + for event in page.items: + print(event.title) + """ spec = _gamma_actions.list_events_spec( ascending=ascending, closed=closed, @@ -744,6 +767,17 @@ def list_markets( volume_num_min: float | None = None, page_size: int = 20, ) -> AsyncPaginator[Market]: + """List markets. + + Returns: + An async paginator over matching markets. + + Examples: + Iterate over individual market items:: + + async for market in client.list_markets(closed=False).items(): + print(market.question) + """ spec = _gamma_actions.list_markets_spec( ascending=ascending, closed=closed, @@ -902,6 +936,11 @@ def search( sort: str | None = None, page_size: int = 10, ) -> AsyncPaginator[SearchResults]: + """Search Polymarket content. + + Returns: + An async paginator over search result pages. + """ spec = _gamma_actions.search_spec( q=q, ascending=ascending, @@ -920,28 +959,34 @@ def search( return async_paginate_page_based(self._ctx, spec, page_size=page_size) async def get_midpoint(self, *, token_id: str) -> Decimal: + """Get the midpoint price for a token.""" path, params = _clob_actions.build_midpoint_request(token_id=token_id) return _clob_actions.parse_midpoint(await self._ctx.clob.get_json(path, params=params)) async def get_midpoints(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get midpoint prices for multiple tokens.""" path, body = _clob_actions.build_midpoints_request(token_ids=token_ids) return _clob_actions.parse_midpoints(await self._ctx.clob.post_json(path, json=body)) async def get_price(self, *, token_id: str, side: OrderSide) -> Decimal: + """Get the executable price for a token side.""" path, params = _clob_actions.build_price_request(token_id=token_id, side=side) return _clob_actions.parse_price(await self._ctx.clob.get_json(path, params=params)) async def get_prices( self, *, requests: Sequence[PriceRequest] ) -> dict[str, dict[OrderSide, Decimal]]: + """Get executable prices for multiple token-side requests.""" path, body = _clob_actions.build_prices_request(requests=requests) return _clob_actions.parse_prices(await self._ctx.clob.post_json(path, json=body)) async def get_order_book(self, *, token_id: str) -> OrderBook: + """Get the order book for a token.""" path, params = _clob_actions.build_order_book_request(token_id=token_id) return _clob_actions.parse_order_book(await self._ctx.clob.get_json(path, params=params)) async def get_order_books(self, *, token_ids: Sequence[str]) -> tuple[OrderBook, ...]: + """Get order books for multiple tokens.""" path, body = _clob_actions.build_order_books_request(token_ids=token_ids) return _clob_actions.parse_order_books(await self._ctx.clob.post_json(path, json=body)) @@ -976,6 +1021,7 @@ async def get_price_history( fidelity: int | None = None, interval: PriceHistoryInterval | None = None, ) -> tuple[PriceHistoryPoint, ...]: + """Get historical price points for a token.""" path, params = _clob_actions.build_price_history_request( token_id=token_id, start_ts=start_ts, @@ -1012,6 +1058,11 @@ async def estimate_market_price( shares: Decimal | int | float | str | None = None, order_type: MarketOrderType = "FOK", ) -> Decimal: + """Estimate the average execution price for a market order. + + BUY orders use ``amount`` as the spend amount. SELL orders use ``shares`` + as the number of shares to sell. + """ return await _estimate_market_price( self._ctx, token_id=token_id, @@ -1024,6 +1075,12 @@ async def estimate_market_price( def list_current_rewards( self, *, sponsored: bool | None = None ) -> AsyncPaginator[CurrentReward]: + """List current rewards. + + Returns: + An async paginator over current reward configurations. + """ + async def fetch(cursor: str | None) -> Page[CurrentReward]: path, params = _rewards_actions.build_list_current_rewards_request( sponsored=sponsored, cursor=cursor @@ -1037,6 +1094,12 @@ async def fetch(cursor: str | None) -> Page[CurrentReward]: def list_market_rewards( self, *, condition_id: str, sponsored: bool | None = None ) -> AsyncPaginator[MarketReward]: + """List rewards for a market condition. + + Returns: + An async paginator over matching market reward configurations. + """ + async def fetch(cursor: str | None) -> Page[MarketReward]: path, params = _rewards_actions.build_list_market_rewards_request( condition_id=ConditionId(condition_id), sponsored=sponsored, cursor=cursor diff --git a/src/polymarket/clients/async_secure.py b/src/polymarket/clients/async_secure.py index cab369a..eb28429 100644 --- a/src/polymarket/clients/async_secure.py +++ b/src/polymarket/clients/async_secure.py @@ -210,6 +210,12 @@ class AsyncSecureClient: + """Async client for authenticated account, trading, wallet, and stream workflows. + + Create instances with :meth:`AsyncSecureClient.create` so the SDK can derive + or validate credentials before authenticated requests are made. + """ + def __init__( self, *, @@ -253,6 +259,21 @@ async def create( validate_credentials: bool = True, logger: logging.Logger | None = None, ) -> Self: + """Create an authenticated async client. + + Args: + private_key: EVM private key used for signing. + wallet: Wallet address to act for. Defaults to the signer's address. + credentials: Existing API credentials. When omitted, credentials are + derived during client creation. + api_key: Optional key for gasless wallet and relayed transaction workflows. + nonce: Credential derivation nonce. Cannot be combined with ``credentials``. + validate_credentials: Whether provided credentials should be validated. + + Raises: + UserInputError: If key material, wallet, nonce, or credentials are invalid. + RequestRejectedError: If credential derivation or validation is rejected. + """ if not private_key: raise UserInputError("private_key is required") _validate_nonce(nonce) @@ -410,6 +431,16 @@ async def subscribe( self, specs: SecureSubscription | Sequence[SecureSubscription], ) -> SubscriptionHandle[MarketEvent | SportsEvent | RtdsEvent | UserEvent]: + """Subscribe to one or more public or authenticated realtime streams. + + Pass a single subscription spec for one stream or a sequence of specs to + receive events through one merged handle. Authenticated user stream specs + are supported only by secure clients. + + Returns: + A subscription handle. Iterate over it to receive events and close it + when finished. + """ items = _normalize_specs(specs) handles: list[AsyncSubscriptionHandle[Any]] = [] try: @@ -1271,6 +1302,7 @@ async def end_authentication(self) -> "AsyncPublicClient": return AsyncPublicClient(environment=environment) async def get_closed_only_mode(self) -> bool: + """Return whether the authenticated account is in closed-only mode.""" path, params = _account_actions.build_closed_only_mode_request() return _account_actions.parse_closed_only_mode( await self._ctx.secure_clob.get_json(path, params=params) @@ -1283,6 +1315,12 @@ def list_open_orders( id: str | None = None, market: str | None = None, ) -> AsyncPaginator[OpenOrder]: + """List open orders for the authenticated account. + + Returns: + An async paginator over matching open orders. + """ + async def fetch(cursor: str | None) -> Page[OpenOrder]: path, params = _account_actions.build_list_open_orders_request( token_id=token_id, id=id, market=market, cursor=cursor @@ -1293,6 +1331,7 @@ async def fetch(cursor: str | None) -> Page[OpenOrder]: return AsyncPaginator(fetch=fetch) async def get_order(self, *, order_id: str) -> OpenOrder: + """Get one open order for the authenticated account.""" path, params = _account_actions.build_get_order_request(order_id=order_id) return _account_actions.parse_open_order( await self._ctx.secure_clob.get_json(path, params=params) @@ -1308,6 +1347,12 @@ def list_account_trades( after: str | None = None, before: str | None = None, ) -> AsyncPaginator[ClobTrade]: + """List trades for the authenticated account. + + Returns: + An async paginator over matching trades. + """ + async def fetch(cursor: str | None) -> Page[ClobTrade]: path, params = _account_actions.build_list_account_trades_request( token_id=token_id, @@ -1340,6 +1385,7 @@ async def drop_notifications(self, *, ids: Sequence[int | str]) -> None: async def get_balance_allowance( self, *, asset_type: AssetType, token_id: str | None = None ) -> BalanceAllowance: + """Get balance and allowance information for an asset.""" path, params = _account_actions.build_balance_allowance_request( asset_type=asset_type, token_id=token_id, @@ -1376,6 +1422,11 @@ async def estimate_market_price( shares: Decimal | int | float | str | None = None, order_type: MarketOrderType = "FOK", ) -> Decimal: + """Estimate the average execution price for a market order. + + BUY orders use ``amount`` as the spend amount. SELL orders use ``shares`` + as the number of shares to sell. + """ return await _estimate_market_price( self._ctx, token_id=token_id, @@ -1396,6 +1447,11 @@ async def create_limit_order( expiration: int | None = None, builder_code: str | None = None, ) -> SignedOrder: + """Create and sign a limit order without posting it. + + Use :meth:`post_order` to submit the returned signed order, or + :meth:`place_limit_order` to create and post in one call. + """ params = validate_limit_order_params( token_id=token_id, price=price, @@ -1440,6 +1496,12 @@ async def create_market_order( order_type: MarketOrderType = "FAK", builder_code: str | None = None, ) -> SignedOrder: + """Create and sign a market order without posting it. + + BUY orders use ``amount`` as the spend amount and may include + ``max_spend``. SELL orders use ``shares`` as the number of shares to + sell. + """ return await self._prepare_and_sign_market_order( token_id=token_id, side=side, @@ -1484,6 +1546,7 @@ async def place_limit_order( expiration: int | None = None, builder_code: str | None = None, ) -> OrderResponse: + """Create, sign, and post a limit order.""" signed = await self.create_limit_order( token_id=token_id, price=price, @@ -1527,6 +1590,12 @@ async def place_market_order( order_type: MarketOrderType = "FAK", builder_code: str | None = None, ) -> OrderResponse: + """Create, sign, and post a market order. + + BUY orders use ``amount`` as the spend amount and may include + ``max_spend``. SELL orders use ``shares`` as the number of shares to + sell. + """ signed = await self._prepare_and_sign_market_order( token_id=token_id, side=side, @@ -1551,6 +1620,14 @@ async def approve_erc20( amount: int | Literal["max"], metadata: str | None = None, ) -> TransactionHandle: + """Submit an ERC-20 approval transaction. + + Args: + amount: Base-units amount to approve, or ``"max"`` for the maximum value. + + Returns: + A transaction handle. Await ``wait()`` to wait for a terminal outcome. + """ try: token = cast(EvmAddress, to_checksum_address(token_address)) except ValueError as error: @@ -1574,6 +1651,11 @@ async def approve_erc1155_for_all( approved: bool = True, metadata: str | None = None, ) -> TransactionHandle: + """Approve or revoke an ERC-1155 operator for all tokens. + + Returns: + A transaction handle. Await ``wait()`` to wait for a terminal outcome. + """ try: token = cast(EvmAddress, to_checksum_address(token_address)) except ValueError as error: @@ -1597,6 +1679,14 @@ async def transfer_erc20( amount: int, metadata: str | None = None, ) -> TransactionHandle: + """Submit an ERC-20 transfer transaction. + + Args: + amount: Base-units amount to transfer. + + Returns: + A transaction handle. Await ``wait()`` to wait for a terminal outcome. + """ try: token = cast(EvmAddress, to_checksum_address(token_address)) except ValueError as error: @@ -1612,6 +1702,15 @@ async def transfer_erc20( return await self._dispatch_single_call(call, metadata=resolved_metadata) async def setup_trading_approvals(self) -> TransactionHandle: + """Approve the standard set of trading allowances for the wallet. + + EOA wallets submit approvals directly. Gasless wallets submit a relayed + transaction. The returned handle represents the final transaction in the + setup workflow. + + Returns: + A transaction handle. Await ``wait()`` to wait for a terminal outcome. + """ env = self._ctx.environment collateral = cast(EvmAddress, env.collateral_token) conditional = cast(EvmAddress, env.conditional_tokens) @@ -1682,6 +1781,15 @@ async def setup_trading_approvals(self) -> TransactionHandle: ) async def setup_gasless_wallet(self) -> Self: + """Create or reuse the gasless wallet for the signer. + + Returns: + A new async secure client scoped to the gasless wallet. + + Raises: + UserInputError: If the client was not created with an API key that + can authorize gasless wallet workflows. + """ ctx = self._ctx if ctx.api_key is None: raise UserInputError( @@ -1721,6 +1829,7 @@ async def setup_gasless_wallet(self) -> Self: ) async def is_gasless_ready(self) -> bool: + """Return whether the signer has a deployed gasless wallet ready to use.""" ctx = self._ctx if ctx.wallet_type != "EOA": type_param = ( @@ -1759,6 +1868,14 @@ async def split_position( amount: int, metadata: str | None = None, ) -> TransactionHandle: + """Split collateral into outcome positions for a condition. + + Args: + amount: Base-units collateral amount to split. + + Returns: + A transaction handle. Await ``wait()`` to wait for a terminal outcome. + """ env = self._ctx.environment neg_risk = await self._resolve_market_neg_risk(condition_id) call = split_position_call( @@ -1781,6 +1898,15 @@ async def merge_positions( amount: int | Literal["max"], metadata: str | None = None, ) -> TransactionHandle: + """Merge outcome positions back into collateral. + + Args: + amount: Base-units position amount to merge, or ``"max"`` to merge + the largest available balanced amount. + + Returns: + A transaction handle. Await ``wait()`` to wait for a terminal outcome. + """ env = self._ctx.environment binary = await self._fetch_binary_positions(condition_id) neg_risk = expect_negative_risk_flag(binary) @@ -1805,6 +1931,16 @@ async def redeem_positions( market_id: str | None = None, metadata: str | None = None, ) -> TransactionHandle: + """Redeem resolved positions for a condition or market. + + Provide exactly one of ``condition_id`` or ``market_id``. + + Returns: + A transaction handle. Await ``wait()`` to wait for a terminal outcome. + + Raises: + UserInputError: If both identifiers or neither identifier is provided. + """ if (condition_id is None) == (market_id is None): raise UserInputError("Provide exactly one of condition_id or market_id") env = self._ctx.environment @@ -1853,6 +1989,7 @@ async def _fetch_binary_positions(self, market_id_or_condition_id: str): # type return expect_binary_positions(page.items) async def post_order(self, signed_order: SignedOrder) -> OrderResponse: + """Post a signed order for the authenticated account.""" path, payload = _post_actions.build_post_order_request( signed_order, owner_api_key=self._ctx.credentials.key ) @@ -1861,6 +1998,7 @@ async def post_order(self, signed_order: SignedOrder) -> OrderResponse: ) async def post_orders(self, signed_orders: Sequence[SignedOrder]) -> tuple[OrderResponse, ...]: + """Post multiple signed orders for the authenticated account.""" path, payload = _post_actions.build_post_orders_request( signed_orders, owner_api_key=self._ctx.credentials.key ) @@ -1869,18 +2007,21 @@ async def post_orders(self, signed_orders: Sequence[SignedOrder]) -> tuple[Order ) async def cancel_order(self, *, order_id: str) -> CancelOrdersResponse: + """Cancel one open order for the authenticated account.""" path, body = _cancel_actions.build_cancel_order_request(order_id=order_id) return _cancel_actions.parse_cancel_orders_response( await self._ctx.secure_clob.delete_json(path, json=body) ) async def cancel_orders(self, *, order_ids: Sequence[str]) -> CancelOrdersResponse: + """Cancel multiple open orders for the authenticated account.""" path, body = _cancel_actions.build_cancel_orders_request(order_ids=order_ids) return _cancel_actions.parse_cancel_orders_response( await self._ctx.secure_clob.delete_json(path, json=body) ) async def cancel_all(self) -> CancelOrdersResponse: + """Cancel all open orders for the authenticated account.""" path, body = _cancel_actions.build_cancel_all_request() return _cancel_actions.parse_cancel_orders_response( await self._ctx.secure_clob.delete_json(path, json=body) @@ -1889,6 +2030,7 @@ async def cancel_all(self) -> CancelOrdersResponse: async def cancel_market_orders( self, *, market: str | None = None, token_id: str | None = None ) -> CancelOrdersResponse: + """Cancel open orders matching a market or token filter.""" path, body = _cancel_actions.build_cancel_market_orders_request( market=market, token_id=token_id ) diff --git a/src/polymarket/clients/public.py b/src/polymarket/clients/public.py index 8625aab..0d89856 100644 --- a/src/polymarket/clients/public.py +++ b/src/polymarket/clients/public.py @@ -277,11 +277,13 @@ def get_comment_thread( ) def get_event_live_volumes(self, *, id: str) -> tuple[LiveVolume, ...]: + """Get live volume entries for an event.""" return sync_dispatch(self._ctx, _data_actions.get_event_live_volumes_spec(id=id)) def get_open_interests( self, *, market: Sequence[str] | None = None ) -> tuple[OpenInterest, ...]: + """Get open interest values, optionally filtered by market ids.""" return sync_dispatch(self._ctx, _data_actions.get_open_interests_spec(market=market)) def get_market_holders( @@ -291,6 +293,7 @@ def get_market_holders( limit: int | None = None, min_balance: int | None = None, ) -> tuple[MetaHolder, ...]: + """Get holder balances for one or more markets.""" return sync_dispatch( self._ctx, _data_actions.get_market_holders_spec( @@ -301,16 +304,19 @@ def get_market_holders( def get_portfolio_values( self, *, user: str, market: Sequence[str] | None = None ) -> tuple[PortfolioValue, ...]: + """Get portfolio value snapshots for a user.""" return sync_dispatch( self._ctx, _data_actions.get_portfolio_values_spec(user=user, market=market) ) def get_traded_market_count(self, *, user: str) -> TradedMarketCount: + """Get the number of markets a user has traded.""" return sync_dispatch(self._ctx, _data_actions.get_traded_market_count_spec(user=user)) def get_builder_volumes( self, *, time_period: BuilderVolumeTimePeriod | None = None ) -> tuple[BuilderVolumeEntry, ...]: + """Get builder volume leaderboard entries.""" return sync_dispatch( self._ctx, _data_actions.get_builder_volumes_spec(time_period=time_period) ) @@ -325,6 +331,13 @@ def list_builder_trades( after: str | None = None, before: str | None = None, ) -> Paginator[BuilderTrade]: + """List builder-attributed trades. + + Returns: + A paginator. Use ``first_page()``, iterate over pages, or call ``items()`` + to stream individual trades. + """ + def fetch(cursor: str | None) -> Page[BuilderTrade]: path, params = _builders_actions.build_list_builder_trades_request( builder_code=builder_code, @@ -354,6 +367,11 @@ def list_positions( title: str | None = None, page_size: int = 20, ) -> Paginator[Position]: + """List open positions for a user. + + Returns: + A paginator over matching positions. + """ spec = _data_actions.list_positions_spec( user=user, market=market, @@ -378,6 +396,11 @@ def list_closed_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> Paginator[ClosedPosition]: + """List closed positions for a user. + + Returns: + A paginator over matching closed positions. + """ spec = _data_actions.list_closed_positions_spec( user=user, market=market, @@ -398,6 +421,11 @@ def list_market_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> Paginator[MetaMarketPosition]: + """List positions in a market. + + Returns: + A paginator over matching market positions. + """ spec = _data_actions.list_market_positions_spec( market=market, user=user, @@ -419,6 +447,11 @@ def list_trades( filter_amount: float | None = None, page_size: int = 20, ) -> Paginator[Trade]: + """List public trades. + + Returns: + A paginator over matching trades. + """ spec = _data_actions.list_trades_spec( user=user, market=market, @@ -444,6 +477,11 @@ def list_activity( end: int | None = None, page_size: int = 20, ) -> Paginator[Activity]: + """List user activity. + + Returns: + A paginator over matching activity entries. + """ spec = _data_actions.list_activity_spec( user=user, market=market, @@ -463,10 +501,16 @@ def list_builder_leaderboard( time_period: LeaderboardTimePeriod | None = None, page_size: int = 20, ) -> Paginator[LeaderboardEntry]: + """List builder leaderboard entries. + + Returns: + A paginator over leaderboard rows. + """ spec = _data_actions.list_builder_leaderboard_spec(time_period=time_period) return sync_paginate_offset(self._ctx, spec, page_size=page_size) def download_accounting_snapshot(self, *, user: str) -> bytes: + """Download the accounting snapshot archive for a user.""" path, params = _data_actions.build_accounting_snapshot_request(user=user) return self._ctx.data.get_bytes(path, params=params) @@ -480,6 +524,11 @@ def list_trader_leaderboard( user_name: str | None = None, page_size: int = 20, ) -> Paginator[TraderLeaderboardEntry]: + """List trader leaderboard entries. + + Returns: + A paginator over leaderboard rows. + """ spec = _data_actions.list_trader_leaderboard_spec( category=category, time_period=time_period, @@ -532,6 +581,23 @@ def list_events( volume_min: float | None = None, page_size: int = 20, ) -> Paginator[Event]: + """List events. + + Returns: + A paginator over matching events. + + Examples: + Fetch the first page:: + + paginator = client.list_events(page_size=10) + first_page = paginator.first_page() + + Iterate over all pages:: + + for page in client.list_events(page_size=10): + for event in page.items: + print(event.title) + """ spec = _gamma_actions.list_events_spec( ascending=ascending, closed=closed, @@ -608,6 +674,22 @@ def list_markets( volume_num_min: float | None = None, page_size: int = 20, ) -> Paginator[Market]: + """List markets. + + Returns: + A paginator over matching markets. + + Examples: + Fetch the first page:: + + paginator = client.list_markets(closed=False, page_size=10) + first_page = paginator.first_page() + + Iterate over every market item:: + + for market in client.list_markets(closed=False).items(): + print(market.question) + """ spec = _gamma_actions.list_markets_spec( ascending=ascending, closed=closed, @@ -656,6 +738,11 @@ def list_series( slug: str | Sequence[str] | None = None, page_size: int = 20, ) -> Paginator[Series]: + """List series. + + Returns: + A paginator over matching series. + """ spec = _gamma_actions.list_series_spec( ascending=ascending, categories_ids=categories_ids, @@ -681,6 +768,11 @@ def list_tags( order: str | None = None, page_size: int = 20, ) -> Paginator[Tag]: + """List tags. + + Returns: + A paginator over matching tags. + """ spec = _gamma_actions.list_tags_spec( ascending=ascending, include_chat=include_chat, @@ -702,6 +794,11 @@ def list_teams( provider_ids: int | Sequence[int] | None = None, page_size: int = 20, ) -> Paginator[Team]: + """List teams. + + Returns: + A paginator over matching teams. + """ spec = _gamma_actions.list_teams_spec( abbreviation=abbreviation, ascending=ascending, @@ -723,6 +820,11 @@ def list_comments( order: str | None = None, page_size: int = 20, ) -> Paginator[Comment]: + """List comments for a market or event. + + Returns: + A paginator over matching comments. + """ spec = _gamma_actions.list_comments_spec( parent_entity_id=parent_entity_id, parent_entity_type=parent_entity_type, @@ -741,6 +843,11 @@ def list_comments_by_user_address( order: str | None = None, page_size: int = 20, ) -> Paginator[Comment]: + """List comments authored by a user address. + + Returns: + A paginator over matching comments. + """ spec = _gamma_actions.list_comments_by_user_address_spec( address=address, ascending=ascending, @@ -766,6 +873,17 @@ def search( sort: str | None = None, page_size: int = 10, ) -> Paginator[SearchResults]: + """Search Polymarket content. + + Returns: + A paginator over search result pages. + + Examples: + Search markets and events:: + + for result in client.search(q="election").items(): + print(result) + """ spec = _gamma_actions.search_spec( q=q, ascending=ascending, @@ -784,46 +902,56 @@ def search( return sync_paginate_page_based(self._ctx, spec, page_size=page_size) def get_midpoint(self, *, token_id: str) -> Decimal: + """Get the midpoint price for a token.""" path, params = _clob_actions.build_midpoint_request(token_id=token_id) return _clob_actions.parse_midpoint(self._ctx.clob.get_json(path, params=params)) def get_midpoints(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get midpoint prices for multiple tokens.""" path, body = _clob_actions.build_midpoints_request(token_ids=token_ids) return _clob_actions.parse_midpoints(self._ctx.clob.post_json(path, json=body)) def get_price(self, *, token_id: str, side: OrderSide) -> Decimal: + """Get the executable price for a token side.""" path, params = _clob_actions.build_price_request(token_id=token_id, side=side) return _clob_actions.parse_price(self._ctx.clob.get_json(path, params=params)) def get_prices( self, *, requests: Sequence[PriceRequest] ) -> dict[str, dict[OrderSide, Decimal]]: + """Get executable prices for multiple token-side requests.""" path, body = _clob_actions.build_prices_request(requests=requests) return _clob_actions.parse_prices(self._ctx.clob.post_json(path, json=body)) def get_order_book(self, *, token_id: str) -> OrderBook: + """Get the order book for a token.""" path, params = _clob_actions.build_order_book_request(token_id=token_id) return _clob_actions.parse_order_book(self._ctx.clob.get_json(path, params=params)) def get_order_books(self, *, token_ids: Sequence[str]) -> tuple[OrderBook, ...]: + """Get order books for multiple tokens.""" path, body = _clob_actions.build_order_books_request(token_ids=token_ids) return _clob_actions.parse_order_books(self._ctx.clob.post_json(path, json=body)) def get_spread(self, *, token_id: str) -> Decimal: + """Get the bid-ask spread for a token.""" path, params = _clob_actions.build_spread_request(token_id=token_id) return _clob_actions.parse_spread(self._ctx.clob.get_json(path, params=params)) def get_spreads(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get bid-ask spreads for multiple tokens.""" path, body = _clob_actions.build_spreads_request(token_ids=token_ids) return _clob_actions.parse_spreads(self._ctx.clob.post_json(path, json=body)) def get_last_trade_price(self, *, token_id: str) -> LastTradePrice: + """Get the most recent trade price for a token.""" path, params = _clob_actions.build_last_trade_price_request(token_id=token_id) return _clob_actions.parse_last_trade_price(self._ctx.clob.get_json(path, params=params)) def get_last_trade_prices( self, *, token_ids: Sequence[str] ) -> tuple[LastTradePriceForToken, ...]: + """Get the most recent trade prices for multiple tokens.""" path, body = _clob_actions.build_last_trade_prices_request(token_ids=token_ids) return _clob_actions.parse_last_trade_prices(self._ctx.clob.post_json(path, json=body)) @@ -836,6 +964,7 @@ def get_price_history( fidelity: int | None = None, interval: PriceHistoryInterval | None = None, ) -> tuple[PriceHistoryPoint, ...]: + """Get historical price points for a token.""" path, params = _clob_actions.build_price_history_request( token_id=token_id, start_ts=start_ts, @@ -872,6 +1001,15 @@ def estimate_market_price( shares: Decimal | int | float | str | None = None, order_type: MarketOrderType = "FOK", ) -> Decimal: + """Estimate the average execution price for a market order. + + BUY orders use ``amount`` as the spend amount. SELL orders use ``shares`` + as the number of shares to sell. + + Raises: + UserInputError: If the side-specific amount is missing or invalid. + InsufficientLiquidityError: If available liquidity cannot fill the order. + """ return _estimate_market_price_sync( self._ctx, token_id=token_id, @@ -882,6 +1020,12 @@ def estimate_market_price( ) def list_current_rewards(self, *, sponsored: bool | None = None) -> Paginator[CurrentReward]: + """List current rewards. + + Returns: + A paginator over current reward configurations. + """ + def fetch(cursor: str | None) -> Page[CurrentReward]: path, params = _rewards_actions.build_list_current_rewards_request( sponsored=sponsored, cursor=cursor @@ -895,6 +1039,12 @@ def fetch(cursor: str | None) -> Page[CurrentReward]: def list_market_rewards( self, *, condition_id: str, sponsored: bool | None = None ) -> Paginator[MarketReward]: + """List rewards for a market condition. + + Returns: + A paginator over matching market reward configurations. + """ + def fetch(cursor: str | None) -> Page[MarketReward]: path, params = _rewards_actions.build_list_market_rewards_request( condition_id=ConditionId(condition_id), sponsored=sponsored, cursor=cursor diff --git a/src/polymarket/clients/secure.py b/src/polymarket/clients/secure.py index db7e9d4..ff9113d 100644 --- a/src/polymarket/clients/secure.py +++ b/src/polymarket/clients/secure.py @@ -188,6 +188,12 @@ def _validate_nonce(nonce: object) -> None: class SecureClient: + """Synchronous client for authenticated account, trading, and wallet workflows. + + Create instances with :meth:`SecureClient.create` so the SDK can derive or + validate credentials before authenticated requests are made. + """ + def __init__( self, *, @@ -227,6 +233,21 @@ def create( validate_credentials: bool = True, logger: logging.Logger | None = None, ) -> Self: + """Create an authenticated synchronous client. + + Args: + private_key: EVM private key used for signing. + wallet: Wallet address to act for. Defaults to the signer's address. + credentials: Existing API credentials. When omitted, credentials are + derived during client creation. + api_key: Optional key for gasless wallet and relayed transaction workflows. + nonce: Credential derivation nonce. Cannot be combined with ``credentials``. + validate_credentials: Whether provided credentials should be validated. + + Raises: + UserInputError: If key material, wallet, nonce, or credentials are invalid. + RequestRejectedError: If credential derivation or validation is rejected. + """ if not private_key: raise UserInputError("private_key is required") _validate_nonce(nonce) @@ -1170,6 +1191,7 @@ def end_authentication(self) -> "PublicClient": return PublicClient(environment=environment) def get_closed_only_mode(self) -> bool: + """Return whether the authenticated account is in closed-only mode.""" path, params = _account_actions.build_closed_only_mode_request() return _account_actions.parse_closed_only_mode( self._ctx.secure_clob.get_json(path, params=params) @@ -1182,6 +1204,12 @@ def list_open_orders( id: str | None = None, market: str | None = None, ) -> Paginator[OpenOrder]: + """List open orders for the authenticated account. + + Returns: + A paginator over matching open orders. + """ + def fetch(cursor: str | None) -> Page[OpenOrder]: path, params = _account_actions.build_list_open_orders_request( token_id=token_id, id=id, market=market, cursor=cursor @@ -1192,6 +1220,7 @@ def fetch(cursor: str | None) -> Page[OpenOrder]: return Paginator(fetch=fetch) def get_order(self, *, order_id: str) -> OpenOrder: + """Get one open order for the authenticated account.""" path, params = _account_actions.build_get_order_request(order_id=order_id) return _account_actions.parse_open_order( self._ctx.secure_clob.get_json(path, params=params) @@ -1207,6 +1236,12 @@ def list_account_trades( after: str | None = None, before: str | None = None, ) -> Paginator[ClobTrade]: + """List trades for the authenticated account. + + Returns: + A paginator over matching trades. + """ + def fetch(cursor: str | None) -> Page[ClobTrade]: path, params = _account_actions.build_list_account_trades_request( token_id=token_id, @@ -1223,6 +1258,7 @@ def fetch(cursor: str | None) -> Page[ClobTrade]: return Paginator(fetch=fetch) def get_notifications(self) -> tuple[Notification, ...]: + """Get notifications for the authenticated account.""" path, params = _account_actions.build_notifications_request( signature_type=signature_type_for(self._ctx.wallet_type) ) @@ -1231,6 +1267,7 @@ def get_notifications(self) -> tuple[Notification, ...]: ) def drop_notifications(self, *, ids: Sequence[int | str]) -> None: + """Delete notifications for the authenticated account.""" path, params = _account_actions.build_drop_notifications_request( ids=ids, signature_type=signature_type_for(self._ctx.wallet_type) ) @@ -1239,6 +1276,7 @@ def drop_notifications(self, *, ids: Sequence[int | str]) -> None: def get_balance_allowance( self, *, asset_type: AssetType, token_id: str | None = None ) -> BalanceAllowance: + """Get balance and allowance information for an asset.""" path, params = _account_actions.build_balance_allowance_request( asset_type=asset_type, token_id=token_id, @@ -1259,6 +1297,15 @@ def create_limit_order( expiration: int | None = None, builder_code: str | None = None, ) -> SignedOrder: + """Create and sign a limit order without posting it. + + Use :meth:`post_order` to submit the returned signed order, or + :meth:`place_limit_order` to create and post in one call. + + Raises: + UserInputError: If order parameters are invalid. + SigningError: If the order cannot be signed. + """ return self._prepare_and_sign_limit_order( token_id=token_id, price=price, @@ -1301,6 +1348,17 @@ def create_market_order( order_type: MarketOrderType = "FAK", builder_code: str | None = None, ) -> SignedOrder: + """Create and sign a market order without posting it. + + BUY orders use ``amount`` as the spend amount and may include + ``max_spend``. SELL orders use ``shares`` as the number of shares to + sell. + + Raises: + UserInputError: If side-specific order parameters are invalid. + InsufficientLiquidityError: If available liquidity cannot fill the order. + SigningError: If the order cannot be signed. + """ return self._prepare_and_sign_market_order( token_id=token_id, side=side, @@ -1322,6 +1380,14 @@ def place_limit_order( expiration: int | None = None, builder_code: str | None = None, ) -> OrderResponse: + """Create, sign, and post a limit order. + + Raises: + UserInputError: If order parameters are invalid. + InsufficientAllowanceError: If required allowance cannot be recovered. + SigningError: If the order cannot be signed. + RequestRejectedError: If posting the order is rejected. + """ signed = self._prepare_and_sign_limit_order( token_id=token_id, price=price, @@ -1365,6 +1431,19 @@ def place_market_order( order_type: MarketOrderType = "FAK", builder_code: str | None = None, ) -> OrderResponse: + """Create, sign, and post a market order. + + BUY orders use ``amount`` as the spend amount and may include + ``max_spend``. SELL orders use ``shares`` as the number of shares to + sell. + + Raises: + UserInputError: If side-specific order parameters are invalid. + InsufficientLiquidityError: If available liquidity cannot fill the order. + InsufficientAllowanceError: If required allowance cannot be recovered. + SigningError: If the order cannot be signed. + RequestRejectedError: If posting the order is rejected. + """ signed = self._prepare_and_sign_market_order( token_id=token_id, side=side, @@ -1377,11 +1456,13 @@ def place_market_order( return post_order_with_allowance_recovery_sync(self, signed) def get_builder_fee_rates(self, builder_code: str) -> BuilderFeeRates: + """Get fee rates for a builder code.""" from polymarket._internal.actions.orders.market_data import fetch_builder_fee_rates_sync return fetch_builder_fee_rates_sync(self._ctx, builder_code=builder_code) def post_order(self, signed_order: SignedOrder) -> OrderResponse: + """Post a signed order for the authenticated account.""" path, payload = _post_actions.build_post_order_request( signed_order, owner_api_key=self._ctx.credentials.key ) @@ -1390,6 +1471,7 @@ def post_order(self, signed_order: SignedOrder) -> OrderResponse: ) def post_orders(self, signed_orders: Sequence[SignedOrder]) -> tuple[OrderResponse, ...]: + """Post multiple signed orders for the authenticated account.""" path, payload = _post_actions.build_post_orders_request( signed_orders, owner_api_key=self._ctx.credentials.key ) @@ -1398,18 +1480,21 @@ def post_orders(self, signed_orders: Sequence[SignedOrder]) -> tuple[OrderRespon ) def cancel_order(self, *, order_id: str) -> CancelOrdersResponse: + """Cancel one open order for the authenticated account.""" path, body = _cancel_actions.build_cancel_order_request(order_id=order_id) return _cancel_actions.parse_cancel_orders_response( self._ctx.secure_clob.delete_json(path, json=body) ) def cancel_orders(self, *, order_ids: Sequence[str]) -> CancelOrdersResponse: + """Cancel multiple open orders for the authenticated account.""" path, body = _cancel_actions.build_cancel_orders_request(order_ids=order_ids) return _cancel_actions.parse_cancel_orders_response( self._ctx.secure_clob.delete_json(path, json=body) ) def cancel_all(self) -> CancelOrdersResponse: + """Cancel all open orders for the authenticated account.""" path, body = _cancel_actions.build_cancel_all_request() return _cancel_actions.parse_cancel_orders_response( self._ctx.secure_clob.delete_json(path, json=body) @@ -1418,6 +1503,7 @@ def cancel_all(self) -> CancelOrdersResponse: def cancel_market_orders( self, *, market: str | None = None, token_id: str | None = None ) -> CancelOrdersResponse: + """Cancel open orders matching a market or token filter.""" path, body = _cancel_actions.build_cancel_market_orders_request( market=market, token_id=token_id ) @@ -1559,6 +1645,14 @@ def approve_erc20( amount: int | Literal["max"], metadata: str | None = None, ) -> SyncTransactionHandle: + """Submit an ERC-20 approval transaction. + + Args: + amount: Base-units amount to approve, or ``"max"`` for the maximum value. + + Returns: + A transaction handle. Call ``wait()`` to wait for a terminal outcome. + """ try: token = cast(EvmAddress, to_checksum_address(token_address)) except ValueError as error: @@ -1582,6 +1676,11 @@ def approve_erc1155_for_all( approved: bool = True, metadata: str | None = None, ) -> SyncTransactionHandle: + """Approve or revoke an ERC-1155 operator for all tokens. + + Returns: + A transaction handle. Call ``wait()`` to wait for a terminal outcome. + """ try: token = cast(EvmAddress, to_checksum_address(token_address)) except ValueError as error: @@ -1605,6 +1704,14 @@ def transfer_erc20( amount: int, metadata: str | None = None, ) -> SyncTransactionHandle: + """Submit an ERC-20 transfer transaction. + + Args: + amount: Base-units amount to transfer. + + Returns: + A transaction handle. Call ``wait()`` to wait for a terminal outcome. + """ try: token = cast(EvmAddress, to_checksum_address(token_address)) except ValueError as error: @@ -1620,6 +1727,15 @@ def transfer_erc20( return self._dispatch_single_call(call, metadata=resolved_metadata) def setup_trading_approvals(self) -> SyncTransactionHandle: + """Approve the standard set of trading allowances for the wallet. + + EOA wallets submit approvals directly. Gasless wallets submit a relayed + transaction. The returned handle represents the final transaction in the + setup workflow. + + Returns: + A transaction handle. Call ``wait()`` to wait for a terminal outcome. + """ env = self._ctx.environment collateral = cast(EvmAddress, env.collateral_token) conditional = cast(EvmAddress, env.conditional_tokens) @@ -1690,6 +1806,15 @@ def setup_trading_approvals(self) -> SyncTransactionHandle: ) def setup_gasless_wallet(self) -> Self: + """Create or reuse the gasless wallet for the signer. + + Returns: + A new secure client scoped to the gasless wallet. + + Raises: + UserInputError: If the client was not created with an API key that + can authorize gasless wallet workflows. + """ ctx = self._ctx if ctx.api_key is None: raise UserInputError( @@ -1729,6 +1854,7 @@ def setup_gasless_wallet(self) -> Self: ) def is_gasless_ready(self) -> bool: + """Return whether the signer has a deployed gasless wallet ready to use.""" ctx = self._ctx if ctx.wallet_type != "EOA": type_param = ( @@ -1749,6 +1875,14 @@ def split_position( amount: int, metadata: str | None = None, ) -> SyncTransactionHandle: + """Split collateral into outcome positions for a condition. + + Args: + amount: Base-units collateral amount to split. + + Returns: + A transaction handle. Call ``wait()`` to wait for a terminal outcome. + """ env = self._ctx.environment neg_risk = self._resolve_market_neg_risk(condition_id) call = split_position_call( @@ -1771,6 +1905,15 @@ def merge_positions( amount: int | Literal["max"], metadata: str | None = None, ) -> SyncTransactionHandle: + """Merge outcome positions back into collateral. + + Args: + amount: Base-units position amount to merge, or ``"max"`` to merge + the largest available balanced amount. + + Returns: + A transaction handle. Call ``wait()`` to wait for a terminal outcome. + """ env = self._ctx.environment binary = self._fetch_binary_positions(condition_id) neg_risk = expect_negative_risk_flag(binary) @@ -1795,6 +1938,16 @@ def redeem_positions( market_id: str | None = None, metadata: str | None = None, ) -> SyncTransactionHandle: + """Redeem resolved positions for a condition or market. + + Provide exactly one of ``condition_id`` or ``market_id``. + + Returns: + A transaction handle. Call ``wait()`` to wait for a terminal outcome. + + Raises: + UserInputError: If both identifiers or neither identifier is provided. + """ if (condition_id is None) == (market_id is None): raise UserInputError("Provide exactly one of condition_id or market_id") env = self._ctx.environment diff --git a/src/polymarket/models/clob/account.py b/src/polymarket/models/clob/account.py index d6f2ac6..deb96ef 100644 --- a/src/polymarket/models/clob/account.py +++ b/src/polymarket/models/clob/account.py @@ -52,6 +52,8 @@ def _parse_optional_epoch(value: object) -> datetime | None: class OpenOrder(BaseModel): + """Open order owned by an account.""" + id: str market: str token_id: TokenId = Field(validation_alias="asset_id") @@ -80,6 +82,8 @@ def _parse_expires_at(cls, value: object) -> datetime | None: class MakerOrder(BaseModel): + """Maker-side fill information attached to a trade.""" + order_id: str = Field(validation_alias="order_id") token_id: TokenId = Field(validation_alias="asset_id") maker_address: str = Field(validation_alias="maker_address") @@ -97,6 +101,8 @@ def _empty_to_none(cls, value: object) -> object: class ClobTrade(BaseModel): + """Executed trade for an account or market.""" + id: str market: str token_id: TokenId = Field(validation_alias="asset_id") @@ -123,6 +129,8 @@ def _parse_epoch_field(cls, value: object) -> datetime: class Notification(BaseModel): + """Account notification.""" + id: int owner: str type: int @@ -151,6 +159,8 @@ def _parse_timestamp(cls, value: object) -> datetime: class BalanceAllowance(BaseModel): + """Balance and allowance values for an asset in base units.""" + balance: int allowances: dict[str, int] diff --git a/src/polymarket/models/data/portfolio.py b/src/polymarket/models/data/portfolio.py index 2acaf0b..16437f6 100644 --- a/src/polymarket/models/data/portfolio.py +++ b/src/polymarket/models/data/portfolio.py @@ -16,6 +16,8 @@ class PortfolioValue(BaseModel): + """Current portfolio value for a user.""" + user: EvmAddress | None = None value: Decimal | None = None @@ -26,11 +28,15 @@ def _parse_value(cls, value: object) -> Decimal | None: class TradedMarketCount(BaseModel): + """Number of markets traded by a user.""" + user: EvmAddress | None = None traded: int | None = None class Position(BaseModel): + """Open market position held by a wallet.""" + condition_id: ConditionId = Field(validation_alias="conditionId") wallet: EvmAddress | None = Field(default=None, validation_alias="proxyWallet") token_id: TokenId | None = Field(default=None, validation_alias="asset") @@ -80,6 +86,8 @@ def _parse_end_date(cls, value: object) -> date | None: class ClosedPosition(BaseModel): + """Closed market position for a wallet.""" + wallet: EvmAddress | None = Field(default=None, validation_alias="proxyWallet") token_id: TokenId | None = Field(default=None, validation_alias="asset") condition_id: ConditionId | None = Field(default=None, validation_alias="conditionId") diff --git a/src/polymarket/models/gamma/market.py b/src/polymarket/models/gamma/market.py index 3112acc..fc1fe34 100644 --- a/src/polymarket/models/gamma/market.py +++ b/src/polymarket/models/gamma/market.py @@ -34,6 +34,8 @@ class UmaResolutionStatus(StrEnum): + """Resolution lifecycle state for a market.""" + DISPUTED = "disputed" PROPOSED = "proposed" REQUESTED = "requested" @@ -42,6 +44,8 @@ class UmaResolutionStatus(StrEnum): class MarketState(BaseModel): + """Operational state and timing for a market.""" + active: bool | None = None closed: bool | None = None archived: bool | None = None @@ -77,6 +81,8 @@ def _parse_datetime(cls, value: object) -> datetime | None: class MarketOutcome(BaseModel): + """One tradable outcome in a binary market.""" + label: str token_id: TokenId | None = Field( default=None, @@ -91,11 +97,15 @@ def _parse_price(cls, value: object) -> Decimal | None: class MarketOutcomes(BaseModel): + """Binary market outcomes.""" + yes: MarketOutcome no: MarketOutcome class MarketMetrics(BaseModel): + """Volume and liquidity metrics for a market.""" + volume: Decimal | None = None volume_num: Decimal | None = Field( default=None, @@ -142,6 +152,8 @@ def _parse_metric(cls, value: object) -> Decimal | None: class MarketPrices(BaseModel): + """Current price and price-change data for a market.""" + best_bid: Decimal | None = Field( default=None, validation_alias="bestBid", @@ -183,6 +195,8 @@ def _parse_price(cls, value: object) -> Decimal | None: class FeeSchedule(BaseModel): + """Fee schedule applied to market trading.""" + exponent: int | float rate: Decimal taker_only: bool = Field(validation_alias="takerOnly") @@ -195,6 +209,8 @@ def _parse_decimal(cls, value: object) -> Decimal: class MarketTrading(BaseModel): + """Trading configuration and constraints for a market.""" + minimum_order_size: Decimal | None = Field( default=None, validation_alias="minimumOrderSize", @@ -227,6 +243,8 @@ def _parse_optional_decimal(cls, value: object) -> Decimal | None: class MarketResolution(BaseModel): + """Resolution metadata for a market.""" + question_id: QuestionId | None = Field( default=None, validation_alias="questionId", @@ -257,6 +275,8 @@ def _parse_uma_status(cls, value: object) -> object | None: class ClobReward(BaseModel): + """Reward configuration attached to a market condition.""" + id: ClobRewardId condition_id: ConditionId = Field(validation_alias="conditionId") asset_address: str = Field(validation_alias="assetAddress") @@ -275,6 +295,8 @@ def _parse_decimal(cls, value: object) -> Decimal: class MarketRewards(BaseModel): + """Reward settings for a market.""" + clob_rewards: tuple[ClobReward, ...] | None = Field( default=None, validation_alias="clobRewards", @@ -299,6 +321,8 @@ def _parse_optional_decimal(cls, value: object) -> Decimal | None: class MarketSportsMetadata(BaseModel): + """Sports-specific metadata for a market.""" + sports_market_type: str | None = Field( default=None, validation_alias="sportsMarketType", @@ -320,6 +344,8 @@ def _parse_datetime(cls, value: object) -> datetime | None: class MarketEvent(BaseModel): + """Event reference attached to a market.""" + id: EventId slug: str | None = None title: str | None = None @@ -331,6 +357,8 @@ def _coerce_id(cls, value: object) -> object: class MarketTag(BaseModel): + """Tag reference attached to a market.""" + id: TagId slug: str | None = None label: str | None = None diff --git a/src/polymarket/pagination.py b/src/polymarket/pagination.py index 59b1a51..b3002ac 100644 --- a/src/polymarket/pagination.py +++ b/src/polymarket/pagination.py @@ -11,13 +11,25 @@ @dataclass(frozen=True, slots=True) class Page(Generic[T]): + """One page of paginated SDK results.""" + items: tuple[T, ...] + """Items returned on this page.""" has_more: bool + """Whether another page is available.""" next_cursor: str | None = None + """Cursor to pass to ``from_cursor()`` for the next page, when available.""" total_count: int | None = None + """Total matching item count when the API provides it.""" class Paginator(Generic[T]): + """Synchronous paginator returned by list-style client methods. + + Iterate over the paginator to fetch pages lazily, or call ``items()`` to + iterate over individual items across pages. + """ + def __init__( self, fetch: Callable[[str | None], Page[T]], @@ -27,9 +39,14 @@ def __init__( self._initial_cursor = initial_cursor def first_page(self) -> Page[T]: + """Fetch the first page for this paginator.""" return self._fetch(self._initial_cursor) def from_cursor(self, cursor: str | None) -> Paginator[T]: + """Create a paginator that starts from ``cursor``. + + Passing ``None`` returns an empty paginator because no next page exists. + """ if cursor is None: return cast(Paginator[T], _EmptyPaginator()) return Paginator(self._fetch, initial_cursor=cursor) @@ -38,6 +55,7 @@ def __iter__(self) -> Iterator[Page[T]]: return self._iter_pages() def items(self) -> Iterator[T]: + """Iterate over individual items across all fetched pages.""" for page in self._iter_pages(): yield from page.items @@ -56,6 +74,12 @@ def _iter_pages(self) -> Iterator[Page[T]]: class AsyncPaginator(Generic[T]): + """Async paginator returned by async list-style client methods. + + Use ``async for`` over the paginator to fetch pages lazily, or call + ``items()`` to iterate over individual items across pages. + """ + def __init__( self, fetch: Callable[[str | None], Awaitable[Page[T]]], @@ -65,9 +89,14 @@ def __init__( self._initial_cursor = initial_cursor async def first_page(self) -> Page[T]: + """Fetch the first page for this paginator.""" return await self._fetch(self._initial_cursor) def from_cursor(self, cursor: str | None) -> AsyncPaginator[T]: + """Create an async paginator that starts from ``cursor``. + + Passing ``None`` returns an empty paginator because no next page exists. + """ if cursor is None: return cast(AsyncPaginator[T], _EmptyAsyncPaginator()) return AsyncPaginator(self._fetch, initial_cursor=cursor) @@ -76,6 +105,7 @@ def __aiter__(self) -> AsyncIterator[Page[T]]: return self._iter_pages() def items(self) -> AsyncIterator[T]: + """Iterate over individual items across all fetched pages.""" return self._iter_items() async def _iter_pages(self) -> AsyncIterator[Page[T]]: diff --git a/src/polymarket/streams/_specs.py b/src/polymarket/streams/_specs.py index faeb9ed..b1a8392 100644 --- a/src/polymarket/streams/_specs.py +++ b/src/polymarket/streams/_specs.py @@ -25,7 +25,7 @@ @dataclass(frozen=True, slots=True, kw_only=True) class MarketSpec: - """Subscription for the CLOB market stream.""" + """Subscribe to realtime market updates for one or more token ids.""" token_ids: Sequence[str] custom_feature_enabled: bool = False @@ -61,6 +61,12 @@ class SportsSpec: @dataclass(frozen=True, slots=True, kw_only=True) class CommentsSpec: + """Subscribe to realtime comment and reaction events. + + Filters are optional. When provided, ``types`` limits event kinds and the + parent entity fields limit events to a specific market or event. + """ + types: Sequence[CommentsEventType] | None = None parent_entity_id: int | None = None parent_entity_type: ParentEntityType | None = None @@ -93,6 +99,12 @@ def __post_init__(self) -> None: @dataclass(frozen=True, slots=True, kw_only=True) class CryptoPricesSpec: + """Subscribe to realtime crypto price updates for a topic. + + When ``symbols`` is omitted, the subscription receives all symbols for the + selected topic. + """ + topic: CryptoPricesTopic symbols: Sequence[str] | None = None @@ -118,6 +130,8 @@ def __post_init__(self) -> None: @dataclass(frozen=True, slots=True, kw_only=True) class EquityPricesSpec: + """Subscribe to realtime equity price updates for one symbol.""" + symbol: str types: Sequence[EquityPricesEventType] | None = None topic: Literal["prices.equity.pyth"] = field(default="prices.equity.pyth", init=False) @@ -140,6 +154,12 @@ def __post_init__(self) -> None: @dataclass(frozen=True, slots=True, kw_only=True) class UserSpec: + """Subscribe to authenticated user order and trade events. + + When ``markets`` is omitted, the subscription receives user events for all + markets available to the authenticated account. + """ + markets: Sequence[str] | None = None topic: Literal["user"] = field(default="user", init=False) diff --git a/src/polymarket/transactions.py b/src/polymarket/transactions.py index aeee513..2efae1d 100644 --- a/src/polymarket/transactions.py +++ b/src/polymarket/transactions.py @@ -12,6 +12,8 @@ @dataclass(frozen=True, slots=True) class GaslessTransactionHandle: + """Async handle for a relayed gasless transaction.""" + transaction_id: str transaction_hash: str | None _relayer: AsyncTransport = field(repr=False) @@ -19,6 +21,7 @@ class GaslessTransactionHandle: _poll_delay_s: float async def wait(self) -> TransactionOutcome: + """Wait until the transaction reaches a terminal outcome.""" from polymarket._internal.actions.relayer.poll import poll_until_terminal return await poll_until_terminal( @@ -32,6 +35,8 @@ async def wait(self) -> TransactionOutcome: @dataclass(frozen=True, slots=True) class EoaTransactionHandle: + """Async handle for a directly broadcast EOA transaction.""" + transaction_hash: str _rpc: JsonRpcClient = field(repr=False) _max_polls: int @@ -39,9 +44,11 @@ class EoaTransactionHandle: @property def transaction_id(self) -> None: + """Return None because EOA transactions do not have relayer ids.""" return None async def wait(self) -> TransactionOutcome: + """Wait until the transaction reaches a terminal outcome.""" from polymarket._internal.eoa.broadcast import wait_for_receipt return await wait_for_receipt( @@ -54,6 +61,8 @@ async def wait(self) -> TransactionOutcome: @dataclass(frozen=True, slots=True) class SyncGaslessTransactionHandle: + """Synchronous handle for a relayed gasless transaction.""" + transaction_id: str transaction_hash: str | None _relayer: SyncTransport = field(repr=False) @@ -61,6 +70,7 @@ class SyncGaslessTransactionHandle: _poll_delay_s: float def wait(self) -> TransactionOutcome: + """Wait until the transaction reaches a terminal outcome.""" from polymarket._internal.actions.relayer.poll import poll_until_terminal_sync return poll_until_terminal_sync( @@ -74,6 +84,8 @@ def wait(self) -> TransactionOutcome: @dataclass(frozen=True, slots=True) class SyncEoaTransactionHandle: + """Synchronous handle for a directly broadcast EOA transaction.""" + transaction_hash: str _rpc: SyncJsonRpcClient = field(repr=False) _max_polls: int @@ -81,9 +93,11 @@ class SyncEoaTransactionHandle: @property def transaction_id(self) -> None: + """Return None because EOA transactions do not have relayer ids.""" return None def wait(self) -> TransactionOutcome: + """Wait until the transaction reaches a terminal outcome.""" from polymarket._internal.eoa.broadcast import wait_for_receipt_sync return wait_for_receipt_sync( @@ -95,7 +109,10 @@ def wait(self) -> TransactionOutcome: TransactionHandle: TypeAlias = GaslessTransactionHandle | EoaTransactionHandle +"""Async transaction handle returned by async wallet methods.""" + SyncTransactionHandle: TypeAlias = SyncGaslessTransactionHandle | SyncEoaTransactionHandle +"""Synchronous transaction handle returned by sync wallet methods.""" __all__ = [ From 3cd361a47bb36e4c8415cc2552941fc25a155ede Mon Sep 17 00:00:00 2001 From: Cesare Naldi <3353250+cesarenaldi@users.noreply.github.com> Date: Mon, 25 May 2026 11:46:36 +0200 Subject: [PATCH 2/4] fix: hide credential validation test switch --- src/polymarket/clients/async_secure.py | 50 ++++++++++++++++++++- src/polymarket/clients/secure.py | 50 ++++++++++++++++++++- tests/integration/test_clob_reads.py | 3 +- tests/unit/_relayer_helpers.py | 18 ++++---- tests/unit/test_account_transport.py | 28 ++++++------ tests/unit/test_auth_transport.py | 26 +++++++---- tests/unit/test_builder_attribution.py | 2 +- tests/unit/test_builder_trades.py | 2 +- tests/unit/test_client.py | 23 ++++++---- tests/unit/test_client_request_params.py | 12 ++--- tests/unit/test_clob_transport.py | 2 +- tests/unit/test_clob_transport_sync.py | 2 +- tests/unit/test_end_authentication.py | 2 +- tests/unit/test_market_order_overloads.py | 2 +- tests/unit/test_order_allowance.py | 2 +- tests/unit/test_order_client.py | 2 +- tests/unit/test_order_estimate.py | 2 +- tests/unit/test_order_limit.py | 2 +- tests/unit/test_order_market.py | 2 +- tests/unit/test_order_market_data.py | 2 +- tests/unit/test_place_order_recovery.py | 2 +- tests/unit/test_relayer_approve_erc20.py | 4 +- tests/unit/test_relayer_is_gasless_ready.py | 2 +- tests/unit/test_rewards_transport.py | 2 +- tests/unit/test_rewards_transport_sync.py | 4 +- tests/unit/test_secure_account_sync.py | 2 +- tests/unit/test_secure_api_keys_sync.py | 2 +- tests/unit/test_secure_auth_sync.py | 16 +++---- tests/unit/test_secure_orders_sync.py | 2 +- tests/unit/test_secure_rewards_sync.py | 2 +- tests/unit/test_secure_signer_defaults.py | 34 +++++++------- 31 files changed, 207 insertions(+), 99 deletions(-) diff --git a/src/polymarket/clients/async_secure.py b/src/polymarket/clients/async_secure.py index eb28429..5ffa275 100644 --- a/src/polymarket/clients/async_secure.py +++ b/src/polymarket/clients/async_secure.py @@ -256,7 +256,6 @@ async def create( credentials: ApiKeyCreds | None = None, api_key: ApiKey | None = None, nonce: int = 0, - validate_credentials: bool = True, logger: logging.Logger | None = None, ) -> Self: """Create an authenticated async client. @@ -268,12 +267,59 @@ async def create( derived during client creation. api_key: Optional key for gasless wallet and relayed transaction workflows. nonce: Credential derivation nonce. Cannot be combined with ``credentials``. - validate_credentials: Whether provided credentials should be validated. Raises: UserInputError: If key material, wallet, nonce, or credentials are invalid. RequestRejectedError: If credential derivation or validation is rejected. """ + return await cls._create( + private_key=private_key, + wallet=wallet, + environment=environment, + credentials=credentials, + api_key=api_key, + nonce=nonce, + validate_credentials=True, + logger=logger, + ) + + @classmethod + async def _create_for_testing( + cls, + *, + private_key: str, + wallet: str | None = None, + environment: Environment = PRODUCTION, + credentials: ApiKeyCreds | None = None, + api_key: ApiKey | None = None, + nonce: int = 0, + validate_credentials: bool = True, + logger: logging.Logger | None = None, + ) -> Self: + return await cls._create( + private_key=private_key, + wallet=wallet, + environment=environment, + credentials=credentials, + api_key=api_key, + nonce=nonce, + validate_credentials=validate_credentials, + logger=logger, + ) + + @classmethod + async def _create( + cls, + *, + private_key: str, + wallet: str | None = None, + environment: Environment = PRODUCTION, + credentials: ApiKeyCreds | None = None, + api_key: ApiKey | None = None, + nonce: int = 0, + validate_credentials: bool, + logger: logging.Logger | None = None, + ) -> Self: if not private_key: raise UserInputError("private_key is required") _validate_nonce(nonce) diff --git a/src/polymarket/clients/secure.py b/src/polymarket/clients/secure.py index ff9113d..bb66140 100644 --- a/src/polymarket/clients/secure.py +++ b/src/polymarket/clients/secure.py @@ -230,7 +230,6 @@ def create( credentials: ApiKeyCreds | None = None, api_key: ApiKey | None = None, nonce: int = 0, - validate_credentials: bool = True, logger: logging.Logger | None = None, ) -> Self: """Create an authenticated synchronous client. @@ -242,12 +241,59 @@ def create( derived during client creation. api_key: Optional key for gasless wallet and relayed transaction workflows. nonce: Credential derivation nonce. Cannot be combined with ``credentials``. - validate_credentials: Whether provided credentials should be validated. Raises: UserInputError: If key material, wallet, nonce, or credentials are invalid. RequestRejectedError: If credential derivation or validation is rejected. """ + return cls._create( + private_key=private_key, + wallet=wallet, + environment=environment, + credentials=credentials, + api_key=api_key, + nonce=nonce, + validate_credentials=True, + logger=logger, + ) + + @classmethod + def _create_for_testing( + cls, + *, + private_key: str, + wallet: str | None = None, + environment: Environment = PRODUCTION, + credentials: ApiKeyCreds | None = None, + api_key: ApiKey | None = None, + nonce: int = 0, + validate_credentials: bool = True, + logger: logging.Logger | None = None, + ) -> Self: + return cls._create( + private_key=private_key, + wallet=wallet, + environment=environment, + credentials=credentials, + api_key=api_key, + nonce=nonce, + validate_credentials=validate_credentials, + logger=logger, + ) + + @classmethod + def _create( + cls, + *, + private_key: str, + wallet: str | None = None, + environment: Environment = PRODUCTION, + credentials: ApiKeyCreds | None = None, + api_key: ApiKey | None = None, + nonce: int = 0, + validate_credentials: bool, + logger: logging.Logger | None = None, + ) -> Self: if not private_key: raise UserInputError("private_key is required") _validate_nonce(nonce) diff --git a/tests/integration/test_clob_reads.py b/tests/integration/test_clob_reads.py index 4e5a24b..2777fb3 100644 --- a/tests/integration/test_clob_reads.py +++ b/tests/integration/test_clob_reads.py @@ -1,3 +1,4 @@ +# pyright: reportPrivateUsage=false import asyncio from decimal import Decimal @@ -40,7 +41,7 @@ def test_async_secure_get_midpoint_returns_decimal_in_unit_range( active_clob_token: TokenId, ) -> None: async def run() -> Decimal: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/_relayer_helpers.py b/tests/unit/_relayer_helpers.py index fc86bdb..0859e44 100644 --- a/tests/unit/_relayer_helpers.py +++ b/tests/unit/_relayer_helpers.py @@ -31,7 +31,7 @@ async def make_deposit_client() -> AsyncSecureClient: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -48,7 +48,7 @@ async def make_proxy_client() -> AsyncSecureClient: signer = Account.from_key(PK_PROXY_WALLET) wallet = derive_proxy_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PK_PROXY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -61,7 +61,7 @@ async def make_eoa_client(*, with_api_key: bool = True) -> AsyncSecureClient: from eth_account import Account signer = Account.from_key(PK_DEPLOY_WALLET) - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, @@ -80,7 +80,7 @@ async def make_eoa_client_with_rpc( env = dataclasses.replace(PRODUCTION, rpc_url="https://rpc.test") signer = Account.from_key(PK_DEPLOY_WALLET) - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, @@ -153,7 +153,7 @@ async def make_safe_client() -> AsyncSecureClient: signer = Account.from_key(PK_SAFE_WALLET) wallet = derive_safe_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PK_SAFE_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -226,7 +226,7 @@ def make_sync_eoa_client(*, with_api_key: bool = True) -> SecureClient: from eth_account import Account signer = Account.from_key(PK_DEPLOY_WALLET) - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, @@ -243,7 +243,7 @@ def make_sync_deposit_client() -> SecureClient: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -260,7 +260,7 @@ def make_sync_proxy_client() -> SecureClient: signer = Account.from_key(PK_PROXY_WALLET) wallet = derive_proxy_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PK_PROXY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -277,7 +277,7 @@ def make_sync_safe_client() -> SecureClient: signer = Account.from_key(PK_SAFE_WALLET) wallet = derive_safe_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PK_SAFE_WALLET, wallet=wallet, credentials=FAKE_CREDS, diff --git a/tests/unit/test_account_transport.py b/tests/unit/test_account_transport.py index 7b176b8..c3cf413 100644 --- a/tests/unit/test_account_transport.py +++ b/tests/unit/test_account_transport.py @@ -96,7 +96,7 @@ def _assert_l2_headers(request: httpx.Request) -> None: def _make_client() -> AsyncSecureClient: return asyncio.run( - AsyncSecureClient.create( + AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -109,7 +109,7 @@ def test_get_closed_only_mode_returns_bool_and_uses_l2_headers() -> None: captured: list[httpx.Request] = [] async def run() -> bool: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -147,7 +147,7 @@ def handler(request: httpx.Request) -> httpx.Response: return httpx.Response(200, json=next(responses), request=request) async def run() -> list[str]: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -177,7 +177,7 @@ def test_get_order_targets_data_order_path() -> None: captured: list[httpx.Request] = [] async def run() -> str: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -209,7 +209,7 @@ def handler(request: httpx.Request) -> httpx.Response: return httpx.Response(200, json=next(responses), request=request) async def run() -> list[str]: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -239,7 +239,7 @@ def test_get_notifications_includes_signature_type_for_eoa_wallet() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -263,7 +263,7 @@ def test_drop_notifications_uses_delete_with_comma_separated_ids() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -286,7 +286,7 @@ async def run() -> None: def test_drop_notifications_rejects_empty_id_list() -> None: async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -305,7 +305,7 @@ def test_get_balance_allowance_for_collateral_omits_token_id() -> None: captured: list[httpx.Request] = [] async def run() -> int: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -334,7 +334,7 @@ def test_get_balance_allowance_for_conditional_includes_token_id() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -366,7 +366,7 @@ def test_secure_client_classifies_eoa_when_wallet_equals_signer() -> None: def test_secure_client_normalizes_wallet_to_checksum() -> None: async def run() -> str: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS.lower(), credentials=FAKE_CREDS, @@ -382,7 +382,7 @@ async def run() -> str: def test_secure_client_rejects_invalid_wallet_address() -> None: async def run() -> None: - await AsyncSecureClient.create( + await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet="not-an-address", credentials=FAKE_CREDS, @@ -400,7 +400,7 @@ def test_secure_client_defaults_wallet_to_signer_address() -> None: expected = to_checksum_address(Account.from_key(PRIVATE_KEY).address) async def run() -> str: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, credentials=FAKE_CREDS, validate_credentials=False, @@ -416,7 +416,7 @@ async def run() -> str: def test_secure_client_rejects_unrelated_wallet_address() -> None: async def run() -> None: - await AsyncSecureClient.create( + await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet="0x0000000000000000000000000000000000000002", credentials=FAKE_CREDS, diff --git a/tests/unit/test_auth_transport.py b/tests/unit/test_auth_transport.py index b357685..3c01aeb 100644 --- a/tests/unit/test_auth_transport.py +++ b/tests/unit/test_auth_transport.py @@ -126,7 +126,7 @@ async def run() -> ApiKeyCreds: def test_async_secure_create_with_credentials_skips_auth_flow() -> None: async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -144,7 +144,7 @@ def test_fetch_api_keys_sends_l2_headers() -> None: captured: list[httpx.Request] = [] async def run() -> tuple[str, ...]: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -173,7 +173,7 @@ def test_delete_api_key_succeeds_on_ok_response() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -193,7 +193,7 @@ async def run() -> None: def test_delete_api_key_raises_unexpected_response_on_non_ok_payload() -> None: async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -211,7 +211,7 @@ async def run() -> None: def test_fetch_api_keys_propagates_401_as_request_rejected() -> None: async def run() -> tuple[str, ...]: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -232,7 +232,7 @@ def test_async_secure_create_rejects_credentials_with_nonzero_nonce() -> None: from polymarket.errors import UserInputError async def run() -> None: - await AsyncSecureClient.create( + await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, nonce=1 ) @@ -244,7 +244,11 @@ def test_async_secure_create_rejects_negative_nonce() -> None: from polymarket.errors import UserInputError async def run() -> None: - await AsyncSecureClient.create(private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=-1) + await AsyncSecureClient._create_for_testing( + private_key=PRIVATE_KEY, + wallet=SIGNER_ADDRESS, + nonce=-1, + ) with pytest.raises(UserInputError, match="non-negative integer"): asyncio.run(run()) @@ -254,7 +258,11 @@ def test_async_secure_create_rejects_bool_nonce() -> None: from polymarket.errors import UserInputError async def run() -> None: - await AsyncSecureClient.create(private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=True) # type: ignore[arg-type] + await AsyncSecureClient._create_for_testing( + private_key=PRIVATE_KEY, + wallet=SIGNER_ADDRESS, + nonce=True, # type: ignore[arg-type] + ) with pytest.raises(UserInputError, match="non-negative integer"): asyncio.run(run()) @@ -298,7 +306,7 @@ def test_l2_signature_includes_canonical_body_for_authenticated_post() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_builder_attribution.py b/tests/unit/test_builder_attribution.py index ef54e3f..424f5cf 100644 --- a/tests/unit/test_builder_attribution.py +++ b/tests/unit/test_builder_attribution.py @@ -190,7 +190,7 @@ def _install_secure_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=_PRIVATE_KEY, wallet=_SIGNER_ADDRESS, credentials=_FAKE_CREDS, diff --git a/tests/unit/test_builder_trades.py b/tests/unit/test_builder_trades.py index 36e7fb6..ce4623e 100644 --- a/tests/unit/test_builder_trades.py +++ b/tests/unit/test_builder_trades.py @@ -342,7 +342,7 @@ def handler(request: httpx.Request) -> httpx.Response: ) async def run() -> BuilderTrade: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=_PRIVATE_KEY, wallet=_SIGNER, credentials=_FAKE_CREDS, diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 8d537af..b96052d 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -1,4 +1,6 @@ +# pyright: reportPrivateUsage=false import asyncio +import inspect from typing import cast import pytest @@ -45,7 +47,7 @@ async def run() -> None: def test_secure_client_factory_uses_production_by_default() -> None: - client = SecureClient.create( + client = SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -57,6 +59,11 @@ def test_secure_client_factory_uses_production_by_default() -> None: client.close() +def test_secure_client_factory_signature_hides_test_validation_switch() -> None: + assert "validate_credentials" not in inspect.signature(SecureClient.create).parameters + assert "validate_credentials" not in inspect.signature(AsyncSecureClient.create).parameters + + def test_secure_client_requires_factory() -> None: from polymarket._internal.context import SyncSecureClientContext @@ -65,7 +72,7 @@ def test_secure_client_requires_factory() -> None: def test_secure_client_supports_context_manager() -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -76,7 +83,7 @@ def test_secure_client_supports_context_manager() -> None: def test_async_secure_client_factory_uses_production_by_default() -> None: async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -97,7 +104,7 @@ def test_async_secure_client_requires_factory() -> None: def test_async_secure_client_supports_context_manager() -> None: async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -110,7 +117,7 @@ async def run() -> None: def test_secure_client_exposes_signer_wallet() -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -121,7 +128,7 @@ def test_secure_client_exposes_signer_wallet() -> None: def test_async_secure_client_exposes_signer_wallet() -> None: async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -146,7 +153,7 @@ def test_secure_client_wallet_defaults_to_signer_when_omitted() -> None: expected = to_checksum_address(Account.from_key(PRIVATE_KEY).address) - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, credentials=FAKE_CREDS, validate_credentials=False, @@ -170,7 +177,7 @@ def test_async_secure_client_wallet_defaults_to_signer_when_omitted() -> None: expected = to_checksum_address(Account.from_key(PRIVATE_KEY).address) async def run() -> str: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, validate_credentials=False, ) diff --git a/tests/unit/test_client_request_params.py b/tests/unit/test_client_request_params.py index 3b2401c..ac5f8c6 100644 --- a/tests/unit/test_client_request_params.py +++ b/tests/unit/test_client_request_params.py @@ -116,7 +116,7 @@ async def run() -> None: def test_secure_list_trades_passes_event_id() -> None: captured: list[httpx.Request] = [] - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -134,7 +134,7 @@ def test_async_secure_list_trades_passes_event_id() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -178,7 +178,7 @@ async def run() -> None: def test_secure_list_activity_passes_event_id() -> None: captured: list[httpx.Request] = [] - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -196,7 +196,7 @@ def test_async_secure_list_activity_passes_event_id() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -228,7 +228,7 @@ def test_public_list_positions_passes_event_id() -> None: def test_secure_list_positions_passes_event_id() -> None: captured: list[httpx.Request] = [] - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -259,7 +259,7 @@ def test_secure_list_trades_rejects_market_and_event_id_together() -> None: from polymarket.errors import UserInputError with ( - SecureClient.create( + SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_clob_transport.py b/tests/unit/test_clob_transport.py index 64b9658..660a216 100644 --- a/tests/unit/test_clob_transport.py +++ b/tests/unit/test_clob_transport.py @@ -73,7 +73,7 @@ def test_async_secure_get_midpoint_uses_same_clob_endpoint() -> None: captured: list[httpx.Request] = [] async def run() -> Decimal: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_clob_transport_sync.py b/tests/unit/test_clob_transport_sync.py index f44cd4e..f437699 100644 --- a/tests/unit/test_clob_transport_sync.py +++ b/tests/unit/test_clob_transport_sync.py @@ -61,7 +61,7 @@ def _body(request: httpx.Request) -> object: def _secure_client() -> SecureClient: - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_end_authentication.py b/tests/unit/test_end_authentication.py index 22e62cf..297b439 100644 --- a/tests/unit/test_end_authentication.py +++ b/tests/unit/test_end_authentication.py @@ -35,7 +35,7 @@ def _install_secure_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _build_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_market_order_overloads.py b/tests/unit/test_market_order_overloads.py index a5b937b..58b6c01 100644 --- a/tests/unit/test_market_order_overloads.py +++ b/tests/unit/test_market_order_overloads.py @@ -19,7 +19,7 @@ def _make_client() -> AsyncSecureClient: return asyncio.run( - AsyncSecureClient.create( + AsyncSecureClient._create_for_testing( private_key=_PRIVATE_KEY, wallet=_SIGNER, credentials=_FAKE_CREDS, diff --git a/tests/unit/test_order_allowance.py b/tests/unit/test_order_allowance.py index 399516d..9b582d2 100644 --- a/tests/unit/test_order_allowance.py +++ b/tests/unit/test_order_allowance.py @@ -32,7 +32,7 @@ def handler(request: httpx.Request) -> httpx.Response: async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_client.py b/tests/unit/test_order_client.py index fa07db6..caa3746 100644 --- a/tests/unit/test_order_client.py +++ b/tests/unit/test_order_client.py @@ -104,7 +104,7 @@ def _install_secure_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_estimate.py b/tests/unit/test_order_estimate.py index 29a02a9..9935e0a 100644 --- a/tests/unit/test_order_estimate.py +++ b/tests/unit/test_order_estimate.py @@ -49,7 +49,7 @@ def handler(request: httpx.Request) -> httpx.Response: async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_limit.py b/tests/unit/test_order_limit.py index da4bf0f..df125a9 100644 --- a/tests/unit/test_order_limit.py +++ b/tests/unit/test_order_limit.py @@ -43,7 +43,7 @@ def _install_public_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_market.py b/tests/unit/test_order_market.py index 34ae025..1e11b4d 100644 --- a/tests/unit/test_order_market.py +++ b/tests/unit/test_order_market.py @@ -57,7 +57,7 @@ def _install_public_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_market_data.py b/tests/unit/test_order_market_data.py index 096c82a..f54c157 100644 --- a/tests/unit/test_order_market_data.py +++ b/tests/unit/test_order_market_data.py @@ -41,7 +41,7 @@ def _install_public_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_place_order_recovery.py b/tests/unit/test_place_order_recovery.py index 170db60..b981001 100644 --- a/tests/unit/test_place_order_recovery.py +++ b/tests/unit/test_place_order_recovery.py @@ -33,7 +33,7 @@ async def _make_deposit_client() -> AsyncSecureClient: signer = Account.from_key(_PRIVATE_KEY) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=_PRIVATE_KEY, wallet=wallet, credentials=_CREDS, diff --git a/tests/unit/test_relayer_approve_erc20.py b/tests/unit/test_relayer_approve_erc20.py index d89ee94..4aea31a 100644 --- a/tests/unit/test_relayer_approve_erc20.py +++ b/tests/unit/test_relayer_approve_erc20.py @@ -35,7 +35,7 @@ def test_approve_erc20_rejects_when_no_api_key() -> None: async def run() -> None: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -425,7 +425,7 @@ def test_approve_erc20_works_with_relayer_api_key() -> None: async def run() -> None: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, diff --git a/tests/unit/test_relayer_is_gasless_ready.py b/tests/unit/test_relayer_is_gasless_ready.py index 95d55d4..7a4a7ab 100644 --- a/tests/unit/test_relayer_is_gasless_ready.py +++ b/tests/unit/test_relayer_is_gasless_ready.py @@ -27,7 +27,7 @@ async def _make_eoa_secure_client() -> AsyncSecureClient: from eth_account import Account signer = Account.from_key(PK_DEPLOY_WALLET) - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, diff --git a/tests/unit/test_rewards_transport.py b/tests/unit/test_rewards_transport.py index a34331e..0b11f4b 100644 --- a/tests/unit/test_rewards_transport.py +++ b/tests/unit/test_rewards_transport.py @@ -65,7 +65,7 @@ def _install_secure_public_clob(client: AsyncSecureClient, handler: httpx.MockTr async def _make_secure_client() -> AsyncSecureClient: - return await AsyncSecureClient.create( + return await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_rewards_transport_sync.py b/tests/unit/test_rewards_transport_sync.py index 56b358b..649aa2e 100644 --- a/tests/unit/test_rewards_transport_sync.py +++ b/tests/unit/test_rewards_transport_sync.py @@ -106,7 +106,7 @@ def test_public_passes_sponsored_filter(self) -> None: def test_secure_uses_unsigned_clob_not_secure_clob(self) -> None: captured: list[httpx.Request] = [] - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -143,7 +143,7 @@ def test_public_routes_with_condition_id_in_path(self) -> None: def test_secure_uses_unsigned_clob_not_secure_clob(self) -> None: captured: list[httpx.Request] = [] - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_account_sync.py b/tests/unit/test_secure_account_sync.py index a42157a..cb18626 100644 --- a/tests/unit/test_secure_account_sync.py +++ b/tests/unit/test_secure_account_sync.py @@ -94,7 +94,7 @@ def _assert_l2_headers(request: httpx.Request) -> None: def _make_client() -> SecureClient: - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_api_keys_sync.py b/tests/unit/test_secure_api_keys_sync.py index 95fcaad..97fa553 100644 --- a/tests/unit/test_secure_api_keys_sync.py +++ b/tests/unit/test_secure_api_keys_sync.py @@ -34,7 +34,7 @@ def _install_secure_clob(client: SecureClient, handler: httpx.MockTransport) -> def _make_client() -> SecureClient: - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_auth_sync.py b/tests/unit/test_secure_auth_sync.py index 8991ed8..c060d05 100644 --- a/tests/unit/test_secure_auth_sync.py +++ b/tests/unit/test_secure_auth_sync.py @@ -26,7 +26,7 @@ def handler(request: httpx.Request) -> httpx.Response: def _make_client() -> SecureClient: - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -107,7 +107,7 @@ def handler(request: httpx.Request) -> httpx.Response: def test_create_with_credentials_skips_auth_flow_when_validation_disabled() -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -147,7 +147,7 @@ def handler(request: httpx.Request) -> httpx.Response: def test_create_rejects_credentials_with_nonzero_nonce() -> None: with pytest.raises(UserInputError, match="nonce cannot be combined"): - SecureClient.create( + SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -157,12 +157,12 @@ def test_create_rejects_credentials_with_nonzero_nonce() -> None: def test_create_rejects_negative_nonce() -> None: with pytest.raises(UserInputError, match="non-negative integer"): - SecureClient.create(private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=-1) + SecureClient._create_for_testing(private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=-1) def test_create_rejects_bool_nonce() -> None: with pytest.raises(UserInputError, match="non-negative integer"): - SecureClient.create( + SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=cast(int, True), @@ -170,7 +170,7 @@ def test_create_rejects_bool_nonce() -> None: def test_create_defaults_wallet_to_signer_when_omitted() -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, credentials=FAKE_CREDS, validate_credentials=False, @@ -181,7 +181,7 @@ def test_create_defaults_wallet_to_signer_when_omitted() -> None: def test_create_rejects_invalid_wallet_address() -> None: with pytest.raises(UserInputError, match="Invalid wallet address"): - SecureClient.create( + SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet="not-an-address", credentials=FAKE_CREDS, @@ -196,7 +196,7 @@ def test_create_classifies_eoa_when_wallet_equals_signer() -> None: def test_create_normalizes_wallet_to_checksum() -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS.lower(), credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_orders_sync.py b/tests/unit/test_secure_orders_sync.py index 16a2654..37efb5f 100644 --- a/tests/unit/test_secure_orders_sync.py +++ b/tests/unit/test_secure_orders_sync.py @@ -98,7 +98,7 @@ def _install_secure_clob(client: SecureClient, handler: httpx.MockTransport) -> def _make_client() -> SecureClient: - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_rewards_sync.py b/tests/unit/test_secure_rewards_sync.py index 444724d..014dad9 100644 --- a/tests/unit/test_secure_rewards_sync.py +++ b/tests/unit/test_secure_rewards_sync.py @@ -32,7 +32,7 @@ def _install_secure_clob(client: SecureClient, handler: httpx.MockTransport) -> def _make_client() -> SecureClient: - return SecureClient.create( + return SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_signer_defaults.py b/tests/unit/test_secure_signer_defaults.py index 289e4e8..2b09ca8 100644 --- a/tests/unit/test_secure_signer_defaults.py +++ b/tests/unit/test_secure_signer_defaults.py @@ -53,7 +53,7 @@ def _captured() -> list[httpx.Request]: def test_secure_get_portfolio_values_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -68,7 +68,7 @@ def test_secure_get_portfolio_values_defaults_to_signer(captured: list[httpx.Req def test_secure_get_portfolio_values_respects_explicit_user( captured: list[httpx.Request], ) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -86,7 +86,7 @@ def test_secure_get_portfolio_values_respects_explicit_user( def test_secure_get_traded_market_count_defaults_to_signer( captured: list[httpx.Request], ) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -103,7 +103,7 @@ def test_secure_get_traded_market_count_defaults_to_signer( def test_secure_get_traded_market_count_respects_explicit_user( captured: list[httpx.Request], ) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -127,7 +127,7 @@ def handler(request: httpx.Request) -> httpx.Response: captured.append(request) return httpx.Response(200, content=b"PK\x03\x04", request=request) - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -146,7 +146,7 @@ def handler(request: httpx.Request) -> httpx.Response: captured.append(request) return httpx.Response(200, content=b"PK\x03\x04", request=request) - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -162,7 +162,7 @@ def handler(request: httpx.Request) -> httpx.Response: def test_secure_list_positions_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -175,7 +175,7 @@ def test_secure_list_positions_defaults_to_signer(captured: list[httpx.Request]) def test_secure_list_positions_respects_explicit_user(captured: list[httpx.Request]) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -191,7 +191,7 @@ def test_secure_list_positions_respects_explicit_user(captured: list[httpx.Reque def test_secure_list_closed_positions_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -207,7 +207,7 @@ def test_secure_list_closed_positions_defaults_to_signer(captured: list[httpx.Re def test_secure_list_trades_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -223,7 +223,7 @@ def test_secure_list_trades_defaults_to_signer(captured: list[httpx.Request]) -> def test_secure_list_activity_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -242,7 +242,7 @@ def test_async_secure_list_positions_defaults_to_signer() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -262,7 +262,7 @@ def test_async_secure_list_positions_respects_explicit_user() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -286,7 +286,7 @@ def test_async_secure_list_positions_defaults_to_wallet_when_proxy() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=proxy_wallet, credentials=FAKE_CREDS, @@ -311,7 +311,7 @@ def handler(request: httpx.Request) -> httpx.Response: return httpx.Response(200, content=b"PK\x03\x04", request=request) async def run() -> None: - client = await AsyncSecureClient.create( + client = await AsyncSecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -335,7 +335,7 @@ def test_secure_list_positions_rejects_explicit_empty_user( ) -> None: from polymarket.errors import UserInputError - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -351,7 +351,7 @@ def test_secure_get_portfolio_values_rejects_explicit_empty_user( ) -> None: from polymarket.errors import UserInputError - with SecureClient.create( + with SecureClient._create_for_testing( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, From 78a2228dfa9f7f041b937ca0aea9d84d3518525d Mon Sep 17 00:00:00 2001 From: Cesare Naldi <3353250+cesarenaldi@users.noreply.github.com> Date: Mon, 25 May 2026 11:58:54 +0200 Subject: [PATCH 3/4] refactor: use private secure client helper in tests --- src/polymarket/clients/async_secure.py | 26 +--------------- src/polymarket/clients/secure.py | 26 +--------------- tests/integration/test_clob_reads.py | 2 +- tests/unit/_relayer_helpers.py | 18 +++++------ tests/unit/test_account_transport.py | 28 ++++++++--------- tests/unit/test_auth_transport.py | 18 +++++------ tests/unit/test_builder_attribution.py | 2 +- tests/unit/test_builder_trades.py | 2 +- tests/unit/test_client.py | 16 +++++----- tests/unit/test_client_request_params.py | 12 ++++---- tests/unit/test_clob_transport.py | 2 +- tests/unit/test_clob_transport_sync.py | 2 +- tests/unit/test_end_authentication.py | 2 +- tests/unit/test_market_order_overloads.py | 2 +- tests/unit/test_order_allowance.py | 2 +- tests/unit/test_order_client.py | 2 +- tests/unit/test_order_estimate.py | 2 +- tests/unit/test_order_limit.py | 2 +- tests/unit/test_order_market.py | 2 +- tests/unit/test_order_market_data.py | 2 +- tests/unit/test_place_order_recovery.py | 2 +- tests/unit/test_relayer_approve_erc20.py | 4 +-- tests/unit/test_relayer_is_gasless_ready.py | 2 +- tests/unit/test_rewards_transport.py | 2 +- tests/unit/test_rewards_transport_sync.py | 4 +-- tests/unit/test_secure_account_sync.py | 2 +- tests/unit/test_secure_api_keys_sync.py | 2 +- tests/unit/test_secure_auth_sync.py | 16 +++++----- tests/unit/test_secure_orders_sync.py | 2 +- tests/unit/test_secure_rewards_sync.py | 2 +- tests/unit/test_secure_signer_defaults.py | 34 ++++++++++----------- 31 files changed, 97 insertions(+), 145 deletions(-) diff --git a/src/polymarket/clients/async_secure.py b/src/polymarket/clients/async_secure.py index 5ffa275..1d94fb0 100644 --- a/src/polymarket/clients/async_secure.py +++ b/src/polymarket/clients/async_secure.py @@ -283,30 +283,6 @@ async def create( logger=logger, ) - @classmethod - async def _create_for_testing( - cls, - *, - private_key: str, - wallet: str | None = None, - environment: Environment = PRODUCTION, - credentials: ApiKeyCreds | None = None, - api_key: ApiKey | None = None, - nonce: int = 0, - validate_credentials: bool = True, - logger: logging.Logger | None = None, - ) -> Self: - return await cls._create( - private_key=private_key, - wallet=wallet, - environment=environment, - credentials=credentials, - api_key=api_key, - nonce=nonce, - validate_credentials=validate_credentials, - logger=logger, - ) - @classmethod async def _create( cls, @@ -317,7 +293,7 @@ async def _create( credentials: ApiKeyCreds | None = None, api_key: ApiKey | None = None, nonce: int = 0, - validate_credentials: bool, + validate_credentials: bool = True, logger: logging.Logger | None = None, ) -> Self: if not private_key: diff --git a/src/polymarket/clients/secure.py b/src/polymarket/clients/secure.py index bb66140..87a76b9 100644 --- a/src/polymarket/clients/secure.py +++ b/src/polymarket/clients/secure.py @@ -257,30 +257,6 @@ def create( logger=logger, ) - @classmethod - def _create_for_testing( - cls, - *, - private_key: str, - wallet: str | None = None, - environment: Environment = PRODUCTION, - credentials: ApiKeyCreds | None = None, - api_key: ApiKey | None = None, - nonce: int = 0, - validate_credentials: bool = True, - logger: logging.Logger | None = None, - ) -> Self: - return cls._create( - private_key=private_key, - wallet=wallet, - environment=environment, - credentials=credentials, - api_key=api_key, - nonce=nonce, - validate_credentials=validate_credentials, - logger=logger, - ) - @classmethod def _create( cls, @@ -291,7 +267,7 @@ def _create( credentials: ApiKeyCreds | None = None, api_key: ApiKey | None = None, nonce: int = 0, - validate_credentials: bool, + validate_credentials: bool = True, logger: logging.Logger | None = None, ) -> Self: if not private_key: diff --git a/tests/integration/test_clob_reads.py b/tests/integration/test_clob_reads.py index 2777fb3..f4615d0 100644 --- a/tests/integration/test_clob_reads.py +++ b/tests/integration/test_clob_reads.py @@ -41,7 +41,7 @@ def test_async_secure_get_midpoint_returns_decimal_in_unit_range( active_clob_token: TokenId, ) -> None: async def run() -> Decimal: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/_relayer_helpers.py b/tests/unit/_relayer_helpers.py index 0859e44..82afb9e 100644 --- a/tests/unit/_relayer_helpers.py +++ b/tests/unit/_relayer_helpers.py @@ -31,7 +31,7 @@ async def make_deposit_client() -> AsyncSecureClient: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -48,7 +48,7 @@ async def make_proxy_client() -> AsyncSecureClient: signer = Account.from_key(PK_PROXY_WALLET) wallet = derive_proxy_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PK_PROXY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -61,7 +61,7 @@ async def make_eoa_client(*, with_api_key: bool = True) -> AsyncSecureClient: from eth_account import Account signer = Account.from_key(PK_DEPLOY_WALLET) - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, @@ -80,7 +80,7 @@ async def make_eoa_client_with_rpc( env = dataclasses.replace(PRODUCTION, rpc_url="https://rpc.test") signer = Account.from_key(PK_DEPLOY_WALLET) - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, @@ -153,7 +153,7 @@ async def make_safe_client() -> AsyncSecureClient: signer = Account.from_key(PK_SAFE_WALLET) wallet = derive_safe_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PK_SAFE_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -226,7 +226,7 @@ def make_sync_eoa_client(*, with_api_key: bool = True) -> SecureClient: from eth_account import Account signer = Account.from_key(PK_DEPLOY_WALLET) - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, @@ -243,7 +243,7 @@ def make_sync_deposit_client() -> SecureClient: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -260,7 +260,7 @@ def make_sync_proxy_client() -> SecureClient: signer = Account.from_key(PK_PROXY_WALLET) wallet = derive_proxy_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PK_PROXY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -277,7 +277,7 @@ def make_sync_safe_client() -> SecureClient: signer = Account.from_key(PK_SAFE_WALLET) wallet = derive_safe_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PK_SAFE_WALLET, wallet=wallet, credentials=FAKE_CREDS, diff --git a/tests/unit/test_account_transport.py b/tests/unit/test_account_transport.py index c3cf413..9442122 100644 --- a/tests/unit/test_account_transport.py +++ b/tests/unit/test_account_transport.py @@ -96,7 +96,7 @@ def _assert_l2_headers(request: httpx.Request) -> None: def _make_client() -> AsyncSecureClient: return asyncio.run( - AsyncSecureClient._create_for_testing( + AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -109,7 +109,7 @@ def test_get_closed_only_mode_returns_bool_and_uses_l2_headers() -> None: captured: list[httpx.Request] = [] async def run() -> bool: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -147,7 +147,7 @@ def handler(request: httpx.Request) -> httpx.Response: return httpx.Response(200, json=next(responses), request=request) async def run() -> list[str]: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -177,7 +177,7 @@ def test_get_order_targets_data_order_path() -> None: captured: list[httpx.Request] = [] async def run() -> str: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -209,7 +209,7 @@ def handler(request: httpx.Request) -> httpx.Response: return httpx.Response(200, json=next(responses), request=request) async def run() -> list[str]: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -239,7 +239,7 @@ def test_get_notifications_includes_signature_type_for_eoa_wallet() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -263,7 +263,7 @@ def test_drop_notifications_uses_delete_with_comma_separated_ids() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -286,7 +286,7 @@ async def run() -> None: def test_drop_notifications_rejects_empty_id_list() -> None: async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -305,7 +305,7 @@ def test_get_balance_allowance_for_collateral_omits_token_id() -> None: captured: list[httpx.Request] = [] async def run() -> int: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -334,7 +334,7 @@ def test_get_balance_allowance_for_conditional_includes_token_id() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -366,7 +366,7 @@ def test_secure_client_classifies_eoa_when_wallet_equals_signer() -> None: def test_secure_client_normalizes_wallet_to_checksum() -> None: async def run() -> str: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS.lower(), credentials=FAKE_CREDS, @@ -382,7 +382,7 @@ async def run() -> str: def test_secure_client_rejects_invalid_wallet_address() -> None: async def run() -> None: - await AsyncSecureClient._create_for_testing( + await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet="not-an-address", credentials=FAKE_CREDS, @@ -400,7 +400,7 @@ def test_secure_client_defaults_wallet_to_signer_address() -> None: expected = to_checksum_address(Account.from_key(PRIVATE_KEY).address) async def run() -> str: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, credentials=FAKE_CREDS, validate_credentials=False, @@ -416,7 +416,7 @@ async def run() -> str: def test_secure_client_rejects_unrelated_wallet_address() -> None: async def run() -> None: - await AsyncSecureClient._create_for_testing( + await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet="0x0000000000000000000000000000000000000002", credentials=FAKE_CREDS, diff --git a/tests/unit/test_auth_transport.py b/tests/unit/test_auth_transport.py index 3c01aeb..8af7c1b 100644 --- a/tests/unit/test_auth_transport.py +++ b/tests/unit/test_auth_transport.py @@ -126,7 +126,7 @@ async def run() -> ApiKeyCreds: def test_async_secure_create_with_credentials_skips_auth_flow() -> None: async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -144,7 +144,7 @@ def test_fetch_api_keys_sends_l2_headers() -> None: captured: list[httpx.Request] = [] async def run() -> tuple[str, ...]: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -173,7 +173,7 @@ def test_delete_api_key_succeeds_on_ok_response() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -193,7 +193,7 @@ async def run() -> None: def test_delete_api_key_raises_unexpected_response_on_non_ok_payload() -> None: async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -211,7 +211,7 @@ async def run() -> None: def test_fetch_api_keys_propagates_401_as_request_rejected() -> None: async def run() -> tuple[str, ...]: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -232,7 +232,7 @@ def test_async_secure_create_rejects_credentials_with_nonzero_nonce() -> None: from polymarket.errors import UserInputError async def run() -> None: - await AsyncSecureClient._create_for_testing( + await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, nonce=1 ) @@ -244,7 +244,7 @@ def test_async_secure_create_rejects_negative_nonce() -> None: from polymarket.errors import UserInputError async def run() -> None: - await AsyncSecureClient._create_for_testing( + await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=-1, @@ -258,7 +258,7 @@ def test_async_secure_create_rejects_bool_nonce() -> None: from polymarket.errors import UserInputError async def run() -> None: - await AsyncSecureClient._create_for_testing( + await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=True, # type: ignore[arg-type] @@ -306,7 +306,7 @@ def test_l2_signature_includes_canonical_body_for_authenticated_post() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_builder_attribution.py b/tests/unit/test_builder_attribution.py index 424f5cf..f48f9e2 100644 --- a/tests/unit/test_builder_attribution.py +++ b/tests/unit/test_builder_attribution.py @@ -190,7 +190,7 @@ def _install_secure_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=_PRIVATE_KEY, wallet=_SIGNER_ADDRESS, credentials=_FAKE_CREDS, diff --git a/tests/unit/test_builder_trades.py b/tests/unit/test_builder_trades.py index ce4623e..52b1bc1 100644 --- a/tests/unit/test_builder_trades.py +++ b/tests/unit/test_builder_trades.py @@ -342,7 +342,7 @@ def handler(request: httpx.Request) -> httpx.Response: ) async def run() -> BuilderTrade: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=_PRIVATE_KEY, wallet=_SIGNER, credentials=_FAKE_CREDS, diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index b96052d..5d34152 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -47,7 +47,7 @@ async def run() -> None: def test_secure_client_factory_uses_production_by_default() -> None: - client = SecureClient._create_for_testing( + client = SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -72,7 +72,7 @@ def test_secure_client_requires_factory() -> None: def test_secure_client_supports_context_manager() -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -83,7 +83,7 @@ def test_secure_client_supports_context_manager() -> None: def test_async_secure_client_factory_uses_production_by_default() -> None: async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -104,7 +104,7 @@ def test_async_secure_client_requires_factory() -> None: def test_async_secure_client_supports_context_manager() -> None: async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -117,7 +117,7 @@ async def run() -> None: def test_secure_client_exposes_signer_wallet() -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -128,7 +128,7 @@ def test_secure_client_exposes_signer_wallet() -> None: def test_async_secure_client_exposes_signer_wallet() -> None: async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -153,7 +153,7 @@ def test_secure_client_wallet_defaults_to_signer_when_omitted() -> None: expected = to_checksum_address(Account.from_key(PRIVATE_KEY).address) - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, credentials=FAKE_CREDS, validate_credentials=False, @@ -177,7 +177,7 @@ def test_async_secure_client_wallet_defaults_to_signer_when_omitted() -> None: expected = to_checksum_address(Account.from_key(PRIVATE_KEY).address) async def run() -> str: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, validate_credentials=False, ) diff --git a/tests/unit/test_client_request_params.py b/tests/unit/test_client_request_params.py index ac5f8c6..0174460 100644 --- a/tests/unit/test_client_request_params.py +++ b/tests/unit/test_client_request_params.py @@ -116,7 +116,7 @@ async def run() -> None: def test_secure_list_trades_passes_event_id() -> None: captured: list[httpx.Request] = [] - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -134,7 +134,7 @@ def test_async_secure_list_trades_passes_event_id() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -178,7 +178,7 @@ async def run() -> None: def test_secure_list_activity_passes_event_id() -> None: captured: list[httpx.Request] = [] - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -196,7 +196,7 @@ def test_async_secure_list_activity_passes_event_id() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -228,7 +228,7 @@ def test_public_list_positions_passes_event_id() -> None: def test_secure_list_positions_passes_event_id() -> None: captured: list[httpx.Request] = [] - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -259,7 +259,7 @@ def test_secure_list_trades_rejects_market_and_event_id_together() -> None: from polymarket.errors import UserInputError with ( - SecureClient._create_for_testing( + SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_clob_transport.py b/tests/unit/test_clob_transport.py index 660a216..6c5f75e 100644 --- a/tests/unit/test_clob_transport.py +++ b/tests/unit/test_clob_transport.py @@ -73,7 +73,7 @@ def test_async_secure_get_midpoint_uses_same_clob_endpoint() -> None: captured: list[httpx.Request] = [] async def run() -> Decimal: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_clob_transport_sync.py b/tests/unit/test_clob_transport_sync.py index f437699..7498df0 100644 --- a/tests/unit/test_clob_transport_sync.py +++ b/tests/unit/test_clob_transport_sync.py @@ -61,7 +61,7 @@ def _body(request: httpx.Request) -> object: def _secure_client() -> SecureClient: - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_end_authentication.py b/tests/unit/test_end_authentication.py index 297b439..072ab8d 100644 --- a/tests/unit/test_end_authentication.py +++ b/tests/unit/test_end_authentication.py @@ -35,7 +35,7 @@ def _install_secure_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _build_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_market_order_overloads.py b/tests/unit/test_market_order_overloads.py index 58b6c01..89e1b31 100644 --- a/tests/unit/test_market_order_overloads.py +++ b/tests/unit/test_market_order_overloads.py @@ -19,7 +19,7 @@ def _make_client() -> AsyncSecureClient: return asyncio.run( - AsyncSecureClient._create_for_testing( + AsyncSecureClient._create( private_key=_PRIVATE_KEY, wallet=_SIGNER, credentials=_FAKE_CREDS, diff --git a/tests/unit/test_order_allowance.py b/tests/unit/test_order_allowance.py index 9b582d2..54aaa40 100644 --- a/tests/unit/test_order_allowance.py +++ b/tests/unit/test_order_allowance.py @@ -32,7 +32,7 @@ def handler(request: httpx.Request) -> httpx.Response: async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_client.py b/tests/unit/test_order_client.py index caa3746..d7a6d74 100644 --- a/tests/unit/test_order_client.py +++ b/tests/unit/test_order_client.py @@ -104,7 +104,7 @@ def _install_secure_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_estimate.py b/tests/unit/test_order_estimate.py index 9935e0a..9b73b4a 100644 --- a/tests/unit/test_order_estimate.py +++ b/tests/unit/test_order_estimate.py @@ -49,7 +49,7 @@ def handler(request: httpx.Request) -> httpx.Response: async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_limit.py b/tests/unit/test_order_limit.py index df125a9..570d119 100644 --- a/tests/unit/test_order_limit.py +++ b/tests/unit/test_order_limit.py @@ -43,7 +43,7 @@ def _install_public_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_market.py b/tests/unit/test_order_market.py index 1e11b4d..c8c9b8c 100644 --- a/tests/unit/test_order_market.py +++ b/tests/unit/test_order_market.py @@ -57,7 +57,7 @@ def _install_public_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_order_market_data.py b/tests/unit/test_order_market_data.py index f54c157..ead755f 100644 --- a/tests/unit/test_order_market_data.py +++ b/tests/unit/test_order_market_data.py @@ -41,7 +41,7 @@ def _install_public_clob(client: AsyncSecureClient, handler: httpx.MockTransport async def _make_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_place_order_recovery.py b/tests/unit/test_place_order_recovery.py index b981001..db388d2 100644 --- a/tests/unit/test_place_order_recovery.py +++ b/tests/unit/test_place_order_recovery.py @@ -33,7 +33,7 @@ async def _make_deposit_client() -> AsyncSecureClient: signer = Account.from_key(_PRIVATE_KEY) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=_PRIVATE_KEY, wallet=wallet, credentials=_CREDS, diff --git a/tests/unit/test_relayer_approve_erc20.py b/tests/unit/test_relayer_approve_erc20.py index 4aea31a..d9e2e6a 100644 --- a/tests/unit/test_relayer_approve_erc20.py +++ b/tests/unit/test_relayer_approve_erc20.py @@ -35,7 +35,7 @@ def test_approve_erc20_rejects_when_no_api_key() -> None: async def run() -> None: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, @@ -425,7 +425,7 @@ def test_approve_erc20_works_with_relayer_api_key() -> None: async def run() -> None: signer = Account.from_key(PK_DEPLOY_WALLET) wallet = derive_uups_deposit_wallet_address(signer.address, PRODUCTION.wallet_derivation) - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=wallet, credentials=FAKE_CREDS, diff --git a/tests/unit/test_relayer_is_gasless_ready.py b/tests/unit/test_relayer_is_gasless_ready.py index 7a4a7ab..7a5af0f 100644 --- a/tests/unit/test_relayer_is_gasless_ready.py +++ b/tests/unit/test_relayer_is_gasless_ready.py @@ -27,7 +27,7 @@ async def _make_eoa_secure_client() -> AsyncSecureClient: from eth_account import Account signer = Account.from_key(PK_DEPLOY_WALLET) - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PK_DEPLOY_WALLET, wallet=signer.address, credentials=FAKE_CREDS, diff --git a/tests/unit/test_rewards_transport.py b/tests/unit/test_rewards_transport.py index 0b11f4b..72afee3 100644 --- a/tests/unit/test_rewards_transport.py +++ b/tests/unit/test_rewards_transport.py @@ -65,7 +65,7 @@ def _install_secure_public_clob(client: AsyncSecureClient, handler: httpx.MockTr async def _make_secure_client() -> AsyncSecureClient: - return await AsyncSecureClient._create_for_testing( + return await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_rewards_transport_sync.py b/tests/unit/test_rewards_transport_sync.py index 649aa2e..1441faf 100644 --- a/tests/unit/test_rewards_transport_sync.py +++ b/tests/unit/test_rewards_transport_sync.py @@ -106,7 +106,7 @@ def test_public_passes_sponsored_filter(self) -> None: def test_secure_uses_unsigned_clob_not_secure_clob(self) -> None: captured: list[httpx.Request] = [] - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -143,7 +143,7 @@ def test_public_routes_with_condition_id_in_path(self) -> None: def test_secure_uses_unsigned_clob_not_secure_clob(self) -> None: captured: list[httpx.Request] = [] - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_account_sync.py b/tests/unit/test_secure_account_sync.py index cb18626..7f7c717 100644 --- a/tests/unit/test_secure_account_sync.py +++ b/tests/unit/test_secure_account_sync.py @@ -94,7 +94,7 @@ def _assert_l2_headers(request: httpx.Request) -> None: def _make_client() -> SecureClient: - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_api_keys_sync.py b/tests/unit/test_secure_api_keys_sync.py index 97fa553..b3eb92a 100644 --- a/tests/unit/test_secure_api_keys_sync.py +++ b/tests/unit/test_secure_api_keys_sync.py @@ -34,7 +34,7 @@ def _install_secure_clob(client: SecureClient, handler: httpx.MockTransport) -> def _make_client() -> SecureClient: - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_auth_sync.py b/tests/unit/test_secure_auth_sync.py index c060d05..40c25c9 100644 --- a/tests/unit/test_secure_auth_sync.py +++ b/tests/unit/test_secure_auth_sync.py @@ -26,7 +26,7 @@ def handler(request: httpx.Request) -> httpx.Response: def _make_client() -> SecureClient: - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -107,7 +107,7 @@ def handler(request: httpx.Request) -> httpx.Response: def test_create_with_credentials_skips_auth_flow_when_validation_disabled() -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -147,7 +147,7 @@ def handler(request: httpx.Request) -> httpx.Response: def test_create_rejects_credentials_with_nonzero_nonce() -> None: with pytest.raises(UserInputError, match="nonce cannot be combined"): - SecureClient._create_for_testing( + SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -157,12 +157,12 @@ def test_create_rejects_credentials_with_nonzero_nonce() -> None: def test_create_rejects_negative_nonce() -> None: with pytest.raises(UserInputError, match="non-negative integer"): - SecureClient._create_for_testing(private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=-1) + SecureClient._create(private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=-1) def test_create_rejects_bool_nonce() -> None: with pytest.raises(UserInputError, match="non-negative integer"): - SecureClient._create_for_testing( + SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, nonce=cast(int, True), @@ -170,7 +170,7 @@ def test_create_rejects_bool_nonce() -> None: def test_create_defaults_wallet_to_signer_when_omitted() -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, credentials=FAKE_CREDS, validate_credentials=False, @@ -181,7 +181,7 @@ def test_create_defaults_wallet_to_signer_when_omitted() -> None: def test_create_rejects_invalid_wallet_address() -> None: with pytest.raises(UserInputError, match="Invalid wallet address"): - SecureClient._create_for_testing( + SecureClient._create( private_key=PRIVATE_KEY, wallet="not-an-address", credentials=FAKE_CREDS, @@ -196,7 +196,7 @@ def test_create_classifies_eoa_when_wallet_equals_signer() -> None: def test_create_normalizes_wallet_to_checksum() -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS.lower(), credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_orders_sync.py b/tests/unit/test_secure_orders_sync.py index 37efb5f..c7d7c63 100644 --- a/tests/unit/test_secure_orders_sync.py +++ b/tests/unit/test_secure_orders_sync.py @@ -98,7 +98,7 @@ def _install_secure_clob(client: SecureClient, handler: httpx.MockTransport) -> def _make_client() -> SecureClient: - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_rewards_sync.py b/tests/unit/test_secure_rewards_sync.py index 014dad9..adeb4fa 100644 --- a/tests/unit/test_secure_rewards_sync.py +++ b/tests/unit/test_secure_rewards_sync.py @@ -32,7 +32,7 @@ def _install_secure_clob(client: SecureClient, handler: httpx.MockTransport) -> def _make_client() -> SecureClient: - return SecureClient._create_for_testing( + return SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, diff --git a/tests/unit/test_secure_signer_defaults.py b/tests/unit/test_secure_signer_defaults.py index 2b09ca8..01ff4bc 100644 --- a/tests/unit/test_secure_signer_defaults.py +++ b/tests/unit/test_secure_signer_defaults.py @@ -53,7 +53,7 @@ def _captured() -> list[httpx.Request]: def test_secure_get_portfolio_values_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -68,7 +68,7 @@ def test_secure_get_portfolio_values_defaults_to_signer(captured: list[httpx.Req def test_secure_get_portfolio_values_respects_explicit_user( captured: list[httpx.Request], ) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -86,7 +86,7 @@ def test_secure_get_portfolio_values_respects_explicit_user( def test_secure_get_traded_market_count_defaults_to_signer( captured: list[httpx.Request], ) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -103,7 +103,7 @@ def test_secure_get_traded_market_count_defaults_to_signer( def test_secure_get_traded_market_count_respects_explicit_user( captured: list[httpx.Request], ) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -127,7 +127,7 @@ def handler(request: httpx.Request) -> httpx.Response: captured.append(request) return httpx.Response(200, content=b"PK\x03\x04", request=request) - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -146,7 +146,7 @@ def handler(request: httpx.Request) -> httpx.Response: captured.append(request) return httpx.Response(200, content=b"PK\x03\x04", request=request) - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -162,7 +162,7 @@ def handler(request: httpx.Request) -> httpx.Response: def test_secure_list_positions_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -175,7 +175,7 @@ def test_secure_list_positions_defaults_to_signer(captured: list[httpx.Request]) def test_secure_list_positions_respects_explicit_user(captured: list[httpx.Request]) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -191,7 +191,7 @@ def test_secure_list_positions_respects_explicit_user(captured: list[httpx.Reque def test_secure_list_closed_positions_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -207,7 +207,7 @@ def test_secure_list_closed_positions_defaults_to_signer(captured: list[httpx.Re def test_secure_list_trades_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -223,7 +223,7 @@ def test_secure_list_trades_defaults_to_signer(captured: list[httpx.Request]) -> def test_secure_list_activity_defaults_to_signer(captured: list[httpx.Request]) -> None: - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -242,7 +242,7 @@ def test_async_secure_list_positions_defaults_to_signer() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -262,7 +262,7 @@ def test_async_secure_list_positions_respects_explicit_user() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -286,7 +286,7 @@ def test_async_secure_list_positions_defaults_to_wallet_when_proxy() -> None: captured: list[httpx.Request] = [] async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=proxy_wallet, credentials=FAKE_CREDS, @@ -311,7 +311,7 @@ def handler(request: httpx.Request) -> httpx.Response: return httpx.Response(200, content=b"PK\x03\x04", request=request) async def run() -> None: - client = await AsyncSecureClient._create_for_testing( + client = await AsyncSecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -335,7 +335,7 @@ def test_secure_list_positions_rejects_explicit_empty_user( ) -> None: from polymarket.errors import UserInputError - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, @@ -351,7 +351,7 @@ def test_secure_get_portfolio_values_rejects_explicit_empty_user( ) -> None: from polymarket.errors import UserInputError - with SecureClient._create_for_testing( + with SecureClient._create( private_key=PRIVATE_KEY, wallet=SIGNER_ADDRESS, credentials=FAKE_CREDS, From 9b1b28c0da10963cce987711379840189ff2cd47 Mon Sep 17 00:00:00 2001 From: Cesare Naldi <3353250+cesarenaldi@users.noreply.github.com> Date: Mon, 25 May 2026 12:03:22 +0200 Subject: [PATCH 4/4] docs: complete public client docstrings --- src/polymarket/clients/async_public.py | 88 ++++++++++++++ src/polymarket/clients/async_secure.py | 152 +++++++++++++++++++++++- src/polymarket/clients/public.py | 1 + src/polymarket/clients/secure.py | 153 ++++++++++++++++++++++++- 4 files changed, 392 insertions(+), 2 deletions(-) diff --git a/src/polymarket/clients/async_public.py b/src/polymarket/clients/async_public.py index 63fc155..ab4c770 100644 --- a/src/polymarket/clients/async_public.py +++ b/src/polymarket/clients/async_public.py @@ -138,6 +138,7 @@ def __init__( @property def environment(self) -> Environment: + """Environment this client sends requests to.""" return self._ctx.environment @overload @@ -306,6 +307,7 @@ async def get_market( ) async def get_market_tags(self, id: str) -> tuple[TagReference, ...]: + """Get a market's tags.""" return await async_dispatch(self._ctx, _gamma_actions.get_market_tags_spec(id)) async def get_event( @@ -334,6 +336,7 @@ async def get_event( ) async def get_event_tags(self, id: str) -> tuple[TagReference, ...]: + """Get an event's tags.""" return await async_dispatch(self._ctx, _gamma_actions.get_event_tags_spec(id)) async def get_series( @@ -343,6 +346,7 @@ async def get_series( include_chat: bool | None = None, locale: str | None = None, ) -> Series: + """Get a series.""" return await async_dispatch( self._ctx, _gamma_actions.get_series_spec(id, include_chat=include_chat, locale=locale), @@ -357,6 +361,7 @@ async def get_tag( include_template: bool | None = None, locale: str | None = None, ) -> Tag: + """Get a tag by id or slug.""" return await async_dispatch( self._ctx, _gamma_actions.get_tag_spec( @@ -376,6 +381,7 @@ async def get_related_tags( omit_empty: bool | None = None, status: str | None = None, ) -> tuple[RelatedTag, ...]: + """Get related tag relationships.""" return await async_dispatch( self._ctx, _gamma_actions.get_related_tags_spec( @@ -392,6 +398,7 @@ async def get_related_tag_resources( omit_empty: bool | None = None, status: str | None = None, ) -> tuple[Tag, ...]: + """Get tag resources linked from related tag relationships.""" return await async_dispatch( self._ctx, _gamma_actions.get_related_tag_resources_spec( @@ -400,12 +407,15 @@ async def get_related_tag_resources( ) async def get_sports(self) -> tuple[SportsMetadata, ...]: + """Get available sports metadata.""" return await async_dispatch(self._ctx, _gamma_actions.get_sports_spec()) async def get_sports_market_types(self) -> SportsMarketTypes: + """Get available sports market types.""" return await async_dispatch(self._ctx, _gamma_actions.get_sports_market_types_spec()) async def get_public_profile(self, address: str) -> PublicProfile | None: + """Get a public profile by wallet address. Returns None if no profile exists.""" try: return await async_dispatch(self._ctx, _gamma_actions.get_public_profile_spec(address)) except RequestRejectedError as error: @@ -416,17 +426,20 @@ async def get_public_profile(self, address: str) -> PublicProfile | None: async def get_comment_thread( self, id: str, *, get_positions: bool | None = None ) -> tuple[Comment, ...]: + """Get a comment thread by comment ID.""" return await async_dispatch( self._ctx, _gamma_actions.get_comment_thread_spec(id, get_positions=get_positions), ) async def get_event_live_volumes(self, *, id: str) -> tuple[LiveVolume, ...]: + """Get live volume entries for an event.""" return await async_dispatch(self._ctx, _data_actions.get_event_live_volumes_spec(id=id)) async def get_open_interests( self, *, market: Sequence[str] | None = None ) -> tuple[OpenInterest, ...]: + """Get open interest values, optionally filtered by market ids.""" return await async_dispatch(self._ctx, _data_actions.get_open_interests_spec(market=market)) async def get_market_holders( @@ -436,6 +449,7 @@ async def get_market_holders( limit: int | None = None, min_balance: int | None = None, ) -> tuple[MetaHolder, ...]: + """Get holder balances for one or more markets.""" return await async_dispatch( self._ctx, _data_actions.get_market_holders_spec( @@ -446,11 +460,13 @@ async def get_market_holders( async def get_portfolio_values( self, *, user: str, market: Sequence[str] | None = None ) -> tuple[PortfolioValue, ...]: + """Get portfolio value snapshots for a user.""" return await async_dispatch( self._ctx, _data_actions.get_portfolio_values_spec(user=user, market=market) ) async def get_traded_market_count(self, *, user: str) -> TradedMarketCount: + """Get the number of markets a user has traded.""" return await async_dispatch( self._ctx, _data_actions.get_traded_market_count_spec(user=user) ) @@ -458,6 +474,7 @@ async def get_traded_market_count(self, *, user: str) -> TradedMarketCount: async def get_builder_volumes( self, *, time_period: BuilderVolumeTimePeriod | None = None ) -> tuple[BuilderVolumeEntry, ...]: + """Get builder volume leaderboard entries.""" return await async_dispatch( self._ctx, _data_actions.get_builder_volumes_spec(time_period=time_period) ) @@ -472,6 +489,12 @@ def list_builder_trades( after: str | None = None, before: str | None = None, ) -> AsyncPaginator[BuilderTrade]: + """List builder-attributed trades. + + Returns: + An async paginator over matching builder-attributed trades. + """ + async def fetch(cursor: str | None) -> Page[BuilderTrade]: path, params = _builders_actions.build_list_builder_trades_request( builder_code=builder_code, @@ -501,6 +524,11 @@ def list_positions( title: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Position]: + """List open positions for a user. + + Returns: + An async paginator over matching positions. + """ spec = _data_actions.list_positions_spec( user=user, market=market, @@ -525,6 +553,11 @@ def list_closed_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> AsyncPaginator[ClosedPosition]: + """List closed positions for a user. + + Returns: + An async paginator over matching closed positions. + """ spec = _data_actions.list_closed_positions_spec( user=user, market=market, @@ -545,6 +578,11 @@ def list_market_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> AsyncPaginator[MetaMarketPosition]: + """List positions in a market. + + Returns: + An async paginator over matching market positions. + """ spec = _data_actions.list_market_positions_spec( market=market, user=user, @@ -566,6 +604,11 @@ def list_trades( filter_amount: float | None = None, page_size: int = 20, ) -> AsyncPaginator[Trade]: + """List public trades. + + Returns: + An async paginator over matching trades. + """ spec = _data_actions.list_trades_spec( user=user, market=market, @@ -591,6 +634,11 @@ def list_activity( end: int | None = None, page_size: int = 20, ) -> AsyncPaginator[Activity]: + """List user activity. + + Returns: + An async paginator over matching activity entries. + """ spec = _data_actions.list_activity_spec( user=user, market=market, @@ -610,10 +658,16 @@ def list_builder_leaderboard( time_period: LeaderboardTimePeriod | None = None, page_size: int = 20, ) -> AsyncPaginator[LeaderboardEntry]: + """List builder leaderboard entries. + + Returns: + An async paginator over leaderboard rows. + """ spec = _data_actions.list_builder_leaderboard_spec(time_period=time_period) return async_paginate_offset(self._ctx, spec, page_size=page_size) async def download_accounting_snapshot(self, *, user: str) -> bytes: + """Download the accounting snapshot archive for a user.""" path, params = _data_actions.build_accounting_snapshot_request(user=user) return await self._ctx.data.get_bytes(path, params=params) @@ -627,6 +681,11 @@ def list_trader_leaderboard( user_name: str | None = None, page_size: int = 20, ) -> AsyncPaginator[TraderLeaderboardEntry]: + """List trader leaderboard entries. + + Returns: + An async paginator over leaderboard rows. + """ spec = _data_actions.list_trader_leaderboard_spec( category=category, time_period=time_period, @@ -826,6 +885,11 @@ def list_series( slug: str | Sequence[str] | None = None, page_size: int = 20, ) -> AsyncPaginator[Series]: + """List series. + + Returns: + An async paginator over matching series. + """ spec = _gamma_actions.list_series_spec( ascending=ascending, categories_ids=categories_ids, @@ -851,6 +915,11 @@ def list_tags( order: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Tag]: + """List tags. + + Returns: + An async paginator over matching tags. + """ spec = _gamma_actions.list_tags_spec( ascending=ascending, include_chat=include_chat, @@ -872,6 +941,11 @@ def list_teams( provider_ids: int | Sequence[int] | None = None, page_size: int = 20, ) -> AsyncPaginator[Team]: + """List teams. + + Returns: + An async paginator over matching teams. + """ spec = _gamma_actions.list_teams_spec( abbreviation=abbreviation, ascending=ascending, @@ -893,6 +967,11 @@ def list_comments( order: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Comment]: + """List comments for a market or event. + + Returns: + An async paginator over matching comments. + """ spec = _gamma_actions.list_comments_spec( parent_entity_id=parent_entity_id, parent_entity_type=parent_entity_type, @@ -911,6 +990,11 @@ def list_comments_by_user_address( order: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Comment]: + """List comments authored by a user address. + + Returns: + An async paginator over matching comments. + """ spec = _gamma_actions.list_comments_by_user_address_spec( address=address, ascending=ascending, @@ -991,14 +1075,17 @@ async def get_order_books(self, *, token_ids: Sequence[str]) -> tuple[OrderBook, return _clob_actions.parse_order_books(await self._ctx.clob.post_json(path, json=body)) async def get_spread(self, *, token_id: str) -> Decimal: + """Get the bid-ask spread for a token.""" path, params = _clob_actions.build_spread_request(token_id=token_id) return _clob_actions.parse_spread(await self._ctx.clob.get_json(path, params=params)) async def get_spreads(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get bid-ask spreads for multiple tokens.""" path, body = _clob_actions.build_spreads_request(token_ids=token_ids) return _clob_actions.parse_spreads(await self._ctx.clob.post_json(path, json=body)) async def get_last_trade_price(self, *, token_id: str) -> LastTradePrice: + """Get the most recent trade price for a token.""" path, params = _clob_actions.build_last_trade_price_request(token_id=token_id) return _clob_actions.parse_last_trade_price( await self._ctx.clob.get_json(path, params=params) @@ -1007,6 +1094,7 @@ async def get_last_trade_price(self, *, token_id: str) -> LastTradePrice: async def get_last_trade_prices( self, *, token_ids: Sequence[str] ) -> tuple[LastTradePriceForToken, ...]: + """Get the most recent trade prices for multiple tokens.""" path, body = _clob_actions.build_last_trade_prices_request(token_ids=token_ids) return _clob_actions.parse_last_trade_prices( await self._ctx.clob.post_json(path, json=body) diff --git a/src/polymarket/clients/async_secure.py b/src/polymarket/clients/async_secure.py index eb28429..034f663 100644 --- a/src/polymarket/clients/async_secure.py +++ b/src/polymarket/clients/async_secure.py @@ -268,7 +268,6 @@ async def create( derived during client creation. api_key: Optional key for gasless wallet and relayed transaction workflows. nonce: Credential derivation nonce. Cannot be combined with ``credentials``. - validate_credentials: Whether provided credentials should be validated. Raises: UserInputError: If key material, wallet, nonce, or credentials are invalid. @@ -367,22 +366,27 @@ def _construct_for_wallet( @property def environment(self) -> Environment: + """Environment this client sends requests to.""" return self._ctx.environment @property def wallet(self) -> EvmAddress: + """Wallet address authenticated by this client.""" return self._ctx.wallet @property def signer(self) -> EvmAddress: + """Signer address used for signatures.""" return cast(EvmAddress, self._ctx.signer.address) @property def wallet_type(self) -> WalletType: + """Detected wallet type for the authenticated wallet.""" return self._ctx.wallet_type @property def credentials(self) -> ApiKeyCreds: + """API credentials used for authenticated requests.""" return self._ctx.credentials @overload @@ -533,6 +537,7 @@ async def __aexit__( await self.close() async def close(self) -> None: + """Close the underlying network transports and any open streams.""" ctx = self._ctx_inner try: if self._market_manager is not None: @@ -579,6 +584,7 @@ async def get_market( include_tag: bool | None = None, locale: str | None = None, ) -> Market: + """Get a market by id, slug, or Polymarket URL.""" return await async_dispatch( self._ctx, _gamma_actions.get_market_spec( @@ -587,6 +593,7 @@ async def get_market( ) async def get_market_tags(self, id: str) -> tuple[TagReference, ...]: + """Get a market's tags.""" return await async_dispatch(self._ctx, _gamma_actions.get_market_tags_spec(id)) async def get_event( @@ -600,6 +607,7 @@ async def get_event( include_template: bool | None = None, locale: str | None = None, ) -> Event: + """Get an event by id, slug, or Polymarket URL.""" return await async_dispatch( self._ctx, _gamma_actions.get_event_spec( @@ -614,6 +622,7 @@ async def get_event( ) async def get_event_tags(self, id: str) -> tuple[TagReference, ...]: + """Get an event's tags.""" return await async_dispatch(self._ctx, _gamma_actions.get_event_tags_spec(id)) async def get_series( @@ -623,6 +632,7 @@ async def get_series( include_chat: bool | None = None, locale: str | None = None, ) -> Series: + """Get a series.""" return await async_dispatch( self._ctx, _gamma_actions.get_series_spec(id, include_chat=include_chat, locale=locale), @@ -637,6 +647,7 @@ async def get_tag( include_template: bool | None = None, locale: str | None = None, ) -> Tag: + """Get a tag by id or slug.""" return await async_dispatch( self._ctx, _gamma_actions.get_tag_spec( @@ -656,6 +667,7 @@ async def get_related_tags( omit_empty: bool | None = None, status: str | None = None, ) -> tuple[RelatedTag, ...]: + """Get related tag relationships.""" return await async_dispatch( self._ctx, _gamma_actions.get_related_tags_spec( @@ -672,6 +684,7 @@ async def get_related_tag_resources( omit_empty: bool | None = None, status: str | None = None, ) -> tuple[Tag, ...]: + """Get tag resources linked from related tag relationships.""" return await async_dispatch( self._ctx, _gamma_actions.get_related_tag_resources_spec( @@ -680,12 +693,15 @@ async def get_related_tag_resources( ) async def get_sports(self) -> tuple[SportsMetadata, ...]: + """Get available sports metadata.""" return await async_dispatch(self._ctx, _gamma_actions.get_sports_spec()) async def get_sports_market_types(self) -> SportsMarketTypes: + """Get available sports market types.""" return await async_dispatch(self._ctx, _gamma_actions.get_sports_market_types_spec()) async def get_public_profile(self, address: str) -> PublicProfile | None: + """Get a public profile by wallet address. Returns None if no profile exists.""" try: return await async_dispatch(self._ctx, _gamma_actions.get_public_profile_spec(address)) except RequestRejectedError as error: @@ -696,17 +712,20 @@ async def get_public_profile(self, address: str) -> PublicProfile | None: async def get_comment_thread( self, id: str, *, get_positions: bool | None = None ) -> tuple[Comment, ...]: + """Get a comment thread by comment ID.""" return await async_dispatch( self._ctx, _gamma_actions.get_comment_thread_spec(id, get_positions=get_positions), ) async def get_event_live_volumes(self, *, id: str) -> tuple[LiveVolume, ...]: + """Get live volume entries for an event.""" return await async_dispatch(self._ctx, _data_actions.get_event_live_volumes_spec(id=id)) async def get_open_interests( self, *, market: Sequence[str] | None = None ) -> tuple[OpenInterest, ...]: + """Get open interest values, optionally filtered by market ids.""" return await async_dispatch(self._ctx, _data_actions.get_open_interests_spec(market=market)) async def get_market_holders( @@ -716,6 +735,7 @@ async def get_market_holders( limit: int | None = None, min_balance: int | None = None, ) -> tuple[MetaHolder, ...]: + """Get holder balances for one or more markets.""" return await async_dispatch( self._ctx, _data_actions.get_market_holders_spec( @@ -729,12 +749,14 @@ async def get_portfolio_values( user: str | None = None, market: Sequence[str] | None = None, ) -> tuple[PortfolioValue, ...]: + """Get portfolio value snapshots for a user or the authenticated wallet.""" return await async_dispatch( self._ctx, _data_actions.get_portfolio_values_spec(user=self._user_or_wallet(user), market=market), ) async def get_traded_market_count(self, *, user: str | None = None) -> TradedMarketCount: + """Get the number of markets traded by a user or the authenticated wallet.""" return await async_dispatch( self._ctx, _data_actions.get_traded_market_count_spec(user=self._user_or_wallet(user)), @@ -743,6 +765,7 @@ async def get_traded_market_count(self, *, user: str | None = None) -> TradedMar async def get_builder_volumes( self, *, time_period: BuilderVolumeTimePeriod | None = None ) -> tuple[BuilderVolumeEntry, ...]: + """Get builder volume leaderboard entries.""" return await async_dispatch( self._ctx, _data_actions.get_builder_volumes_spec(time_period=time_period) ) @@ -757,6 +780,12 @@ def list_builder_trades( after: str | None = None, before: str | None = None, ) -> AsyncPaginator[BuilderTrade]: + """List builder-attributed trades. + + Returns: + An async paginator over matching builder-attributed trades. + """ + async def fetch(cursor: str | None) -> Page[BuilderTrade]: path, params = _builders_actions.build_list_builder_trades_request( builder_code=builder_code, @@ -786,6 +815,11 @@ def list_positions( title: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Position]: + """List open positions for a user or the authenticated wallet. + + Returns: + An async paginator over matching positions. + """ spec = _data_actions.list_positions_spec( user=self._user_or_wallet(user), market=market, @@ -810,6 +844,11 @@ def list_closed_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> AsyncPaginator[ClosedPosition]: + """List closed positions for a user or the authenticated wallet. + + Returns: + An async paginator over matching closed positions. + """ spec = _data_actions.list_closed_positions_spec( user=self._user_or_wallet(user), market=market, @@ -830,6 +869,11 @@ def list_market_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> AsyncPaginator[MetaMarketPosition]: + """List positions in a market. + + Returns: + An async paginator over matching market positions. + """ spec = _data_actions.list_market_positions_spec( market=market, user=user, @@ -851,6 +895,11 @@ def list_trades( filter_amount: float | None = None, page_size: int = 20, ) -> AsyncPaginator[Trade]: + """List trades for a user or the authenticated wallet. + + Returns: + An async paginator over matching trades. + """ spec = _data_actions.list_trades_spec( user=self._user_or_wallet(user), market=market, @@ -876,6 +925,11 @@ def list_activity( end: int | None = None, page_size: int = 20, ) -> AsyncPaginator[Activity]: + """List activity for a user or the authenticated wallet. + + Returns: + An async paginator over matching activity entries. + """ spec = _data_actions.list_activity_spec( user=self._user_or_wallet(user), market=market, @@ -895,10 +949,16 @@ def list_builder_leaderboard( time_period: LeaderboardTimePeriod | None = None, page_size: int = 20, ) -> AsyncPaginator[LeaderboardEntry]: + """List builder leaderboard entries. + + Returns: + An async paginator over leaderboard rows. + """ spec = _data_actions.list_builder_leaderboard_spec(time_period=time_period) return async_paginate_offset(self._ctx, spec, page_size=page_size) async def download_accounting_snapshot(self, *, user: str | None = None) -> bytes: + """Download the accounting snapshot archive for a user or the authenticated wallet.""" path, params = _data_actions.build_accounting_snapshot_request( user=self._user_or_wallet(user) ) @@ -914,6 +974,11 @@ def list_trader_leaderboard( user_name: str | None = None, page_size: int = 20, ) -> AsyncPaginator[TraderLeaderboardEntry]: + """List trader leaderboard entries. + + Returns: + An async paginator over leaderboard rows. + """ spec = _data_actions.list_trader_leaderboard_spec( category=category, time_period=time_period, @@ -966,6 +1031,11 @@ def list_events( volume_min: float | None = None, page_size: int = 20, ) -> AsyncPaginator[Event]: + """List events. + + Returns: + An async paginator over matching events. + """ spec = _gamma_actions.list_events_spec( ascending=ascending, closed=closed, @@ -1042,6 +1112,11 @@ def list_markets( volume_num_min: float | None = None, page_size: int = 20, ) -> AsyncPaginator[Market]: + """List markets. + + Returns: + An async paginator over matching markets. + """ spec = _gamma_actions.list_markets_spec( ascending=ascending, closed=closed, @@ -1090,6 +1165,11 @@ def list_series( slug: str | Sequence[str] | None = None, page_size: int = 20, ) -> AsyncPaginator[Series]: + """List series. + + Returns: + An async paginator over matching series. + """ spec = _gamma_actions.list_series_spec( ascending=ascending, categories_ids=categories_ids, @@ -1115,6 +1195,11 @@ def list_tags( order: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Tag]: + """List tags. + + Returns: + An async paginator over matching tags. + """ spec = _gamma_actions.list_tags_spec( ascending=ascending, include_chat=include_chat, @@ -1136,6 +1221,11 @@ def list_teams( provider_ids: int | Sequence[int] | None = None, page_size: int = 20, ) -> AsyncPaginator[Team]: + """List teams. + + Returns: + An async paginator over matching teams. + """ spec = _gamma_actions.list_teams_spec( abbreviation=abbreviation, ascending=ascending, @@ -1157,6 +1247,11 @@ def list_comments( order: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Comment]: + """List comments for a market or event. + + Returns: + An async paginator over matching comments. + """ spec = _gamma_actions.list_comments_spec( parent_entity_id=parent_entity_id, parent_entity_type=parent_entity_type, @@ -1175,6 +1270,11 @@ def list_comments_by_user_address( order: str | None = None, page_size: int = 20, ) -> AsyncPaginator[Comment]: + """List comments authored by a user address. + + Returns: + An async paginator over matching comments. + """ spec = _gamma_actions.list_comments_by_user_address_spec( address=address, ascending=ascending, @@ -1200,6 +1300,11 @@ def search( sort: str | None = None, page_size: int = 10, ) -> AsyncPaginator[SearchResults]: + """Search Polymarket content. + + Returns: + An async paginator over search result pages. + """ spec = _gamma_actions.search_spec( q=q, ascending=ascending, @@ -1218,40 +1323,49 @@ def search( return async_paginate_page_based(self._ctx, spec, page_size=page_size) async def get_midpoint(self, *, token_id: str) -> Decimal: + """Get the midpoint price for a token.""" path, params = _clob_actions.build_midpoint_request(token_id=token_id) return _clob_actions.parse_midpoint(await self._ctx.clob.get_json(path, params=params)) async def get_midpoints(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get midpoint prices for multiple tokens.""" path, body = _clob_actions.build_midpoints_request(token_ids=token_ids) return _clob_actions.parse_midpoints(await self._ctx.clob.post_json(path, json=body)) async def get_price(self, *, token_id: str, side: OrderSide) -> Decimal: + """Get the executable price for a token side.""" path, params = _clob_actions.build_price_request(token_id=token_id, side=side) return _clob_actions.parse_price(await self._ctx.clob.get_json(path, params=params)) async def get_prices( self, *, requests: Sequence[PriceRequest] ) -> dict[str, dict[OrderSide, Decimal]]: + """Get executable prices for multiple token-side requests.""" path, body = _clob_actions.build_prices_request(requests=requests) return _clob_actions.parse_prices(await self._ctx.clob.post_json(path, json=body)) async def get_order_book(self, *, token_id: str) -> OrderBook: + """Get the order book for a token.""" path, params = _clob_actions.build_order_book_request(token_id=token_id) return _clob_actions.parse_order_book(await self._ctx.clob.get_json(path, params=params)) async def get_order_books(self, *, token_ids: Sequence[str]) -> tuple[OrderBook, ...]: + """Get order books for multiple tokens.""" path, body = _clob_actions.build_order_books_request(token_ids=token_ids) return _clob_actions.parse_order_books(await self._ctx.clob.post_json(path, json=body)) async def get_spread(self, *, token_id: str) -> Decimal: + """Get the bid-ask spread for a token.""" path, params = _clob_actions.build_spread_request(token_id=token_id) return _clob_actions.parse_spread(await self._ctx.clob.get_json(path, params=params)) async def get_spreads(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get bid-ask spreads for multiple tokens.""" path, body = _clob_actions.build_spreads_request(token_ids=token_ids) return _clob_actions.parse_spreads(await self._ctx.clob.post_json(path, json=body)) async def get_last_trade_price(self, *, token_id: str) -> LastTradePrice: + """Get the most recent trade price for a token.""" path, params = _clob_actions.build_last_trade_price_request(token_id=token_id) return _clob_actions.parse_last_trade_price( await self._ctx.clob.get_json(path, params=params) @@ -1260,6 +1374,7 @@ async def get_last_trade_price(self, *, token_id: str) -> LastTradePrice: async def get_last_trade_prices( self, *, token_ids: Sequence[str] ) -> tuple[LastTradePriceForToken, ...]: + """Get the most recent trade prices for multiple tokens.""" path, body = _clob_actions.build_last_trade_prices_request(token_ids=token_ids) return _clob_actions.parse_last_trade_prices( await self._ctx.clob.post_json(path, json=body) @@ -1274,6 +1389,7 @@ async def get_price_history( fidelity: int | None = None, interval: PriceHistoryInterval | None = None, ) -> tuple[PriceHistoryPoint, ...]: + """Get historical price points for a token.""" path, params = _clob_actions.build_price_history_request( token_id=token_id, start_ts=start_ts, @@ -1284,12 +1400,15 @@ async def get_price_history( return _clob_actions.parse_price_history(await self._ctx.clob.get_json(path, params=params)) async def fetch_api_keys(self) -> tuple[str, ...]: + """Fetch API key identifiers for the authenticated account.""" return await _auth_actions.fetch_api_keys(self._ctx.secure_clob) async def delete_api_key(self) -> None: + """Delete the API key currently used by this client.""" await _auth_actions.delete_api_key(self._ctx.secure_clob) async def end_authentication(self) -> "AsyncPublicClient": + """Delete current credentials, close this client, and return an async public client.""" environment = self._ctx.environment try: await self.delete_api_key() @@ -1369,6 +1488,7 @@ async def fetch(cursor: str | None) -> Page[ClobTrade]: return AsyncPaginator(fetch=fetch) async def get_notifications(self) -> tuple[Notification, ...]: + """Get notifications for the authenticated account.""" path, params = _account_actions.build_notifications_request( signature_type=signature_type_for(self._ctx.wallet_type) ) @@ -1377,6 +1497,7 @@ async def get_notifications(self) -> tuple[Notification, ...]: ) async def drop_notifications(self, *, ids: Sequence[int | str]) -> None: + """Delete notifications for the authenticated account.""" path, params = _account_actions.build_drop_notifications_request( ids=ids, signature_type=signature_type_for(self._ctx.wallet_type) ) @@ -1608,6 +1729,7 @@ async def place_market_order( return await post_order_with_allowance_recovery(self, signed) async def get_builder_fee_rates(self, builder_code: str) -> BuilderFeeRates: + """Get fee rates for a builder code.""" from polymarket._internal.actions.orders.market_data import fetch_builder_fee_rates return await fetch_builder_fee_rates(self._ctx, builder_code=builder_code) @@ -2055,6 +2177,12 @@ async def _sign_order(self, draft: OrderDraft, *, post_only: bool) -> SignedOrde def list_current_rewards( self, *, sponsored: bool | None = None ) -> AsyncPaginator[CurrentReward]: + """List current rewards. + + Returns: + An async paginator over current reward configurations. + """ + async def fetch(cursor: str | None) -> Page[CurrentReward]: path, params = _rewards_actions.build_list_current_rewards_request( sponsored=sponsored, cursor=cursor @@ -2068,6 +2196,12 @@ async def fetch(cursor: str | None) -> Page[CurrentReward]: def list_market_rewards( self, *, condition_id: str, sponsored: bool | None = None ) -> AsyncPaginator[MarketReward]: + """List rewards for a market condition. + + Returns: + An async paginator over matching market reward configurations. + """ + async def fetch(cursor: str | None) -> Page[MarketReward]: path, params = _rewards_actions.build_list_market_rewards_request( condition_id=ConditionId(condition_id), sponsored=sponsored, cursor=cursor @@ -2079,18 +2213,26 @@ async def fetch(cursor: str | None) -> Page[MarketReward]: return AsyncPaginator(fetch=fetch) async def get_order_scoring(self, *, order_id: str) -> bool: + """Return whether an order is currently scoring rewards.""" path, params = _rewards_actions.build_get_order_scoring_request(order_id=order_id) return _rewards_actions.parse_order_scoring( await self._ctx.secure_clob.get_json(path, params=params) ) async def get_orders_scoring(self, *, order_ids: Sequence[str]) -> dict[str, bool]: + """Return reward-scoring status for multiple orders.""" path, body = _rewards_actions.build_get_orders_scoring_request(order_ids=order_ids) return _rewards_actions.parse_orders_scoring( await self._ctx.secure_clob.post_json(path, json=body) ) def list_user_earnings_for_day(self, *, date: str) -> AsyncPaginator[UserEarning]: + """List reward earnings for the authenticated user on a date. + + Returns: + An async paginator over matching earning entries. + """ + async def fetch(cursor: str | None) -> Page[UserEarning]: path, params = _rewards_actions.build_list_user_earnings_for_day_request( date=date, @@ -2106,6 +2248,7 @@ async def fetch(cursor: str | None) -> Page[UserEarning]: async def get_total_earnings_for_user_for_day( self, *, date: str ) -> tuple[TotalUserEarning, ...]: + """Get total reward earnings for the authenticated user on a date.""" path, params = _rewards_actions.build_total_user_earnings_for_day_request( date=date, signature_type=signature_type_for(self._ctx.wallet_type) ) @@ -2122,6 +2265,12 @@ def list_user_earnings_and_markets_config( position: str | None = None, page_size: int | None = None, ) -> AsyncPaginator[UserRewardsEarning]: + """List reward earnings with market configuration for the authenticated user. + + Returns: + An async paginator over matching reward earning entries. + """ + async def fetch(cursor: str | None) -> Page[UserRewardsEarning]: path, params = _rewards_actions.build_list_user_earnings_and_markets_config_request( date=date, @@ -2139,6 +2288,7 @@ async def fetch(cursor: str | None) -> Page[UserRewardsEarning]: return AsyncPaginator(fetch=fetch) async def get_reward_percentages(self) -> RewardsPercentages: + """Get current reward percentage allocations for the authenticated account.""" path, params = _rewards_actions.build_get_reward_percentages_request( signature_type=signature_type_for(self._ctx.wallet_type) ) diff --git a/src/polymarket/clients/public.py b/src/polymarket/clients/public.py index 0d89856..25afd71 100644 --- a/src/polymarket/clients/public.py +++ b/src/polymarket/clients/public.py @@ -110,6 +110,7 @@ def __init__( @property def environment(self) -> Environment: + """Environment this client sends requests to.""" return self._ctx.environment def __enter__(self) -> Self: diff --git a/src/polymarket/clients/secure.py b/src/polymarket/clients/secure.py index ff9113d..ec7c7c0 100644 --- a/src/polymarket/clients/secure.py +++ b/src/polymarket/clients/secure.py @@ -242,7 +242,6 @@ def create( derived during client creation. api_key: Optional key for gasless wallet and relayed transaction workflows. nonce: Credential derivation nonce. Cannot be combined with ``credentials``. - validate_credentials: Whether provided credentials should be validated. Raises: UserInputError: If key material, wallet, nonce, or credentials are invalid. @@ -349,22 +348,27 @@ def _construct_for_wallet( @property def environment(self) -> Environment: + """Environment this client sends requests to.""" return self._ctx.environment @property def wallet(self) -> EvmAddress: + """Wallet address authenticated by this client.""" return self._ctx.wallet @property def signer(self) -> EvmAddress: + """Signer address used for signatures.""" return cast(EvmAddress, self._ctx.signer.address) @property def wallet_type(self) -> WalletType: + """Detected wallet type for the authenticated wallet.""" return self._ctx.wallet_type @property def credentials(self) -> ApiKeyCreds: + """API credentials used for authenticated requests.""" return self._ctx.credentials def __enter__(self) -> Self: @@ -410,6 +414,7 @@ def get_market( include_tag: bool | None = None, locale: str | None = None, ) -> Market: + """Get a market by id, slug, or Polymarket URL.""" return sync_dispatch( self._ctx, _gamma_actions.get_market_spec( @@ -418,6 +423,7 @@ def get_market( ) def get_market_tags(self, id: str) -> tuple[TagReference, ...]: + """Get a market's tags.""" return sync_dispatch(self._ctx, _gamma_actions.get_market_tags_spec(id)) def get_event( @@ -431,6 +437,7 @@ def get_event( include_template: bool | None = None, locale: str | None = None, ) -> Event: + """Get an event by id, slug, or Polymarket URL.""" return sync_dispatch( self._ctx, _gamma_actions.get_event_spec( @@ -445,6 +452,7 @@ def get_event( ) def get_event_tags(self, id: str) -> tuple[TagReference, ...]: + """Get an event's tags.""" return sync_dispatch(self._ctx, _gamma_actions.get_event_tags_spec(id)) def get_series( @@ -454,6 +462,7 @@ def get_series( include_chat: bool | None = None, locale: str | None = None, ) -> Series: + """Get a series.""" return sync_dispatch( self._ctx, _gamma_actions.get_series_spec(id, include_chat=include_chat, locale=locale), @@ -468,6 +477,7 @@ def get_tag( include_template: bool | None = None, locale: str | None = None, ) -> Tag: + """Get a tag by id or slug.""" return sync_dispatch( self._ctx, _gamma_actions.get_tag_spec( @@ -487,6 +497,7 @@ def get_related_tags( omit_empty: bool | None = None, status: str | None = None, ) -> tuple[RelatedTag, ...]: + """Get related tag relationships.""" return sync_dispatch( self._ctx, _gamma_actions.get_related_tags_spec( @@ -503,6 +514,7 @@ def get_related_tag_resources( omit_empty: bool | None = None, status: str | None = None, ) -> tuple[Tag, ...]: + """Get tag resources linked from related tag relationships.""" return sync_dispatch( self._ctx, _gamma_actions.get_related_tag_resources_spec( @@ -511,12 +523,15 @@ def get_related_tag_resources( ) def get_sports(self) -> tuple[SportsMetadata, ...]: + """Get available sports metadata.""" return sync_dispatch(self._ctx, _gamma_actions.get_sports_spec()) def get_sports_market_types(self) -> SportsMarketTypes: + """Get available sports market types.""" return sync_dispatch(self._ctx, _gamma_actions.get_sports_market_types_spec()) def get_public_profile(self, address: str) -> PublicProfile | None: + """Get a public profile by wallet address. Returns None if no profile exists.""" try: return sync_dispatch(self._ctx, _gamma_actions.get_public_profile_spec(address)) except RequestRejectedError as error: @@ -527,17 +542,20 @@ def get_public_profile(self, address: str) -> PublicProfile | None: def get_comment_thread( self, id: str, *, get_positions: bool | None = None ) -> tuple[Comment, ...]: + """Get a comment thread by comment ID.""" return sync_dispatch( self._ctx, _gamma_actions.get_comment_thread_spec(id, get_positions=get_positions), ) def get_event_live_volumes(self, *, id: str) -> tuple[LiveVolume, ...]: + """Get live volume entries for an event.""" return sync_dispatch(self._ctx, _data_actions.get_event_live_volumes_spec(id=id)) def get_open_interests( self, *, market: Sequence[str] | None = None ) -> tuple[OpenInterest, ...]: + """Get open interest values, optionally filtered by market ids.""" return sync_dispatch(self._ctx, _data_actions.get_open_interests_spec(market=market)) def get_market_holders( @@ -547,6 +565,7 @@ def get_market_holders( limit: int | None = None, min_balance: int | None = None, ) -> tuple[MetaHolder, ...]: + """Get holder balances for one or more markets.""" return sync_dispatch( self._ctx, _data_actions.get_market_holders_spec( @@ -560,12 +579,14 @@ def get_portfolio_values( user: str | None = None, market: Sequence[str] | None = None, ) -> tuple[PortfolioValue, ...]: + """Get portfolio value snapshots for a user or the authenticated wallet.""" return sync_dispatch( self._ctx, _data_actions.get_portfolio_values_spec(user=self._user_or_wallet(user), market=market), ) def get_traded_market_count(self, *, user: str | None = None) -> TradedMarketCount: + """Get the number of markets traded by a user or the authenticated wallet.""" return sync_dispatch( self._ctx, _data_actions.get_traded_market_count_spec(user=self._user_or_wallet(user)), @@ -574,6 +595,7 @@ def get_traded_market_count(self, *, user: str | None = None) -> TradedMarketCou def get_builder_volumes( self, *, time_period: BuilderVolumeTimePeriod | None = None ) -> tuple[BuilderVolumeEntry, ...]: + """Get builder volume leaderboard entries.""" return sync_dispatch( self._ctx, _data_actions.get_builder_volumes_spec(time_period=time_period) ) @@ -588,6 +610,12 @@ def list_builder_trades( after: str | None = None, before: str | None = None, ) -> Paginator[BuilderTrade]: + """List builder-attributed trades. + + Returns: + A paginator over matching builder-attributed trades. + """ + def fetch(cursor: str | None) -> Page[BuilderTrade]: path, params = _builders_actions.build_list_builder_trades_request( builder_code=builder_code, @@ -617,6 +645,11 @@ def list_positions( title: str | None = None, page_size: int = 20, ) -> Paginator[Position]: + """List open positions for a user or the authenticated wallet. + + Returns: + A paginator over matching positions. + """ spec = _data_actions.list_positions_spec( user=self._user_or_wallet(user), market=market, @@ -641,6 +674,11 @@ def list_closed_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> Paginator[ClosedPosition]: + """List closed positions for a user or the authenticated wallet. + + Returns: + A paginator over matching closed positions. + """ spec = _data_actions.list_closed_positions_spec( user=self._user_or_wallet(user), market=market, @@ -661,6 +699,11 @@ def list_market_positions( sort_direction: SortDirection | None = None, page_size: int = 20, ) -> Paginator[MetaMarketPosition]: + """List positions in a market. + + Returns: + A paginator over matching market positions. + """ spec = _data_actions.list_market_positions_spec( market=market, user=user, @@ -682,6 +725,11 @@ def list_trades( filter_amount: float | None = None, page_size: int = 20, ) -> Paginator[Trade]: + """List trades for a user or the authenticated wallet. + + Returns: + A paginator over matching trades. + """ spec = _data_actions.list_trades_spec( user=self._user_or_wallet(user), market=market, @@ -707,6 +755,11 @@ def list_activity( end: int | None = None, page_size: int = 20, ) -> Paginator[Activity]: + """List activity for a user or the authenticated wallet. + + Returns: + A paginator over matching activity entries. + """ spec = _data_actions.list_activity_spec( user=self._user_or_wallet(user), market=market, @@ -726,10 +779,16 @@ def list_builder_leaderboard( time_period: LeaderboardTimePeriod | None = None, page_size: int = 20, ) -> Paginator[LeaderboardEntry]: + """List builder leaderboard entries. + + Returns: + A paginator over leaderboard rows. + """ spec = _data_actions.list_builder_leaderboard_spec(time_period=time_period) return sync_paginate_offset(self._ctx, spec, page_size=page_size) def download_accounting_snapshot(self, *, user: str | None = None) -> bytes: + """Download the accounting snapshot archive for a user or the authenticated wallet.""" path, params = _data_actions.build_accounting_snapshot_request( user=self._user_or_wallet(user) ) @@ -745,6 +804,11 @@ def list_trader_leaderboard( user_name: str | None = None, page_size: int = 20, ) -> Paginator[TraderLeaderboardEntry]: + """List trader leaderboard entries. + + Returns: + A paginator over leaderboard rows. + """ spec = _data_actions.list_trader_leaderboard_spec( category=category, time_period=time_period, @@ -797,6 +861,11 @@ def list_events( volume_min: float | None = None, page_size: int = 20, ) -> Paginator[Event]: + """List events. + + Returns: + A paginator over matching events. + """ spec = _gamma_actions.list_events_spec( ascending=ascending, closed=closed, @@ -873,6 +942,11 @@ def list_markets( volume_num_min: float | None = None, page_size: int = 20, ) -> Paginator[Market]: + """List markets. + + Returns: + A paginator over matching markets. + """ spec = _gamma_actions.list_markets_spec( ascending=ascending, closed=closed, @@ -921,6 +995,11 @@ def list_series( slug: str | Sequence[str] | None = None, page_size: int = 20, ) -> Paginator[Series]: + """List series. + + Returns: + A paginator over matching series. + """ spec = _gamma_actions.list_series_spec( ascending=ascending, categories_ids=categories_ids, @@ -946,6 +1025,11 @@ def list_tags( order: str | None = None, page_size: int = 20, ) -> Paginator[Tag]: + """List tags. + + Returns: + A paginator over matching tags. + """ spec = _gamma_actions.list_tags_spec( ascending=ascending, include_chat=include_chat, @@ -967,6 +1051,11 @@ def list_teams( provider_ids: int | Sequence[int] | None = None, page_size: int = 20, ) -> Paginator[Team]: + """List teams. + + Returns: + A paginator over matching teams. + """ spec = _gamma_actions.list_teams_spec( abbreviation=abbreviation, ascending=ascending, @@ -988,6 +1077,11 @@ def list_comments( order: str | None = None, page_size: int = 20, ) -> Paginator[Comment]: + """List comments for a market or event. + + Returns: + A paginator over matching comments. + """ spec = _gamma_actions.list_comments_spec( parent_entity_id=parent_entity_id, parent_entity_type=parent_entity_type, @@ -1006,6 +1100,11 @@ def list_comments_by_user_address( order: str | None = None, page_size: int = 20, ) -> Paginator[Comment]: + """List comments authored by a user address. + + Returns: + A paginator over matching comments. + """ spec = _gamma_actions.list_comments_by_user_address_spec( address=address, ascending=ascending, @@ -1031,6 +1130,11 @@ def search( sort: str | None = None, page_size: int = 10, ) -> Paginator[SearchResults]: + """Search Polymarket content. + + Returns: + A paginator over search result pages. + """ spec = _gamma_actions.search_spec( q=q, ascending=ascending, @@ -1049,46 +1153,56 @@ def search( return sync_paginate_page_based(self._ctx, spec, page_size=page_size) def get_midpoint(self, *, token_id: str) -> Decimal: + """Get the midpoint price for a token.""" path, params = _clob_actions.build_midpoint_request(token_id=token_id) return _clob_actions.parse_midpoint(self._ctx.clob.get_json(path, params=params)) def get_midpoints(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get midpoint prices for multiple tokens.""" path, body = _clob_actions.build_midpoints_request(token_ids=token_ids) return _clob_actions.parse_midpoints(self._ctx.clob.post_json(path, json=body)) def get_price(self, *, token_id: str, side: OrderSide) -> Decimal: + """Get the executable price for a token side.""" path, params = _clob_actions.build_price_request(token_id=token_id, side=side) return _clob_actions.parse_price(self._ctx.clob.get_json(path, params=params)) def get_prices( self, *, requests: Sequence[PriceRequest] ) -> dict[str, dict[OrderSide, Decimal]]: + """Get executable prices for multiple token-side requests.""" path, body = _clob_actions.build_prices_request(requests=requests) return _clob_actions.parse_prices(self._ctx.clob.post_json(path, json=body)) def get_order_book(self, *, token_id: str) -> OrderBook: + """Get the order book for a token.""" path, params = _clob_actions.build_order_book_request(token_id=token_id) return _clob_actions.parse_order_book(self._ctx.clob.get_json(path, params=params)) def get_order_books(self, *, token_ids: Sequence[str]) -> tuple[OrderBook, ...]: + """Get order books for multiple tokens.""" path, body = _clob_actions.build_order_books_request(token_ids=token_ids) return _clob_actions.parse_order_books(self._ctx.clob.post_json(path, json=body)) def get_spread(self, *, token_id: str) -> Decimal: + """Get the bid-ask spread for a token.""" path, params = _clob_actions.build_spread_request(token_id=token_id) return _clob_actions.parse_spread(self._ctx.clob.get_json(path, params=params)) def get_spreads(self, *, token_ids: Sequence[str]) -> dict[str, Decimal]: + """Get bid-ask spreads for multiple tokens.""" path, body = _clob_actions.build_spreads_request(token_ids=token_ids) return _clob_actions.parse_spreads(self._ctx.clob.post_json(path, json=body)) def get_last_trade_price(self, *, token_id: str) -> LastTradePrice: + """Get the most recent trade price for a token.""" path, params = _clob_actions.build_last_trade_price_request(token_id=token_id) return _clob_actions.parse_last_trade_price(self._ctx.clob.get_json(path, params=params)) def get_last_trade_prices( self, *, token_ids: Sequence[str] ) -> tuple[LastTradePriceForToken, ...]: + """Get the most recent trade prices for multiple tokens.""" path, body = _clob_actions.build_last_trade_prices_request(token_ids=token_ids) return _clob_actions.parse_last_trade_prices(self._ctx.clob.post_json(path, json=body)) @@ -1101,6 +1215,7 @@ def get_price_history( fidelity: int | None = None, interval: PriceHistoryInterval | None = None, ) -> tuple[PriceHistoryPoint, ...]: + """Get historical price points for a token.""" path, params = _clob_actions.build_price_history_request( token_id=token_id, start_ts=start_ts, @@ -1137,6 +1252,11 @@ def estimate_market_price( shares: Decimal | int | float | str | None = None, order_type: MarketOrderType = "FOK", ) -> Decimal: + """Estimate the average execution price for a market order. + + BUY orders use ``amount`` as the spend amount. SELL orders use ``shares`` + as the number of shares to sell. + """ return _estimate_market_price_sync( self._ctx, token_id=token_id, @@ -1147,6 +1267,12 @@ def estimate_market_price( ) def list_current_rewards(self, *, sponsored: bool | None = None) -> Paginator[CurrentReward]: + """List current rewards. + + Returns: + A paginator over current reward configurations. + """ + def fetch(cursor: str | None) -> Page[CurrentReward]: path, params = _rewards_actions.build_list_current_rewards_request( sponsored=sponsored, cursor=cursor @@ -1160,6 +1286,12 @@ def fetch(cursor: str | None) -> Page[CurrentReward]: def list_market_rewards( self, *, condition_id: str, sponsored: bool | None = None ) -> Paginator[MarketReward]: + """List rewards for a market condition. + + Returns: + A paginator over matching market reward configurations. + """ + def fetch(cursor: str | None) -> Page[MarketReward]: path, params = _rewards_actions.build_list_market_rewards_request( condition_id=ConditionId(condition_id), sponsored=sponsored, cursor=cursor @@ -1171,12 +1303,15 @@ def fetch(cursor: str | None) -> Page[MarketReward]: return Paginator(fetch=fetch) def fetch_api_keys(self) -> tuple[str, ...]: + """Fetch API key identifiers for the authenticated account.""" return _auth_actions.fetch_api_keys_sync(self._ctx.secure_clob) def delete_api_key(self) -> None: + """Delete the API key currently used by this client.""" _auth_actions.delete_api_key_sync(self._ctx.secure_clob) def end_authentication(self) -> "PublicClient": + """Delete current credentials, close this client, and return a public client.""" from polymarket.clients.public import PublicClient environment = self._ctx.environment @@ -1572,18 +1707,26 @@ def _sign_order(self, draft: OrderDraft, *, post_only: bool) -> SignedOrder: return create_signed_order(unsigned, final_signature, post_only=post_only) def get_order_scoring(self, *, order_id: str) -> bool: + """Return whether an order is currently scoring rewards.""" path, params = _rewards_actions.build_get_order_scoring_request(order_id=order_id) return _rewards_actions.parse_order_scoring( self._ctx.secure_clob.get_json(path, params=params) ) def get_orders_scoring(self, *, order_ids: Sequence[str]) -> dict[str, bool]: + """Return reward-scoring status for multiple orders.""" path, body = _rewards_actions.build_get_orders_scoring_request(order_ids=order_ids) return _rewards_actions.parse_orders_scoring( self._ctx.secure_clob.post_json(path, json=body) ) def list_user_earnings_for_day(self, *, date: str) -> Paginator[UserEarning]: + """List reward earnings for the authenticated user on a date. + + Returns: + A paginator over matching earning entries. + """ + def fetch(cursor: str | None) -> Page[UserEarning]: path, params = _rewards_actions.build_list_user_earnings_for_day_request( date=date, @@ -1597,6 +1740,7 @@ def fetch(cursor: str | None) -> Page[UserEarning]: return Paginator(fetch=fetch) def get_total_earnings_for_user_for_day(self, *, date: str) -> tuple[TotalUserEarning, ...]: + """Get total reward earnings for the authenticated user on a date.""" path, params = _rewards_actions.build_total_user_earnings_for_day_request( date=date, signature_type=signature_type_for(self._ctx.wallet_type) ) @@ -1613,6 +1757,12 @@ def list_user_earnings_and_markets_config( position: str | None = None, page_size: int | None = None, ) -> Paginator[UserRewardsEarning]: + """List reward earnings with market configuration for the authenticated user. + + Returns: + A paginator over matching reward earning entries. + """ + def fetch(cursor: str | None) -> Page[UserRewardsEarning]: path, params = _rewards_actions.build_list_user_earnings_and_markets_config_request( date=date, @@ -1630,6 +1780,7 @@ def fetch(cursor: str | None) -> Page[UserRewardsEarning]: return Paginator(fetch=fetch) def get_reward_percentages(self) -> RewardsPercentages: + """Get current reward percentage allocations for the authenticated account.""" path, params = _rewards_actions.build_get_reward_percentages_request( signature_type=signature_type_for(self._ctx.wallet_type) )