diff --git a/README.md b/README.md index 43c72f2d..dcdd11c7 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Before using the SDK, ensure you have: - [binance-sdk-sub-account](./clients/sub_account/) - Sub Account connector (Pypi package: [`binance-sdk-sub-account`](https://pypi.org/project/binance-sdk-sub-account/)) - [binance-sdk-vip-loan](./clients/vip_loan/) - VIP Loan connector (Pypi package: [`binance-sdk-vip-loan`](https://pypi.org/project/binance-sdk-vip-loan/)) - [binance-sdk-wallet](./clients/wallet/) - Wallet connector (Pypi package: [`binance-sdk-wallet`](https://pypi.org/project/binance-sdk-wallet/)) +- [binance-sdk-w3w-prediction](./clients/w3w_prediction/) - W3W Prediction connector (Pypi package: [`binance-sdk-w3w-prediction`](https://pypi.org/project/binance-sdk-wallet/)) ## Documentation diff --git a/clients/derivatives_trading_coin_futures/CHANGELOG.md b/clients/derivatives_trading_coin_futures/CHANGELOG.md index b150de1f..40f86ec4 100644 --- a/clients/derivatives_trading_coin_futures/CHANGELOG.md +++ b/clients/derivatives_trading_coin_futures/CHANGELOG.md @@ -1,5 +1,53 @@ # Changelog +## 6.0.0 - 2026-06-29 + +### Changed (13) + +#### WebSocket Streams + +- Modified response for `all_book_tickers_stream()` (`!bookTicker` stream): + - property `st` added + +- Modified response for `contract_info_stream()` (`!contractInfo` stream): + - property `st` added + +- Modified response for `all_market_liquidation_order_streams()` (`!forceOrder@arr` stream): + - property `st` added + +- Modified response for `all_market_mini_tickers_stream()` (`!miniTicker@arr` stream): + - items: property `st` added + - items: item property `st` added + +- Modified response for `all_market_tickers_streams()` (`!ticker@arr` stream): + - items: property `st` added + - items: item property `st` added + +- Modified response for `aggregate_trade_streams()` (`@aggTrade` stream): + - property `st` added + +- Modified response for `individual_symbol_book_ticker_streams()` (`@bookTicker` stream): + - property `st` added + +- Modified response for `partial_book_depth_streams()` (`@depth@` stream): + - property `st` added + +- Modified response for `diff_book_depth_streams()` (`@depth@` stream): + - property `st` added + +- Modified response for `mark_price_stream()` (`@markPrice@` stream): + - property `st` added + +- Modified response for `individual_symbol_mini_ticker_stream()` (`@miniTicker` stream): + - property `st` added + +- Modified response for `individual_symbol_ticker_streams()` (`@ticker` stream): + - property `st` added + +- Modified response for `mark_price_of_all_symbols_of_a_pair()` (`@markPrice@` stream): + - items: property `st` added + - items: item property `st` added + ## 5.7.0 - 2026-06-09 ### Changed (2) diff --git a/clients/derivatives_trading_coin_futures/pyproject.toml b/clients/derivatives_trading_coin_futures/pyproject.toml index 1c4a33f0..aa2d10cf 100644 --- a/clients/derivatives_trading_coin_futures/pyproject.toml +++ b/clients/derivatives_trading_coin_futures/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "binance-sdk-derivatives-trading-coin-futures" -version = "5.7.0" +version = "6.0.0" description = "Official Binance Derivatives Trading Coin Futures SDK - A lightweight library that provides a convenient interface to Binance's DerivativesTradingCoinFutures REST API, WebSocket API and WebSocket Streams." authors = ["Binance"] license = "MIT" diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/account_api.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/account_api.py index 23f1c254..24d27fe5 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/account_api.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/account_api.py @@ -180,10 +180,11 @@ def get_download_id_for_futures_order_history( Get Download Id For Futures Order History - * Request Limitation is 10 times per month, shared by front end download page and rest api + * Request Limitation is 8 times per month, shared by front end download page and rest api + * This endpoint uses the IP rate limit bucket and costs 1000 weight per call. The maximum is 2 calls per minute; the 3rd call within the same minute will trigger a ban. * The time between `startTime` and `endTime` can not be longer than 1 year - Weight: 5 + Weight: 1000 Args: start_time (Union[int, None]): Timestamp in ms @@ -241,10 +242,11 @@ def get_download_id_for_futures_trade_history( Get download id for futures trade history - * Request Limitation is 5 times per month, shared by front end download page and rest api + * Request Limitation is 8 times per month, shared by front end download page and rest api + * This endpoint uses the IP rate limit bucket and costs 1000 weight per call. The maximum is 2 calls per minute; the 3rd call within the same minute will trigger a ban. * The time between `startTime` and `endTime` can not be longer than 1 year - Weight: 5 + Weight: 1000 Args: start_time (Union[int, None]): Timestamp in ms @@ -302,10 +304,11 @@ def get_download_id_for_futures_transaction_history( Get download id for futures transaction history - * Request Limitation is 5 times per month, shared by front end download page and rest api + * Request Limitation is 8 times per month, shared by front end download page and rest api + * This endpoint uses the IP rate limit bucket and costs 1000 weight per call. The maximum is 2 calls per minute; the 3rd call within the same minute will trigger a ban. * The time between `startTime` and `endTime` can not be longer than 1 year - Weight: 5 + Weight: 1000 Args: start_time (Union[int, None]): Timestamp in ms @@ -362,7 +365,7 @@ def get_futures_order_history_download_link_by_id( Get futures order history download link by Id - * Download link expiration: 24h + * Download link expiration: 7 days Weight: 5 @@ -412,7 +415,7 @@ def get_futures_trade_download_link_by_id( Get futures trade download link by Id - * Download link expiration: 24h + * Download link expiration: 7 days Weight: 5 @@ -462,7 +465,7 @@ def get_futures_transaction_history_download_link_by_id( Get futures transaction history download link by Id - * Download link expiration: 24h + * Download link expiration: 7 days Weight: 5 @@ -620,7 +623,7 @@ def notional_bracket_for_symbol( Get the symbol's notional bracket list. - Weight: 1 + Weight: 1 (after CM migration: 1 with symbol / 2 without symbol) Args: symbol (Optional[str] = None): diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/market_data_api.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/market_data_api.py index 5cb6776d..b1499718 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/market_data_api.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/market_data_api.py @@ -197,7 +197,7 @@ def compressed_aggregate_trades_list( Get compressed, aggregate trades. Market trades that fill in 100ms with the same price and the same taking side will have the quantity aggregated. - * support querying futures trade histories that are not older than one year + * support querying futures trade histories that are not older than 24 hours * If both `startTime` and `endTime` are sent, time between `startTime` and `endTime` must be less than 1 hour. * If `fromId`, `startTime`, and `endTime` are not sent, the most recent aggregate trades will be returned. * Only market trades will be aggregated and returned, which means the insurance fund trades and ADL trades won't be aggregated. @@ -269,7 +269,6 @@ def continuous_contract_kline_candlestick_data( * CURRENT_QUARTER * NEXT_QUARTER - 1000 | 10 * The difference between `startTime` and `endTime` can only be up to 200 days * Between `startTime` and `endTime`, the most recent `limit` data from `endTime` will be returned: @@ -519,7 +518,6 @@ def index_price_kline_candlestick_data( Kline/candlestick bars for the index price of a pair. Klines are uniquely identified by their open time. - 1000 | 10 * The difference between `startTime` and `endTime` can only be up to 200 days * Between `startTime` and `endTime`, the most recent `limit` data from `endTime` will be returned: @@ -734,7 +732,6 @@ def mark_price_kline_candlestick_data( Kline/candlestick bars for the mark price of a symbol. Klines are uniquely identified by their open time. - 1000 | 10 * The difference between `startTime` and `endTime` can only be up to 200 days * Between `startTime` and `endTime`, the most recent `limit` data from `endTime` will be returned: @@ -808,6 +805,7 @@ def old_trades_lookup( Get older market historical trades. * Market trades means trades filled in the order book. Only market trades will be returned, which means the insurance fund trades and ADL trades won't be returned. + * Only supports data from within the last one month Weight: 20 diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/trade_api.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/trade_api.py index 95012744..23b00cb2 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/trade_api.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/api/trade_api.py @@ -101,7 +101,7 @@ def account_trade_list( * If startTime and endTime are both not sent, then the last 7 days' data will be returned. * The time between startTime and endTime cannot be longer than 7 days. - Weight: 20 with symbol,40 with pair + Weight: 20 with symbol,40 with pair (after CM migration: 5 flat) Args: symbol (Optional[str] = None): @@ -174,7 +174,7 @@ def all_orders( * If orderId is set, it will get orders >= that orderId. Otherwise most recent orders are returned. * The query time period must be less then 7 days( default as the recent 7 days). - Weight: 20 with symbol, 40 with pair + Weight: 20 with symbol, 40 with pair (after CM migration: 5 flat) Args: symbol (Optional[str] = None): @@ -399,7 +399,6 @@ def cancel_order( Cancel an active order. - * Either `orderId` or `origClientOrderId` must be sent. Weight: 1 @@ -567,7 +566,11 @@ def change_position_mode( POST /dapi/v1/positionSide/dual https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/rest-api/Change-Position-Mode - Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol*** + Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol***. + + **After CM migration**, UM and CM share the **same** `dualSidePosition` setting. Calling this endpoint flips both UM and CM at once. If either side has any open order or open position, the change is rejected: + - `-4067` (open orders exist) + - `-4068` (open position exists) Weight: 1 @@ -802,7 +805,7 @@ def modify_isolated_position_margin( Args: symbol (Union[str, None]): amount (Union[float, None]): - type (Union[ModifyIsolatedPositionMarginTypeEnum, None]): + type (Union[ModifyIsolatedPositionMarginTypeEnum, None]): **After CM migration, stop-type values (`STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`) are no longer accepted by this endpoint and will return `-4120`. Use the new `/dapi/v1/algoOrder` endpoint instead.** position_side (Optional[ModifyIsolatedPositionMarginPositionSideEnum] = None): Default `BOTH` for One-way Mode ; `LONG` or `SHORT` for Hedge Mode. It must be sent with Hedge Mode. recv_window (Optional[int] = None): @@ -921,7 +924,7 @@ def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. - * Either `quantity` or `price` must be sent. + * Either `quantity` or `price` must be sent. *(After CM migration, both `quantity` and `price` are required.)* * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. * However the order will be cancelled by the amendment in the following situations: * when the order is in partially filled status and the new `quantity` <= `executedQty` @@ -1013,7 +1016,6 @@ def new_order( Send in a new order. - * Order with type `STOP`, parameter `timeInForce` can be sent ( default `GTC`). * Order with type `TAKE_PROFIT`, parameter `timeInForce` can be sent ( default `GTC`). * Condition orders will be triggered when: @@ -1056,7 +1058,7 @@ def new_order( Args: symbol (Union[str, None]): side (Union[NewOrderSideEnum, None]): `SELL`, `BUY` - type (Union[NewOrderTypeEnum, None]): + type (Union[NewOrderTypeEnum, None]): **After CM migration, stop-type values (`STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`) are no longer accepted by this endpoint and will return `-4120`. Use the new `/dapi/v1/algoOrder` endpoint instead.** position_side (Optional[NewOrderPositionSideEnum] = None): Default `BOTH` for One-way Mode ; `LONG` or `SHORT` for Hedge Mode. It must be sent with Hedge Mode. time_in_force (Optional[NewOrderTimeInForceEnum] = None): quantity (Optional[float] = None): quantity measured by contract number, Cannot be sent with `closePosition`=`true` @@ -1068,7 +1070,7 @@ def new_order( activation_price (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, default as the latest price(supporting different `workingType`) callback_rate (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, min 0.1, max 10 where 1 for 1% working_type (Optional[NewOrderWorkingTypeEnum] = None): stopPrice triggered by: "MARK_PRICE", "CONTRACT_PRICE". Default "CONTRACT_PRICE" - price_protect (Optional[str] = None): "TRUE" or "FALSE", default "FALSE". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. + price_protect (Optional[str] = None): "true" or "false", default "false". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. new_order_resp_type (Optional[NewOrderNewOrderRespTypeEnum] = None): "ACK", "RESULT", default "ACK" price_match (Optional[NewOrderPriceMatchEnum] = None): only avaliable for `LIMIT`/`STOP`/`TAKE_PROFIT` order; can be set to `OPPONENT`/ `OPPONENT_5`/ `OPPONENT_10`/ `OPPONENT_20`: /`QUEUE`/ `QUEUE_5`/ `QUEUE_10`/ `QUEUE_20`; Can't be passed together with `price` self_trade_prevention_mode (Optional[NewOrderSelfTradePreventionModeEnum] = None): `EXPIRE_TAKER`:expire taker order when STP triggers/ `EXPIRE_MAKER`:expire taker order when STP triggers/ `EXPIRE_BOTH`:expire both orders when STP triggers; default `EXPIRE_MAKER` @@ -1424,9 +1426,9 @@ def users_force_orders( User's Force Orders * If "autoCloseType" is not sent, orders with both of the types will be returned - * If "startTime" is not sent, data within 200 days before "endTime" can be queried + * Only support querying data in the past 90 days - Weight: 20 with symbol, 50 without symbol + Weight: 20 (after CM migration: 20 with symbol / 50 without symbol) Args: symbol (Optional[str] = None): diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/__init__.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/__init__.py index 4f2711b1..e87a48ab 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/__init__.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/__init__.py @@ -160,9 +160,6 @@ from .kline_candlestick_data_response import ( KlineCandlestickDataResponse as KlineCandlestickDataResponse, ) -from .kline_candlestick_data_response_item import ( - KlineCandlestickDataResponseItem as KlineCandlestickDataResponseItem, -) from .long_short_ratio_response import LongShortRatioResponse as LongShortRatioResponse from .long_short_ratio_response_inner import ( LongShortRatioResponseInner as LongShortRatioResponseInner, diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/kline_candlestick_data_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/kline_candlestick_data_response.py index 47653999..87a6aa7e 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/kline_candlestick_data_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/kline_candlestick_data_response.py @@ -16,16 +16,13 @@ import re # noqa: F401 import json -from pydantic import ConfigDict +from pydantic import BaseModel, ConfigDict from typing import Any, ClassVar, Dict -from binance_sdk_derivatives_trading_coin_futures.rest_api.models.kline_candlestick_data_response_item import ( - KlineCandlestickDataResponseItem, -) from typing import Optional, Set, List from typing_extensions import Self -class KlineCandlestickDataResponse(KlineCandlestickDataResponseItem): +class KlineCandlestickDataResponse(BaseModel): """ KlineCandlestickDataResponse """ # noqa: E501 diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/rest_api.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/rest_api.py index 93f62075..f115a667 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/rest_api.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/rest_api.py @@ -295,10 +295,11 @@ def get_download_id_for_futures_order_history( Get Download Id For Futures Order History - * Request Limitation is 10 times per month, shared by front end download page and rest api + * Request Limitation is 8 times per month, shared by front end download page and rest api + * This endpoint uses the IP rate limit bucket and costs 1000 weight per call. The maximum is 2 calls per minute; the 3rd call within the same minute will trigger a ban. * The time between `startTime` and `endTime` can not be longer than 1 year - Weight: 5 + Weight: 1000 Args: start_time (Union[int, None]): Timestamp in ms @@ -328,10 +329,11 @@ def get_download_id_for_futures_trade_history( Get download id for futures trade history - * Request Limitation is 5 times per month, shared by front end download page and rest api + * Request Limitation is 8 times per month, shared by front end download page and rest api + * This endpoint uses the IP rate limit bucket and costs 1000 weight per call. The maximum is 2 calls per minute; the 3rd call within the same minute will trigger a ban. * The time between `startTime` and `endTime` can not be longer than 1 year - Weight: 5 + Weight: 1000 Args: start_time (Union[int, None]): Timestamp in ms @@ -361,10 +363,11 @@ def get_download_id_for_futures_transaction_history( Get download id for futures transaction history - * Request Limitation is 5 times per month, shared by front end download page and rest api + * Request Limitation is 8 times per month, shared by front end download page and rest api + * This endpoint uses the IP rate limit bucket and costs 1000 weight per call. The maximum is 2 calls per minute; the 3rd call within the same minute will trigger a ban. * The time between `startTime` and `endTime` can not be longer than 1 year - Weight: 5 + Weight: 1000 Args: start_time (Union[int, None]): Timestamp in ms @@ -393,7 +396,7 @@ def get_futures_order_history_download_link_by_id( Get futures order history download link by Id - * Download link expiration: 24h + * Download link expiration: 7 days Weight: 5 @@ -423,7 +426,7 @@ def get_futures_trade_download_link_by_id( Get futures trade download link by Id - * Download link expiration: 24h + * Download link expiration: 7 days Weight: 5 @@ -453,7 +456,7 @@ def get_futures_transaction_history_download_link_by_id( Get futures transaction history download link by Id - * Download link expiration: 24h + * Download link expiration: 7 days Weight: 5 @@ -553,7 +556,7 @@ def notional_bracket_for_symbol( Get the symbol's notional bracket list. - Weight: 1 + Weight: 1 (after CM migration: 1 with symbol / 2 without symbol) Args: symbol (Optional[str] = None): @@ -669,7 +672,7 @@ def compressed_aggregate_trades_list( Get compressed, aggregate trades. Market trades that fill in 100ms with the same price and the same taking side will have the quantity aggregated. - * support querying futures trade histories that are not older than one year + * support querying futures trade histories that are not older than 24 hours * If both `startTime` and `endTime` are sent, time between `startTime` and `endTime` must be less than 1 hour. * If `fromId`, `startTime`, and `endTime` are not sent, the most recent aggregate trades will be returned. * Only market trades will be aggregated and returned, which means the insurance fund trades and ADL trades won't be aggregated. @@ -718,7 +721,6 @@ def continuous_contract_kline_candlestick_data( * CURRENT_QUARTER * NEXT_QUARTER - 1000 | 10 * The difference between `startTime` and `endTime` can only be up to 200 days * Between `startTime` and `endTime`, the most recent `limit` data from `endTime` will be returned: @@ -871,7 +873,6 @@ def index_price_kline_candlestick_data( Kline/candlestick bars for the index price of a pair. Klines are uniquely identified by their open time. - 1000 | 10 * The difference between `startTime` and `endTime` can only be up to 200 days * Between `startTime` and `endTime`, the most recent `limit` data from `endTime` will be returned: @@ -1005,7 +1006,6 @@ def mark_price_kline_candlestick_data( Kline/candlestick bars for the mark price of a symbol. Klines are uniquely identified by their open time. - 1000 | 10 * The difference between `startTime` and `endTime` can only be up to 200 days * Between `startTime` and `endTime`, the most recent `limit` data from `endTime` will be returned: @@ -1052,6 +1052,7 @@ def old_trades_lookup( Get older market historical trades. * Market trades means trades filled in the order book. Only market trades will be returned, which means the insurance fund trades and ADL trades won't be returned. + * Only supports data from within the last one month Weight: 20 @@ -1550,7 +1551,7 @@ def account_trade_list( * If startTime and endTime are both not sent, then the last 7 days' data will be returned. * The time between startTime and endTime cannot be longer than 7 days. - Weight: 20 with symbol,40 with pair + Weight: 20 with symbol,40 with pair (after CM migration: 5 flat) Args: symbol (Optional[str] = None): @@ -1600,7 +1601,7 @@ def all_orders( * If orderId is set, it will get orders >= that orderId. Otherwise most recent orders are returned. * The query time period must be less then 7 days( default as the recent 7 days). - Weight: 20 with symbol, 40 with pair + Weight: 20 with symbol, 40 with pair (after CM migration: 5 flat) Args: symbol (Optional[str] = None): @@ -1730,7 +1731,6 @@ def cancel_order( Cancel an active order. - * Either `orderId` or `origClientOrderId` must be sent. Weight: 1 @@ -1819,7 +1819,11 @@ def change_position_mode( """ Change Position Mode(TRADE) - Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol*** + Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol***. + + **After CM migration**, UM and CM share the **same** `dualSidePosition` setting. Calling this endpoint flips both UM and CM at once. If either side has any open order or open position, the change is rejected: + - `-4067` (open orders exist) + - `-4068` (open position exists) Weight: 1 @@ -1969,7 +1973,7 @@ def modify_isolated_position_margin( Args: symbol (Union[str, None]): amount (Union[float, None]): - type (Union[ModifyIsolatedPositionMarginTypeEnum, None]): + type (Union[ModifyIsolatedPositionMarginTypeEnum, None]): **After CM migration, stop-type values (`STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`) are no longer accepted by this endpoint and will return `-4120`. Use the new `/dapi/v1/algoOrder` endpoint instead.** position_side (Optional[ModifyIsolatedPositionMarginPositionSideEnum] = None): Default `BOTH` for One-way Mode ; `LONG` or `SHORT` for Hedge Mode. It must be sent with Hedge Mode. recv_window (Optional[int] = None): @@ -2033,7 +2037,7 @@ def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. - * Either `quantity` or `price` must be sent. + * Either `quantity` or `price` must be sent. *(After CM migration, both `quantity` and `price` are required.)* * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. * However the order will be cancelled by the amendment in the following situations: * when the order is in partially filled status and the new `quantity` <= `executedQty` @@ -2100,7 +2104,6 @@ def new_order( Send in a new order. - * Order with type `STOP`, parameter `timeInForce` can be sent ( default `GTC`). * Order with type `TAKE_PROFIT`, parameter `timeInForce` can be sent ( default `GTC`). * Condition orders will be triggered when: @@ -2143,7 +2146,7 @@ def new_order( Args: symbol (Union[str, None]): side (Union[NewOrderSideEnum, None]): `SELL`, `BUY` - type (Union[NewOrderTypeEnum, None]): + type (Union[NewOrderTypeEnum, None]): **After CM migration, stop-type values (`STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`) are no longer accepted by this endpoint and will return `-4120`. Use the new `/dapi/v1/algoOrder` endpoint instead.** position_side (Optional[NewOrderPositionSideEnum] = None): Default `BOTH` for One-way Mode ; `LONG` or `SHORT` for Hedge Mode. It must be sent with Hedge Mode. time_in_force (Optional[NewOrderTimeInForceEnum] = None): quantity (Optional[float] = None): quantity measured by contract number, Cannot be sent with `closePosition`=`true` @@ -2155,7 +2158,7 @@ def new_order( activation_price (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, default as the latest price(supporting different `workingType`) callback_rate (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, min 0.1, max 10 where 1 for 1% working_type (Optional[NewOrderWorkingTypeEnum] = None): stopPrice triggered by: "MARK_PRICE", "CONTRACT_PRICE". Default "CONTRACT_PRICE" - price_protect (Optional[str] = None): "TRUE" or "FALSE", default "FALSE". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. + price_protect (Optional[str] = None): "true" or "false", default "false". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. new_order_resp_type (Optional[NewOrderNewOrderRespTypeEnum] = None): "ACK", "RESULT", default "ACK" price_match (Optional[NewOrderPriceMatchEnum] = None): only avaliable for `LIMIT`/`STOP`/`TAKE_PROFIT` order; can be set to `OPPONENT`/ `OPPONENT_5`/ `OPPONENT_10`/ `OPPONENT_20`: /`QUEUE`/ `QUEUE_5`/ `QUEUE_10`/ `QUEUE_20`; Can't be passed together with `price` self_trade_prevention_mode (Optional[NewOrderSelfTradePreventionModeEnum] = None): `EXPIRE_TAKER`:expire taker order when STP triggers/ `EXPIRE_MAKER`:expire taker order when STP triggers/ `EXPIRE_BOTH`:expire both orders when STP triggers; default `EXPIRE_MAKER` @@ -2376,9 +2379,9 @@ def users_force_orders( User's Force Orders * If "autoCloseType" is not sent, orders with both of the types will be returned - * If "startTime" is not sent, data within 200 days before "endTime" can be queried + * Only support querying data in the past 90 days - Weight: 20 with symbol, 50 without symbol + Weight: 20 (after CM migration: 20 with symbol / 50 without symbol) Args: symbol (Optional[str] = None): diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/api/trade_api.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/api/trade_api.py index 70ac78cd..375cf1e4 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/api/trade_api.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/api/trade_api.py @@ -125,7 +125,7 @@ async def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. - * Both `quantity` and `price` must be sent, which is different from dapi modify order endpoint. + * Both `quantity` and `price` must be sent. * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. * However the order will be cancelled by the amendment in the following situations: * when the order is in partially filled status and the new `quantity` <= `executedQty` @@ -262,7 +262,7 @@ async def new_order( Args: symbol (Union[str, None]): side (Union[NewOrderSideEnum, None]): `SELL`, `BUY` - type (Union[NewOrderTypeEnum, None]): `LIMIT`, `MARKET`, `STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET` + type (Union[NewOrderTypeEnum, None]): `LIMIT`, `MARKET`, `STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`. **After CM migration, stop-type values (`STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`) are no longer accepted and will return `-4120`. Use the REST `/dapi/v1/algoOrder` endpoint instead.** id (Optional[str] = None): Unique WebSocket request ID. position_side (Optional[NewOrderPositionSideEnum] = None): Default `BOTH` for One-way Mode; `LONG` or `SHORT` for Hedge Mode. It must be sent in Hedge Mode. time_in_force (Optional[NewOrderTimeInForceEnum] = None): @@ -275,7 +275,7 @@ async def new_order( activation_price (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, default as the latest price(supporting different workingType) callback_rate (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, min 0.1, max 10 where 1 for 1% working_type (Optional[NewOrderWorkingTypeEnum] = None): stopPrice triggered by: "MARK_PRICE", "CONTRACT_PRICE". Default "CONTRACT_PRICE" - price_protect (Optional[str] = None): "TRUE" or "FALSE", default "FALSE". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. + price_protect (Optional[str] = None): "true" or "false", default "false". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. new_order_resp_type (Optional[NewOrderNewOrderRespTypeEnum] = None): `ACK`,`RESULT`, default `ACK` price_match (Optional[NewOrderPriceMatchEnum] = None): only available for `LIMIT`/`STOP`/`TAKE_PROFIT` order; can be set to `OPPONENT`/ `OPPONENT_5`/ `OPPONENT_10`/ `OPPONENT_20`: /`QUEUE`/ `QUEUE_5`/ `QUEUE_10`/ `QUEUE_20`; Can't be passed together with `price` self_trade_prevention_mode (Optional[NewOrderSelfTradePreventionModeEnum] = None): `NONE`: No STP / `EXPIRE_TAKER`:expire taker order when STP triggers/ `EXPIRE_MAKER`:expire taker order when STP triggers/ `EXPIRE_BOTH`:expire both orders when STP triggers; default `NONE` diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/websocket_api.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/websocket_api.py index e11a078d..1c3d9f09 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/websocket_api.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_api/websocket_api.py @@ -259,7 +259,7 @@ async def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. - * Both `quantity` and `price` must be sent, which is different from dapi modify order endpoint. + * Both `quantity` and `price` must be sent. * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. * However the order will be cancelled by the amendment in the following situations: * when the order is in partially filled status and the new `quantity` <= `executedQty` @@ -364,7 +364,7 @@ async def new_order( Args: symbol (Union[str, None]): side (Union[NewOrderSideEnum, None]): `SELL`, `BUY` - type (Union[NewOrderTypeEnum, None]): `LIMIT`, `MARKET`, `STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET` + type (Union[NewOrderTypeEnum, None]): `LIMIT`, `MARKET`, `STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`. **After CM migration, stop-type values (`STOP`, `STOP_MARKET`, `TAKE_PROFIT`, `TAKE_PROFIT_MARKET`, `TRAILING_STOP_MARKET`) are no longer accepted and will return `-4120`. Use the REST `/dapi/v1/algoOrder` endpoint instead.** id (Optional[str] = None): Unique WebSocket request ID. position_side (Optional[NewOrderPositionSideEnum] = None): Default `BOTH` for One-way Mode; `LONG` or `SHORT` for Hedge Mode. It must be sent in Hedge Mode. time_in_force (Optional[NewOrderTimeInForceEnum] = None): @@ -377,7 +377,7 @@ async def new_order( activation_price (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, default as the latest price(supporting different workingType) callback_rate (Optional[float] = None): Used with `TRAILING_STOP_MARKET` orders, min 0.1, max 10 where 1 for 1% working_type (Optional[NewOrderWorkingTypeEnum] = None): stopPrice triggered by: "MARK_PRICE", "CONTRACT_PRICE". Default "CONTRACT_PRICE" - price_protect (Optional[str] = None): "TRUE" or "FALSE", default "FALSE". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. + price_protect (Optional[str] = None): "true" or "false", default "false". Used with `STOP/STOP_MARKET` or `TAKE_PROFIT/TAKE_PROFIT_MARKET` orders. new_order_resp_type (Optional[NewOrderNewOrderRespTypeEnum] = None): `ACK`,`RESULT`, default `ACK` price_match (Optional[NewOrderPriceMatchEnum] = None): only available for `LIMIT`/`STOP`/`TAKE_PROFIT` order; can be set to `OPPONENT`/ `OPPONENT_5`/ `OPPONENT_10`/ `OPPONENT_20`: /`QUEUE`/ `QUEUE_5`/ `QUEUE_10`/ `QUEUE_20`; Can't be passed together with `price` self_trade_prevention_mode (Optional[NewOrderSelfTradePreventionModeEnum] = None): `NONE`: No STP / `EXPIRE_TAKER`:expire taker order when STP triggers/ `EXPIRE_MAKER`:expire taker order when STP triggers/ `EXPIRE_BOTH`:expire both orders when STP triggers; default `NONE` diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/aggregate_trade_streams_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/aggregate_trade_streams_response.py index 0d6ce615..da7aef93 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/aggregate_trade_streams_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/aggregate_trade_streams_response.py @@ -37,6 +37,7 @@ class AggregateTradeStreamsResponse(BaseModel): l: Optional[StrictInt] = None T: Optional[StrictInt] = Field(default=None, alias="T") m: Optional[StrictBool] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -49,6 +50,7 @@ class AggregateTradeStreamsResponse(BaseModel): "l", "T", "m", + "st", ] model_config = ConfigDict( @@ -121,6 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "l": obj.get("l"), "T": obj.get("T"), "m": obj.get("m"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_book_tickers_stream_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_book_tickers_stream_response.py index 58869023..afa74693 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_book_tickers_stream_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_book_tickers_stream_response.py @@ -30,25 +30,27 @@ class AllBookTickersStreamResponse(BaseModel): e: Optional[StrictStr] = None u: Optional[StrictInt] = None s: Optional[StrictStr] = None - ps: Optional[StrictStr] = None b: Optional[StrictStr] = None B: Optional[StrictStr] = Field(default=None, alias="B") a: Optional[StrictStr] = None A: Optional[StrictStr] = Field(default=None, alias="A") T: Optional[StrictInt] = Field(default=None, alias="T") E: Optional[StrictInt] = Field(default=None, alias="E") + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", "u", "s", - "ps", "b", "B", "a", "A", "T", "E", + "ps", + "st", ] model_config = ConfigDict( @@ -114,13 +116,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "e": obj.get("e"), "u": obj.get("u"), "s": obj.get("s"), - "ps": obj.get("ps"), "b": obj.get("b"), "B": obj.get("B"), "a": obj.get("a"), "A": obj.get("A"), "T": obj.get("T"), "E": obj.get("E"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py index 8ef8bdbb..70a866ac 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py @@ -33,8 +33,9 @@ class AllMarketLiquidationOrderStreamsResponse(BaseModel): e: Optional[StrictStr] = None E: Optional[StrictInt] = Field(default=None, alias="E") o: Optional[AllMarketLiquidationOrderStreamsResponseO] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "o"] + __properties: ClassVar[List[str]] = ["e", "E", "o", "st"] model_config = ConfigDict( populate_by_name=True, @@ -106,6 +107,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("o") is not None else None ), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py index 1c879edb..ab2166e7 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py @@ -37,6 +37,7 @@ class AllMarketMiniTickersStreamResponseInner(BaseModel): l: Optional[StrictStr] = None v: Optional[StrictStr] = None q: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -49,6 +50,7 @@ class AllMarketMiniTickersStreamResponseInner(BaseModel): "l", "v", "q", + "st", ] model_config = ConfigDict( @@ -121,6 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "l": obj.get("l"), "v": obj.get("v"), "q": obj.get("q"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py index 29285227..94ab06d0 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py @@ -30,7 +30,6 @@ class AllMarketTickersStreamsResponseInner(BaseModel): e: Optional[StrictStr] = None E: Optional[StrictInt] = Field(default=None, alias="E") s: Optional[StrictStr] = None - ps: Optional[StrictStr] = None p: Optional[StrictStr] = None P: Optional[StrictStr] = Field(default=None, alias="P") w: Optional[StrictStr] = None @@ -46,12 +45,13 @@ class AllMarketTickersStreamsResponseInner(BaseModel): F: Optional[StrictInt] = Field(default=None, alias="F") L: Optional[StrictInt] = Field(default=None, alias="L") n: Optional[StrictInt] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", "E", "s", - "ps", "p", "P", "w", @@ -67,6 +67,8 @@ class AllMarketTickersStreamsResponseInner(BaseModel): "F", "L", "n", + "ps", + "st", ] model_config = ConfigDict( @@ -132,7 +134,6 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "e": obj.get("e"), "E": obj.get("E"), "s": obj.get("s"), - "ps": obj.get("ps"), "p": obj.get("p"), "P": obj.get("P"), "w": obj.get("w"), @@ -148,6 +149,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "F": obj.get("F"), "L": obj.get("L"), "n": obj.get("n"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/contract_info_stream_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/contract_info_stream_response.py index 09ee6510..bddcb454 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/contract_info_stream_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/contract_info_stream_response.py @@ -39,6 +39,7 @@ class ContractInfoStreamResponse(BaseModel): ot: Optional[StrictInt] = None cs: Optional[StrictStr] = None bks: Optional[List[ContractInfoStreamResponseBksInner]] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -50,6 +51,7 @@ class ContractInfoStreamResponse(BaseModel): "ot", "cs", "bks", + "st", ] model_config = ConfigDict( @@ -135,6 +137,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("bks") is not None else None ), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/diff_book_depth_streams_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/diff_book_depth_streams_response.py index eb4042e4..2de4b499 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/diff_book_depth_streams_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/diff_book_depth_streams_response.py @@ -43,6 +43,7 @@ class DiffBookDepthStreamsResponse(BaseModel): pu: Optional[StrictInt] = None b: Optional[List[DiffBookDepthStreamsResponseBItem]] = None a: Optional[List[DiffBookDepthStreamsResponseAItem]] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -55,6 +56,7 @@ class DiffBookDepthStreamsResponse(BaseModel): "pu", "b", "a", + "st", ] model_config = ConfigDict( @@ -155,6 +157,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("a") is not None else None ), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py index ae31b07b..793e22b7 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py @@ -30,25 +30,27 @@ class IndividualSymbolBookTickerStreamsResponse(BaseModel): e: Optional[StrictStr] = None u: Optional[StrictInt] = None s: Optional[StrictStr] = None - ps: Optional[StrictStr] = None b: Optional[StrictStr] = None B: Optional[StrictStr] = Field(default=None, alias="B") a: Optional[StrictStr] = None A: Optional[StrictStr] = Field(default=None, alias="A") T: Optional[StrictInt] = Field(default=None, alias="T") E: Optional[StrictInt] = Field(default=None, alias="E") + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", "u", "s", - "ps", "b", "B", "a", "A", "T", "E", + "ps", + "st", ] model_config = ConfigDict( @@ -114,13 +116,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "e": obj.get("e"), "u": obj.get("u"), "s": obj.get("s"), - "ps": obj.get("ps"), "b": obj.get("b"), "B": obj.get("B"), "a": obj.get("a"), "A": obj.get("A"), "T": obj.get("T"), "E": obj.get("E"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py index faf08a8f..2878e8cc 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py @@ -37,6 +37,7 @@ class IndividualSymbolMiniTickerStreamResponse(BaseModel): l: Optional[StrictStr] = None v: Optional[StrictStr] = None q: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -49,6 +50,7 @@ class IndividualSymbolMiniTickerStreamResponse(BaseModel): "l", "v", "q", + "st", ] model_config = ConfigDict( @@ -121,6 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "l": obj.get("l"), "v": obj.get("v"), "q": obj.get("q"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py index 3b2d61d7..e124c606 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py @@ -30,7 +30,6 @@ class IndividualSymbolTickerStreamsResponse(BaseModel): e: Optional[StrictStr] = None E: Optional[StrictInt] = Field(default=None, alias="E") s: Optional[StrictStr] = None - ps: Optional[StrictStr] = None p: Optional[StrictStr] = None P: Optional[StrictStr] = Field(default=None, alias="P") w: Optional[StrictStr] = None @@ -46,12 +45,13 @@ class IndividualSymbolTickerStreamsResponse(BaseModel): F: Optional[StrictInt] = Field(default=None, alias="F") L: Optional[StrictInt] = Field(default=None, alias="L") n: Optional[StrictInt] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", "E", "s", - "ps", "p", "P", "w", @@ -67,6 +67,8 @@ class IndividualSymbolTickerStreamsResponse(BaseModel): "F", "L", "n", + "ps", + "st", ] model_config = ConfigDict( @@ -132,7 +134,6 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "e": obj.get("e"), "E": obj.get("E"), "s": obj.get("s"), - "ps": obj.get("ps"), "p": obj.get("p"), "P": obj.get("P"), "w": obj.get("w"), @@ -148,6 +149,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "F": obj.get("F"), "L": obj.get("L"), "n": obj.get("n"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_of_all_symbols_of_a_pair_response_inner.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_of_all_symbols_of_a_pair_response_inner.py index 685f9d06..eb9d8bf8 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_of_all_symbols_of_a_pair_response_inner.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_of_all_symbols_of_a_pair_response_inner.py @@ -35,8 +35,9 @@ class MarkPriceOfAllSymbolsOfAPairResponseInner(BaseModel): i: Optional[StrictStr] = None r: Optional[StrictStr] = None T: Optional[StrictInt] = Field(default=None, alias="T") + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "s", "p", "P", "i", "r", "T"] + __properties: ClassVar[List[str]] = ["e", "E", "s", "p", "P", "i", "r", "T", "st"] model_config = ConfigDict( populate_by_name=True, @@ -106,6 +107,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "i": obj.get("i"), "r": obj.get("r"), "T": obj.get("T"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_stream_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_stream_response.py index e5b6f45b..3c5e072f 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_stream_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/mark_price_stream_response.py @@ -35,8 +35,9 @@ class MarkPriceStreamResponse(BaseModel): i: Optional[StrictStr] = None r: Optional[StrictStr] = None T: Optional[StrictInt] = Field(default=None, alias="T") + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "s", "p", "P", "i", "r", "T"] + __properties: ClassVar[List[str]] = ["e", "E", "s", "p", "P", "i", "r", "T", "st"] model_config = ConfigDict( populate_by_name=True, @@ -106,6 +107,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "i": obj.get("i"), "r": obj.get("r"), "T": obj.get("T"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/partial_book_depth_streams_response.py b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/partial_book_depth_streams_response.py index 11434f53..6e81f198 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/partial_book_depth_streams_response.py +++ b/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/websocket_streams/models/partial_book_depth_streams_response.py @@ -43,6 +43,7 @@ class PartialBookDepthStreamsResponse(BaseModel): pu: Optional[StrictInt] = None b: Optional[List[PartialBookDepthStreamsResponseBItem]] = None a: Optional[List[PartialBookDepthStreamsResponseAItem]] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -55,6 +56,7 @@ class PartialBookDepthStreamsResponse(BaseModel): "pu", "b", "a", + "st", ] model_config = ConfigDict( @@ -155,6 +157,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("a") is not None else None ), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_coin_futures/tests/unit/websocket_streams/test_websocket_market_streams_api_ws_streams.py b/clients/derivatives_trading_coin_futures/tests/unit/websocket_streams/test_websocket_market_streams_api_ws_streams.py index afbde634..863bb14a 100644 --- a/clients/derivatives_trading_coin_futures/tests/unit/websocket_streams/test_websocket_market_streams_api_ws_streams.py +++ b/clients/derivatives_trading_coin_futures/tests/unit/websocket_streams/test_websocket_market_streams_api_ws_streams.py @@ -58,6 +58,7 @@ async def test_aggregate_trade_streams_subscription(self): "l": 606073, "T": 1591261134199, "m": False, + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@aggTrade".replace("/", "", 1), @@ -98,6 +99,7 @@ async def test_aggregate_trade_streams_success(self): "l": 606073, "T": 1591261134199, "m": False, + "st": 1, } self.ws_streams.aggregate_trade_streams = AsyncMock( return_value=expected_response @@ -124,6 +126,7 @@ async def test_aggregate_trade_streams_success_with_optional_params(self): "l": 606073, "T": 1591261134199, "m": False, + "st": 1, } self.ws_streams.aggregate_trade_streams = AsyncMock( @@ -167,13 +170,14 @@ async def test_all_book_tickers_stream_subscription(self): "e": "bookTicker", "u": 17242169, "s": "BTCUSD_200626", - "ps": "BTCUSD", "b": "9548.1", "B": "52", "a": "9548.5", "A": "11", "T": 1591268628155, "E": 1591268628166, + "ps": "BTCUSD", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/!bookTicker".replace("/", "", 1), @@ -203,13 +207,14 @@ async def test_all_book_tickers_stream_success(self): "e": "bookTicker", "u": 17242169, "s": "BTCUSD_200626", - "ps": "BTCUSD", "b": "9548.1", "B": "52", "a": "9548.5", "A": "11", "T": 1591268628155, "E": 1591268628166, + "ps": "BTCUSD", + "st": 1, } self.ws_streams.all_book_tickers_stream = AsyncMock( return_value=expected_response @@ -229,13 +234,14 @@ async def test_all_book_tickers_stream_success_with_optional_params(self): "e": "bookTicker", "u": 17242169, "s": "BTCUSD_200626", - "ps": "BTCUSD", "b": "9548.1", "B": "52", "a": "9548.5", "A": "11", "T": 1591268628155, "E": 1591268628166, + "ps": "BTCUSD", + "st": 1, } self.ws_streams.all_book_tickers_stream = AsyncMock( @@ -277,6 +283,7 @@ async def test_all_market_liquidation_order_streams_subscription(self): "z": "1", "T": 1591154240949, }, + "st": 1, } stream_endpoint = ws_streams_placeholder( "/!forceOrder@arr".replace("/", "", 1), @@ -319,6 +326,7 @@ async def test_all_market_liquidation_order_streams_success(self): "z": "1", "T": 1591154240949, }, + "st": 1, } self.ws_streams.all_market_liquidation_order_streams = AsyncMock( return_value=expected_response @@ -353,6 +361,7 @@ async def test_all_market_liquidation_order_streams_success_with_optional_params "z": "1", "T": 1591154240949, }, + "st": 1, } self.ws_streams.all_market_liquidation_order_streams = AsyncMock( @@ -391,6 +400,7 @@ async def test_all_market_mini_tickers_stream_subscription(self): "l": "7000.0", "v": "487476", "q": "33264343847.22378500", + "st": 1, } ] stream_endpoint = ws_streams_placeholder( @@ -429,6 +439,7 @@ async def test_all_market_mini_tickers_stream_success(self): "l": "7000.0", "v": "487476", "q": "33264343847.22378500", + "st": 1, } ] self.ws_streams.all_market_mini_tickers_stream = AsyncMock( @@ -457,6 +468,7 @@ async def test_all_market_mini_tickers_stream_success_with_optional_params(self) "l": "7000.0", "v": "487476", "q": "33264343847.22378500", + "st": 1, } ] @@ -489,7 +501,6 @@ async def test_all_market_tickers_streams_subscription(self): "e": "24hrTicker", "E": 1591268262453, "s": "BTCUSD_200626", - "ps": "BTCUSD", "p": "-43.4", "P": "-0.452", "w": "0.00147974", @@ -505,6 +516,8 @@ async def test_all_market_tickers_streams_subscription(self): "F": 512014, "L": 615289, "n": 103272, + "ps": "BTCUSD", + "st": 1, } ] stream_endpoint = ws_streams_placeholder( @@ -536,7 +549,6 @@ async def test_all_market_tickers_streams_success(self): "e": "24hrTicker", "E": 1591268262453, "s": "BTCUSD_200626", - "ps": "BTCUSD", "p": "-43.4", "P": "-0.452", "w": "0.00147974", @@ -552,6 +564,8 @@ async def test_all_market_tickers_streams_success(self): "F": 512014, "L": 615289, "n": 103272, + "ps": "BTCUSD", + "st": 1, } ] self.ws_streams.all_market_tickers_streams = AsyncMock( @@ -573,7 +587,6 @@ async def test_all_market_tickers_streams_success_with_optional_params(self): "e": "24hrTicker", "E": 1591268262453, "s": "BTCUSD_200626", - "ps": "BTCUSD", "p": "-43.4", "P": "-0.452", "w": "0.00147974", @@ -589,6 +602,8 @@ async def test_all_market_tickers_streams_success_with_optional_params(self): "F": 512014, "L": 615289, "n": 103272, + "ps": "BTCUSD", + "st": 1, } ] @@ -866,6 +881,7 @@ async def test_contract_info_stream_subscription(self): "ma": 20, }, ], + "st": 1, } stream_endpoint = ws_streams_placeholder( "/!contractInfo".replace("/", "", 1), @@ -920,6 +936,7 @@ async def test_contract_info_stream_success(self): "ma": 20, }, ], + "st": 1, } self.ws_streams.contract_info_stream = AsyncMock(return_value=expected_response) @@ -962,6 +979,7 @@ async def test_contract_info_stream_success_with_optional_params(self): "ma": 20, }, ], + "st": 1, } self.ws_streams.contract_info_stream = AsyncMock(return_value=expected_response) @@ -999,6 +1017,7 @@ async def test_diff_book_depth_streams_subscription(self): "pu": 17285675, "b": [["9517.6", "10"]], "a": [["9518.5", "45"]], + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@depth@".replace("/", "", 1), @@ -1039,6 +1058,7 @@ async def test_diff_book_depth_streams_success(self): "pu": 17285675, "b": [["9517.6", "10"]], "a": [["9518.5", "45"]], + "st": 1, } self.ws_streams.diff_book_depth_streams = AsyncMock( return_value=expected_response @@ -1069,6 +1089,7 @@ async def test_diff_book_depth_streams_success_with_optional_params(self): "pu": 17285675, "b": [["9517.6", "10"]], "a": [["9518.5", "45"]], + "st": 1, } self.ws_streams.diff_book_depth_streams = AsyncMock( @@ -1400,13 +1421,14 @@ async def test_individual_symbol_book_ticker_streams_subscription(self): "e": "bookTicker", "u": 17242169, "s": "BTCUSD_200626", - "ps": "BTCUSD", "b": "9548.1", "B": "52", "a": "9548.5", "A": "11", "T": 1591268628155, "E": 1591268628166, + "ps": "BTCUSD", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@bookTicker".replace("/", "", 1), @@ -1440,13 +1462,14 @@ async def test_individual_symbol_book_ticker_streams_success(self): "e": "bookTicker", "u": 17242169, "s": "BTCUSD_200626", - "ps": "BTCUSD", "b": "9548.1", "B": "52", "a": "9548.5", "A": "11", "T": 1591268628155, "E": 1591268628166, + "ps": "BTCUSD", + "st": 1, } self.ws_streams.individual_symbol_book_ticker_streams = AsyncMock( return_value=expected_response @@ -1468,13 +1491,14 @@ async def test_individual_symbol_book_ticker_streams_success_with_optional_param "e": "bookTicker", "u": 17242169, "s": "BTCUSD_200626", - "ps": "BTCUSD", "b": "9548.1", "B": "52", "a": "9548.5", "A": "11", "T": 1591268628155, "E": 1591268628166, + "ps": "BTCUSD", + "st": 1, } self.ws_streams.individual_symbol_book_ticker_streams = AsyncMock( @@ -1533,6 +1557,7 @@ async def test_individual_symbol_mini_ticker_stream_subscription(self): "l": "7000.0", "v": "487476", "q": "33264343847.22378500", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@miniTicker".replace("/", "", 1), @@ -1573,6 +1598,7 @@ async def test_individual_symbol_mini_ticker_stream_success(self): "l": "7000.0", "v": "487476", "q": "33264343847.22378500", + "st": 1, } self.ws_streams.individual_symbol_mini_ticker_stream = AsyncMock( return_value=expected_response @@ -1601,6 +1627,7 @@ async def test_individual_symbol_mini_ticker_stream_success_with_optional_params "l": "7000.0", "v": "487476", "q": "33264343847.22378500", + "st": 1, } self.ws_streams.individual_symbol_mini_ticker_stream = AsyncMock( @@ -1652,7 +1679,6 @@ async def test_individual_symbol_ticker_streams_subscription(self): "e": "24hrTicker", "E": 1591268262453, "s": "BTCUSD_200626", - "ps": "BTCUSD", "p": "-43.4", "P": "-0.452", "w": "0.00147974", @@ -1668,6 +1694,8 @@ async def test_individual_symbol_ticker_streams_subscription(self): "F": 512014, "L": 615289, "n": 103272, + "ps": "BTCUSD", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@ticker".replace("/", "", 1), @@ -1701,7 +1729,6 @@ async def test_individual_symbol_ticker_streams_success(self): "e": "24hrTicker", "E": 1591268262453, "s": "BTCUSD_200626", - "ps": "BTCUSD", "p": "-43.4", "P": "-0.452", "w": "0.00147974", @@ -1717,6 +1744,8 @@ async def test_individual_symbol_ticker_streams_success(self): "F": 512014, "L": 615289, "n": 103272, + "ps": "BTCUSD", + "st": 1, } self.ws_streams.individual_symbol_ticker_streams = AsyncMock( return_value=expected_response @@ -1736,7 +1765,6 @@ async def test_individual_symbol_ticker_streams_success_with_optional_params(sel "e": "24hrTicker", "E": 1591268262453, "s": "BTCUSD_200626", - "ps": "BTCUSD", "p": "-43.4", "P": "-0.452", "w": "0.00147974", @@ -1752,6 +1780,8 @@ async def test_individual_symbol_ticker_streams_success_with_optional_params(sel "F": 512014, "L": 615289, "n": 103272, + "ps": "BTCUSD", + "st": 1, } self.ws_streams.individual_symbol_ticker_streams = AsyncMock( @@ -2309,6 +2339,7 @@ async def test_mark_price_of_all_symbols_of_a_pair_subscription(self): "i": "10933.62615417", "r": "", "T": 0, + "st": 1, }, { "e": "markPriceUpdate", @@ -2319,6 +2350,7 @@ async def test_mark_price_of_all_symbols_of_a_pair_subscription(self): "i": "10933.62615417", "r": "0.00000000", "T": 1596096000000, + "st": 1, }, ] stream_endpoint = ws_streams_placeholder( @@ -2359,6 +2391,7 @@ async def test_mark_price_of_all_symbols_of_a_pair_success(self): "i": "10933.62615417", "r": "", "T": 0, + "st": 1, }, { "e": "markPriceUpdate", @@ -2369,6 +2402,7 @@ async def test_mark_price_of_all_symbols_of_a_pair_success(self): "i": "10933.62615417", "r": "0.00000000", "T": 1596096000000, + "st": 1, }, ] self.ws_streams.mark_price_of_all_symbols_of_a_pair = AsyncMock( @@ -2401,6 +2435,7 @@ async def test_mark_price_of_all_symbols_of_a_pair_success_with_optional_params( "i": "10933.62615417", "r": "", "T": 0, + "st": 1, }, { "e": "markPriceUpdate", @@ -2411,6 +2446,7 @@ async def test_mark_price_of_all_symbols_of_a_pair_success_with_optional_params( "i": "10933.62615417", "r": "0.00000000", "T": 1596096000000, + "st": 1, }, ] @@ -2468,6 +2504,7 @@ async def test_mark_price_stream_subscription(self): "i": "10933.62615417", "r": "", "T": 0, + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@markPrice@".replace("/", "", 1), @@ -2506,6 +2543,7 @@ async def test_mark_price_stream_success(self): "i": "10933.62615417", "r": "", "T": 0, + "st": 1, } self.ws_streams.mark_price_stream = AsyncMock(return_value=expected_response) @@ -2532,6 +2570,7 @@ async def test_mark_price_stream_success_with_optional_params(self): "i": "10933.62615417", "r": "", "T": 0, + "st": 1, } self.ws_streams.mark_price_stream = AsyncMock(return_value=expected_response) @@ -2597,6 +2636,7 @@ async def test_partial_book_depth_streams_subscription(self): ["9525.1", "10"], ["9525.3", "6"], ], + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@depth@".replace("/", "", 1), @@ -2650,6 +2690,7 @@ async def test_partial_book_depth_streams_success(self): ["9525.1", "10"], ["9525.3", "6"], ], + "st": 1, } self.ws_streams.partial_book_depth_streams = AsyncMock( return_value=expected_response @@ -2693,6 +2734,7 @@ async def test_partial_book_depth_streams_success_with_optional_params(self): ["9525.1", "10"], ["9525.3", "6"], ], + "st": 1, } self.ws_streams.partial_book_depth_streams = AsyncMock( diff --git a/clients/derivatives_trading_usds_futures/CHANGELOG.md b/clients/derivatives_trading_usds_futures/CHANGELOG.md index 4e17d184..7659efa8 100644 --- a/clients/derivatives_trading_usds_futures/CHANGELOG.md +++ b/clients/derivatives_trading_usds_futures/CHANGELOG.md @@ -1,5 +1,75 @@ # Changelog +## 12.0.0 - 2026-06-29 + +### Changed (15) + +#### REST API + +- Modified response for `asset_index()` (`GET /fapi/v1/assetIndex`): + - oneOf added 2 schema(s) + - oneOf removed 2 schema(s) + +#### WebSocket Streams + +- Modified response for `all_book_tickers_stream()` (`!bookTicker` stream): + - property `ps` added + - property `st` added + +- Modified response for `contract_info_stream()` (`!contractInfo` stream): + - property `st` added + - property `ps` deleted + +- Modified response for `all_market_liquidation_order_streams()` (`!forceOrder@arr` stream): + - property `st` added + - property `ps` added + +- Modified response for `mark_price_stream_for_all_market()` (`!markPrice@arr@` stream): + - items: property `st` added + - items: item property `st` added + +- Modified response for `all_market_mini_tickers_stream()` (`!miniTicker@arr` stream): + - items: property `st` added + - items: property `ps` added + - items: item property `st` added + - items: item property `ps` added + +- Modified response for `all_market_tickers_streams()` (`!ticker@arr` stream): + - items: property `ps` added + - items: property `st` added + - items: item property `ps` added + - items: item property `st` added + +- Modified response for `aggregate_trade_streams()` (`@aggTrade` stream): + - property `st` added + +- Modified response for `individual_symbol_book_ticker_streams()` (`@bookTicker` stream): + - property `st` added + - property `ps` added + +- Modified response for `partial_book_depth_streams()` (`@depth@` stream): + - property `ps` added + - property `st` added + +- Modified response for `diff_book_depth_streams()` (`@depth@` stream): + - property `st` added + - property `ps` added + +- Modified response for `mark_price_stream()` (`@markPrice@` stream): + - property `st` added + +- Modified response for `individual_symbol_mini_ticker_stream()` (`@miniTicker` stream): + - property `ps` added + - property `st` added + +- Modified response for `rpi_diff_book_depth_streams()` (`@rpiDepth@500ms` stream): + - property `st` added + - property `ps` added + +- Modified response for `individual_symbol_ticker_streams()` (`@ticker` stream): + - property `ps` added + - property `st` added + ## 11.0.0 - 2026-06-09 ### Changed (11) diff --git a/clients/derivatives_trading_usds_futures/examples/rest_api/MarketData/multi_assets_mode_asset_index.py b/clients/derivatives_trading_usds_futures/examples/rest_api/MarketData/asset_index.py similarity index 69% rename from clients/derivatives_trading_usds_futures/examples/rest_api/MarketData/multi_assets_mode_asset_index.py rename to clients/derivatives_trading_usds_futures/examples/rest_api/MarketData/asset_index.py index d831c53e..94946cb0 100644 --- a/clients/derivatives_trading_usds_futures/examples/rest_api/MarketData/multi_assets_mode_asset_index.py +++ b/clients/derivatives_trading_usds_futures/examples/rest_api/MarketData/asset_index.py @@ -24,18 +24,18 @@ client = DerivativesTradingUsdsFutures(config_rest_api=configuration_rest_api) -def multi_assets_mode_asset_index(): +def asset_index(): try: - response = client.rest_api.multi_assets_mode_asset_index() + response = client.rest_api.asset_index() rate_limits = response.rate_limits - logging.info(f"multi_assets_mode_asset_index() rate limits: {rate_limits}") + logging.info(f"asset_index() rate limits: {rate_limits}") data = response.data() - logging.info(f"multi_assets_mode_asset_index() response: {data}") + logging.info(f"asset_index() response: {data}") except Exception as e: - logging.error(f"multi_assets_mode_asset_index() error: {e}") + logging.error(f"asset_index() error: {e}") if __name__ == "__main__": - multi_assets_mode_asset_index() + asset_index() diff --git a/clients/derivatives_trading_usds_futures/examples/websocket_streams/multi_assets_mode_asset_index.py b/clients/derivatives_trading_usds_futures/examples/websocket_streams/asset_index.py similarity index 82% rename from clients/derivatives_trading_usds_futures/examples/websocket_streams/multi_assets_mode_asset_index.py rename to clients/derivatives_trading_usds_futures/examples/websocket_streams/asset_index.py index 3cefc292..4b998ef5 100644 --- a/clients/derivatives_trading_usds_futures/examples/websocket_streams/multi_assets_mode_asset_index.py +++ b/clients/derivatives_trading_usds_futures/examples/websocket_streams/asset_index.py @@ -23,22 +23,22 @@ client = DerivativesTradingUsdsFutures(config_ws_streams=configuration_ws_streams) -async def multi_assets_mode_asset_index(): +async def asset_index(): connection = None try: connection = await client.websocket_streams.create_connection() - stream = await connection.multi_assets_mode_asset_index() + stream = await connection.asset_index() stream.on("message", lambda data: print(f"{data}")) await asyncio.sleep(5) await stream.unsubscribe() except Exception as e: - logging.error(f"multi_assets_mode_asset_index() error: {e}") + logging.error(f"asset_index() error: {e}") finally: if connection: await connection.close_connection(close_session=True) if __name__ == "__main__": - asyncio.run(multi_assets_mode_asset_index()) + asyncio.run(asset_index()) diff --git a/clients/derivatives_trading_usds_futures/pyproject.toml b/clients/derivatives_trading_usds_futures/pyproject.toml index 003b37c7..8dd7b017 100644 --- a/clients/derivatives_trading_usds_futures/pyproject.toml +++ b/clients/derivatives_trading_usds_futures/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "binance-sdk-derivatives-trading-usds-futures" -version = "11.0.0" +version = "12.0.0" description = "Official Binance Derivatives Trading Usds Futures SDK - A lightweight library that provides a convenient interface to Binance's DerivativesTradingUsdsFutures REST API, WebSocket API and WebSocket Streams." authors = ["Binance"] license = "MIT" diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/market_data_api.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/market_data_api.py index e6b737dd..12509548 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/market_data_api.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/market_data_api.py @@ -17,6 +17,7 @@ from binance_common.utils import send_request from ..models import AdlRiskResponse +from ..models import AssetIndexResponse from ..models import BasisResponse from ..models import CheckServerTimeResponse from ..models import CompositeIndexSymbolInformationResponse @@ -30,7 +31,6 @@ from ..models import LongShortRatioResponse from ..models import MarkPriceResponse from ..models import MarkPriceKlineCandlestickDataResponse -from ..models import MultiAssetsModeAssetIndexResponse from ..models import OldTradesLookupResponse from ..models import OpenInterestResponse from ..models import OpenInterestStatisticsResponse @@ -120,6 +120,44 @@ def adl_risk( response_model=AdlRiskResponse, ) + def asset_index( + self, + symbol: Optional[str] = None, + ) -> ApiResponse[AssetIndexResponse]: + """ + Asset Index + GET /fapi/v1/assetIndex + https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/Asset-Index + + Asset index price. + + Weight: 1 for a single symbol; 10 when the symbol parameter is omitted + + Args: + symbol (Optional[str] = None): + + Returns: + ApiResponse[AssetIndexResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + body = {} + payload = {"symbol": symbol} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/fapi/v1/assetIndex", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=AssetIndexResponse, + ) + def basis( self, pair: Union[str, None], @@ -142,7 +180,7 @@ def basis( Weight: 0 Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. contract_type (Union[BasisContractTypeEnum, None]): period (Union[BasisPeriodEnum, None]): "5m","15m","30m","1h","2h","4h","6h","12h","1d" limit (Optional[int] = None): Default 100; max 1000 @@ -368,7 +406,7 @@ def continuous_contract_kline_candlestick_data( | > 1000 | 10 | Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. contract_type (Union[ContinuousContractKlineCandlestickDataContractTypeEnum, None]): interval (Union[ContinuousContractKlineCandlestickDataIntervalEnum, None]): start_time (Optional[int] = None): @@ -561,7 +599,6 @@ def index_price_kline_candlestick_data( Kline/candlestick bars for the index price of a pair. Klines are uniquely identified by their open time. - * If startTime and endTime are not sent, the most recent klines are returned. Weight: based on parameter LIMIT @@ -573,7 +610,7 @@ def index_price_kline_candlestick_data( | > 1000 | 10 | Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. interval (Union[IndexPriceKlineCandlestickDataIntervalEnum, None]): start_time (Optional[int] = None): end_time (Optional[int] = None): @@ -859,44 +896,6 @@ def mark_price_kline_candlestick_data( response_model=MarkPriceKlineCandlestickDataResponse, ) - def multi_assets_mode_asset_index( - self, - symbol: Optional[str] = None, - ) -> ApiResponse[MultiAssetsModeAssetIndexResponse]: - """ - Multi-Assets Mode Asset Index - GET /fapi/v1/assetIndex - https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/Multi-Assets-Mode-Asset-Index - - asset index for Multi-Assets mode - - Weight: 1 for a single symbol; 10 when the symbol parameter is omitted - - Args: - symbol (Optional[str] = None): - - Returns: - ApiResponse[MultiAssetsModeAssetIndexResponse] - - Raises: - RequiredError: If a required parameter is missing. - - """ - - body = {} - payload = {"symbol": symbol} - - return send_request( - self._session, - self._configuration, - method="GET", - path="/fapi/v1/assetIndex", - payload=payload, - body=body, - time_unit=self._configuration.time_unit, - response_model=MultiAssetsModeAssetIndexResponse, - ) - def old_trades_lookup( self, symbol: Union[str, None], @@ -1192,7 +1191,7 @@ def quarterly_contract_settlement_price( Weight: 0 Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. Returns: ApiResponse[QuarterlyContractSettlementPriceResponse] @@ -1818,12 +1817,12 @@ def trading_schedule( Trading session schedules for the underlying assets of TradFi Perps are provided for a one-week period forward and one-week period backward starting from the day prior to the query time, covering the U.S. equity market, Korean equity market and the commodity market. - Session types per market: - - U.S. equity market: "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", "NO_TRADING". - - Commodity market: "REGULAR", "NO_TRADING". - - Korean equity market: "REGULAR", "NO_TRADING". + Session types per market: + - U.S. equity market: "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", "NO_TRADING". + - Commodity market: "REGULAR", "NO_TRADING". + - Korean equity market: "REGULAR", "NO_TRADING". - Weight: 5 + Weight: 5 Args: diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/trade_api.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/trade_api.py index 13794a68..004fb7ab 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/trade_api.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/api/trade_api.py @@ -731,7 +731,11 @@ def change_position_mode( POST /fapi/v1/positionSide/dual https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api/Change-Position-Mode - Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol*** + Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol***. + + **After CM migration**, UM and CM share the **same** `dualSidePosition` setting. Calling this endpoint flips both UM and CM at once. If either side has any open order or open position, the change is rejected: + - `-4067` (open orders exist) + - `-4068` (open position exists) Weight: 1 @@ -1183,7 +1187,6 @@ def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue - * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. * Both `quantity` and `price` must be sent, which is different from dapi modify order endpoint. * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/__init__.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/__init__.py index baa7f003..dc8a1dfd 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/__init__.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/__init__.py @@ -41,6 +41,12 @@ from .adl_risk_response2_inner import AdlRiskResponse2Inner as AdlRiskResponse2Inner from .all_orders_response import AllOrdersResponse as AllOrdersResponse from .all_orders_response_inner import AllOrdersResponseInner as AllOrdersResponseInner +from .asset_index_response import AssetIndexResponse as AssetIndexResponse +from .asset_index_response1 import AssetIndexResponse1 as AssetIndexResponse1 +from .asset_index_response2 import AssetIndexResponse2 as AssetIndexResponse2 +from .asset_index_response2_inner import ( + AssetIndexResponse2Inner as AssetIndexResponse2Inner, +) from .auto_cancel_all_open_orders_response import ( AutoCancelAllOpenOrdersResponse as AutoCancelAllOpenOrdersResponse, ) @@ -253,18 +259,6 @@ ModifyMultipleOrdersResponseInner as ModifyMultipleOrdersResponseInner, ) from .modify_order_response import ModifyOrderResponse as ModifyOrderResponse -from .multi_assets_mode_asset_index_response import ( - MultiAssetsModeAssetIndexResponse as MultiAssetsModeAssetIndexResponse, -) -from .multi_assets_mode_asset_index_response1 import ( - MultiAssetsModeAssetIndexResponse1 as MultiAssetsModeAssetIndexResponse1, -) -from .multi_assets_mode_asset_index_response2 import ( - MultiAssetsModeAssetIndexResponse2 as MultiAssetsModeAssetIndexResponse2, -) -from .multi_assets_mode_asset_index_response2_inner import ( - MultiAssetsModeAssetIndexResponse2Inner as MultiAssetsModeAssetIndexResponse2Inner, -) from .new_algo_order_response import NewAlgoOrderResponse as NewAlgoOrderResponse from .new_order_response import NewOrderResponse as NewOrderResponse from .notional_and_leverage_brackets_response import ( diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response.py similarity index 62% rename from clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response.py rename to clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response.py index a55280dd..9d2b0185 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response.py @@ -20,39 +20,31 @@ ValidationError, ) from typing import Any, Optional -from binance_sdk_derivatives_trading_usds_futures.rest_api.models.multi_assets_mode_asset_index_response1 import ( - MultiAssetsModeAssetIndexResponse1, +from binance_sdk_derivatives_trading_usds_futures.rest_api.models.asset_index_response1 import ( + AssetIndexResponse1, ) -from binance_sdk_derivatives_trading_usds_futures.rest_api.models.multi_assets_mode_asset_index_response2 import ( - MultiAssetsModeAssetIndexResponse2, +from binance_sdk_derivatives_trading_usds_futures.rest_api.models.asset_index_response2 import ( + AssetIndexResponse2, ) from typing import Union, Set, Dict from typing_extensions import Self -MULTIASSETSMODEASSETINDEXRESPONSE_ONE_OF_SCHEMAS = [ - "MultiAssetsModeAssetIndexResponse1", - "MultiAssetsModeAssetIndexResponse2", -] +ASSETINDEXRESPONSE_ONE_OF_SCHEMAS = ["AssetIndexResponse1", "AssetIndexResponse2"] -class MultiAssetsModeAssetIndexResponse(BaseModel): +class AssetIndexResponse(BaseModel): """ - MultiAssetsModeAssetIndexResponse + AssetIndexResponse """ - # data type: MultiAssetsModeAssetIndexResponse1 - oneof_schema_1_validator: Optional[MultiAssetsModeAssetIndexResponse1] = None - # data type: MultiAssetsModeAssetIndexResponse2 - oneof_schema_2_validator: Optional[MultiAssetsModeAssetIndexResponse2] = None - actual_instance: Optional[ - Union[ - MultiAssetsModeAssetIndexResponse1, list[MultiAssetsModeAssetIndexResponse2] - ] - ] = None - one_of_schemas: Set[str] = { - "MultiAssetsModeAssetIndexResponse1", - "MultiAssetsModeAssetIndexResponse2", - } + # data type: AssetIndexResponse1 + oneof_schema_1_validator: Optional[AssetIndexResponse1] = None + # data type: AssetIndexResponse2 + oneof_schema_2_validator: Optional[AssetIndexResponse2] = None + actual_instance: Optional[Union[AssetIndexResponse1, list[AssetIndexResponse2]]] = ( + None + ) + one_of_schemas: Set[str] = {"AssetIndexResponse1", "AssetIndexResponse2"} model_config = ConfigDict( validate_assignment=True, @@ -86,21 +78,17 @@ def from_dict(cls, parsed) -> Self: is_list = isinstance(parsed, list) - # deserialize data into MultiAssetsModeAssetIndexResponse1 - if is_list == MultiAssetsModeAssetIndexResponse1.is_array(): + # deserialize data into AssetIndexResponse1 + if is_list == AssetIndexResponse1.is_array(): try: - instance.actual_instance = MultiAssetsModeAssetIndexResponse1.from_dict( - parsed - ) + instance.actual_instance = AssetIndexResponse1.from_dict(parsed) match += 1 except (ValidationError, ValueError) as e: error_messages.append(str(e)) - # deserialize data into MultiAssetsModeAssetIndexResponse2 - if is_list == MultiAssetsModeAssetIndexResponse2.is_array(): + # deserialize data into AssetIndexResponse2 + if is_list == AssetIndexResponse2.is_array(): try: - instance.actual_instance = MultiAssetsModeAssetIndexResponse2.from_dict( - parsed - ) + instance.actual_instance = AssetIndexResponse2.from_dict(parsed) match += 1 except (ValidationError, ValueError) as e: error_messages.append(str(e)) @@ -108,13 +96,13 @@ def from_dict(cls, parsed) -> Self: if match > 1: # more than 1 match raise ValueError( - "Multiple matches found when deserializing the JSON string into MultiAssetsModeAssetIndexResponse with oneOf schemas: MultiAssetsModeAssetIndexResponse1, MultiAssetsModeAssetIndexResponse2. Details: " + "Multiple matches found when deserializing the JSON string into AssetIndexResponse with oneOf schemas: AssetIndexResponse1, AssetIndexResponse2. Details: " + ", ".join(error_messages) ) elif match == 0: # no match raise ValueError( - "No match found when deserializing the JSON string into MultiAssetsModeAssetIndexResponse with oneOf schemas: MultiAssetsModeAssetIndexResponse1, MultiAssetsModeAssetIndexResponse2. Details: " + "No match found when deserializing the JSON string into AssetIndexResponse with oneOf schemas: AssetIndexResponse1, AssetIndexResponse2. Details: " + ", ".join(error_messages) ) else: @@ -134,13 +122,7 @@ def to_json(self) -> str: def to_dict( self, - ) -> Optional[ - Union[ - Dict[str, Any], - MultiAssetsModeAssetIndexResponse1, - MultiAssetsModeAssetIndexResponse2, - ] - ]: + ) -> Optional[Union[Dict[str, Any], AssetIndexResponse1, AssetIndexResponse2]]: """Returns the dict representation of the actual instance""" if self.actual_instance is None: return None diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response1.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response1.py similarity index 94% rename from clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response1.py rename to clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response1.py index d3cf87d9..fddd5aee 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response1.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response1.py @@ -22,9 +22,9 @@ from typing_extensions import Self -class MultiAssetsModeAssetIndexResponse1(BaseModel): +class AssetIndexResponse1(BaseModel): """ - MultiAssetsModeAssetIndexResponse1 + AssetIndexResponse1 """ # noqa: E501 symbol: Optional[StrictStr] = None @@ -82,7 +82,7 @@ def is_array(cls) -> bool: @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponse1 from a JSON string""" + """Create an instance of AssetIndexResponse1 from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: @@ -116,7 +116,7 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponse1 from a dict""" + """Create an instance of AssetIndexResponse1 from a dict""" if obj is None: return None diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response2.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response2.py similarity index 87% rename from clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response2.py rename to clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response2.py index 4ac4cc55..945e5299 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response2.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response2.py @@ -18,16 +18,16 @@ from pydantic import ConfigDict from typing import Any, ClassVar, Dict -from binance_sdk_derivatives_trading_usds_futures.rest_api.models.multi_assets_mode_asset_index_response2_inner import ( - MultiAssetsModeAssetIndexResponse2Inner, +from binance_sdk_derivatives_trading_usds_futures.rest_api.models.asset_index_response2_inner import ( + AssetIndexResponse2Inner, ) from typing import Optional, Set, List from typing_extensions import Self -class MultiAssetsModeAssetIndexResponse2(MultiAssetsModeAssetIndexResponse2Inner): +class AssetIndexResponse2(AssetIndexResponse2Inner): """ - MultiAssetsModeAssetIndexResponse2 + AssetIndexResponse2 """ # noqa: E501 __properties: ClassVar[List[str]] = [] @@ -53,7 +53,7 @@ def is_array(cls) -> bool: @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponse2 from a JSON string""" + """Create an instance of AssetIndexResponse2 from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response2_inner.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response2_inner.py similarity index 94% rename from clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response2_inner.py rename to clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response2_inner.py index 51d423ef..491df8dd 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/multi_assets_mode_asset_index_response2_inner.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/models/asset_index_response2_inner.py @@ -22,9 +22,9 @@ from typing_extensions import Self -class MultiAssetsModeAssetIndexResponse2Inner(BaseModel): +class AssetIndexResponse2Inner(BaseModel): """ - MultiAssetsModeAssetIndexResponse2Inner + AssetIndexResponse2Inner """ # noqa: E501 symbol: Optional[StrictStr] = None @@ -82,7 +82,7 @@ def is_array(cls) -> bool: @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponse2Inner from a JSON string""" + """Create an instance of AssetIndexResponse2Inner from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: @@ -116,7 +116,7 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponse2Inner from a dict""" + """Create an instance of AssetIndexResponse2Inner from a dict""" if obj is None: return None diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/rest_api.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/rest_api.py index 8b1280d1..03255896 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/rest_api.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/rest_api/rest_api.py @@ -47,6 +47,7 @@ from .models import OrderStatusResponse from .models import SendQuoteRequestResponse from .models import AdlRiskResponse +from .models import AssetIndexResponse from .models import BasisResponse from .models import CheckServerTimeResponse from .models import CompositeIndexSymbolInformationResponse @@ -60,7 +61,6 @@ from .models import LongShortRatioResponse from .models import MarkPriceResponse from .models import MarkPriceKlineCandlestickDataResponse -from .models import MultiAssetsModeAssetIndexResponse from .models import OldTradesLookupResponse from .models import OpenInterestResponse from .models import OpenInterestStatisticsResponse @@ -978,6 +978,30 @@ def adl_risk( return self._marketDataApi.adl_risk(symbol) + def asset_index( + self, + symbol: Optional[str] = None, + ) -> ApiResponse[AssetIndexResponse]: + """ + Asset Index + + Asset index price. + + Weight: 1 for a single symbol; 10 when the symbol parameter is omitted + + Args: + symbol (Optional[str] = None): + + Returns: + ApiResponse[AssetIndexResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.asset_index(symbol) + def basis( self, pair: Union[str, None], @@ -998,7 +1022,7 @@ def basis( Weight: 0 Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. contract_type (Union[BasisContractTypeEnum, None]): period (Union[BasisPeriodEnum, None]): "5m","15m","30m","1h","2h","4h","6h","12h","1d" limit (Optional[int] = None): Default 100; max 1000 @@ -1140,7 +1164,7 @@ def continuous_contract_kline_candlestick_data( | > 1000 | 10 | Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. contract_type (Union[ContinuousContractKlineCandlestickDataContractTypeEnum, None]): interval (Union[ContinuousContractKlineCandlestickDataIntervalEnum, None]): start_time (Optional[int] = None): @@ -1255,7 +1279,6 @@ def index_price_kline_candlestick_data( Kline/candlestick bars for the index price of a pair. Klines are uniquely identified by their open time. - * If startTime and endTime are not sent, the most recent klines are returned. Weight: based on parameter LIMIT @@ -1267,7 +1290,7 @@ def index_price_kline_candlestick_data( | > 1000 | 10 | Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. interval (Union[IndexPriceKlineCandlestickDataIntervalEnum, None]): start_time (Optional[int] = None): end_time (Optional[int] = None): @@ -1433,30 +1456,6 @@ def mark_price_kline_candlestick_data( symbol, interval, start_time, end_time, limit ) - def multi_assets_mode_asset_index( - self, - symbol: Optional[str] = None, - ) -> ApiResponse[MultiAssetsModeAssetIndexResponse]: - """ - Multi-Assets Mode Asset Index - - asset index for Multi-Assets mode - - Weight: 1 for a single symbol; 10 when the symbol parameter is omitted - - Args: - symbol (Optional[str] = None): - - Returns: - ApiResponse[MultiAssetsModeAssetIndexResponse] - - Raises: - RequiredError: If a required parameter is missing. - - """ - - return self._marketDataApi.multi_assets_mode_asset_index(symbol) - def old_trades_lookup( self, symbol: Union[str, None], @@ -1639,7 +1638,7 @@ def quarterly_contract_settlement_price( Weight: 0 Args: - pair (Union[str, None]): + pair (Union[str, None]): After CM migration, accepts both UM and CM pair values. Returns: ApiResponse[QuarterlyContractSettlementPriceResponse] @@ -2025,12 +2024,12 @@ def trading_schedule( Trading session schedules for the underlying assets of TradFi Perps are provided for a one-week period forward and one-week period backward starting from the day prior to the query time, covering the U.S. equity market, Korean equity market and the commodity market. - Session types per market: - - U.S. equity market: "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", "NO_TRADING". - - Commodity market: "REGULAR", "NO_TRADING". - - Korean equity market: "REGULAR", "NO_TRADING". + Session types per market: + - U.S. equity market: "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", "NO_TRADING". + - Commodity market: "REGULAR", "NO_TRADING". + - Korean equity market: "REGULAR", "NO_TRADING". - Weight: 5 + Weight: 5 Args: @@ -2439,7 +2438,11 @@ def change_position_mode( """ Change Position Mode(TRADE) - Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol*** + Change user's position mode (Hedge Mode or One-way Mode ) on ***EVERY symbol***. + + **After CM migration**, UM and CM share the **same** `dualSidePosition` setting. Calling this endpoint flips both UM and CM at once. If either side has any open order or open position, the change is rejected: + - `-4067` (open orders exist) + - `-4068` (open position exists) Weight: 1 @@ -2717,7 +2720,6 @@ def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue - * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. * Both `quantity` and `price` must be sent, which is different from dapi modify order endpoint. * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/api/trade_api.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/api/trade_api.py index 9cfc90ab..5e5b757f 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/api/trade_api.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/api/trade_api.py @@ -183,7 +183,7 @@ async def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. - * Both `quantity` and `price` must be sent, which is different from dapi modify order endpoint. + * Both `quantity` and `price` must be sent. *(After CM migration, the dapi modify order endpoint follows the same rule.)* * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. * However the order will be cancelled by the amendment in the following situations: * when the order is in partially filled status and the new `quantity` <= `executedQty` diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/websocket_api.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/websocket_api.py index 5f1bc289..b95e9d52 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/websocket_api.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_api/websocket_api.py @@ -461,7 +461,7 @@ async def modify_order( Order modify function, currently only LIMIT order modification is supported, modified orders will be reordered in the match queue * Either `orderId` or `origClientOrderId` must be sent, and the `orderId` will prevail if both are sent. - * Both `quantity` and `price` must be sent, which is different from dapi modify order endpoint. + * Both `quantity` and `price` must be sent. *(After CM migration, the dapi modify order endpoint follows the same rule.)* * When the new `quantity` or `price` doesn't satisfy PRICE_FILTER / PERCENT_FILTER / LOT_SIZE, amendment will be rejected and the order will stay as it is. * However the order will be cancelled by the amendment in the following situations: * when the order is in partially filled status and the new `quantity` <= `executedQty` diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/__init__.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/__init__.py index 423c1686..0d9776f2 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/__init__.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/__init__.py @@ -41,6 +41,10 @@ from .all_market_tickers_streams_response_inner import ( AllMarketTickersStreamsResponseInner as AllMarketTickersStreamsResponseInner, ) +from .asset_index_response import AssetIndexResponse as AssetIndexResponse +from .asset_index_response_inner import ( + AssetIndexResponseInner as AssetIndexResponseInner, +) from .composite_index_symbol_information_streams_response import ( CompositeIndexSymbolInformationStreamsResponse as CompositeIndexSymbolInformationStreamsResponse, ) @@ -106,12 +110,6 @@ from .mark_price_stream_response import ( MarkPriceStreamResponse as MarkPriceStreamResponse, ) -from .multi_assets_mode_asset_index_response import ( - MultiAssetsModeAssetIndexResponse as MultiAssetsModeAssetIndexResponse, -) -from .multi_assets_mode_asset_index_response_inner import ( - MultiAssetsModeAssetIndexResponseInner as MultiAssetsModeAssetIndexResponseInner, -) from .order_trade_update import OrderTradeUpdate as OrderTradeUpdate from .order_trade_update_o import OrderTradeUpdateO as OrderTradeUpdateO from .partial_book_depth_streams_response import ( diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/aggregate_trade_streams_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/aggregate_trade_streams_response.py index 728d2c7a..68160fce 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/aggregate_trade_streams_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/aggregate_trade_streams_response.py @@ -38,6 +38,7 @@ class AggregateTradeStreamsResponse(BaseModel): l: Optional[StrictInt] = None T: Optional[StrictInt] = Field(default=None, alias="T") m: Optional[StrictBool] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -51,6 +52,7 @@ class AggregateTradeStreamsResponse(BaseModel): "l", "T", "m", + "st", ] model_config = ConfigDict( @@ -124,6 +126,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "l": obj.get("l"), "T": obj.get("T"), "m": obj.get("m"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_book_tickers_stream_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_book_tickers_stream_response.py index 949cbdd8..4b4e30bd 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_book_tickers_stream_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_book_tickers_stream_response.py @@ -36,8 +36,22 @@ class AllBookTickersStreamResponse(BaseModel): B: Optional[StrictStr] = Field(default=None, alias="B") a: Optional[StrictStr] = None A: Optional[StrictStr] = Field(default=None, alias="A") + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "u", "E", "T", "s", "b", "B", "a", "A"] + __properties: ClassVar[List[str]] = [ + "e", + "u", + "E", + "T", + "s", + "b", + "B", + "a", + "A", + "ps", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -108,6 +122,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "B": obj.get("B"), "a": obj.get("a"), "A": obj.get("A"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py index 023aa123..d45066be 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_liquidation_order_streams_response.py @@ -33,8 +33,10 @@ class AllMarketLiquidationOrderStreamsResponse(BaseModel): e: Optional[StrictStr] = None E: Optional[StrictInt] = Field(default=None, alias="E") o: Optional[AllMarketLiquidationOrderStreamsResponseO] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "o"] + __properties: ClassVar[List[str]] = ["e", "E", "o", "ps", "st"] model_config = ConfigDict( populate_by_name=True, @@ -106,6 +108,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("o") is not None else None ), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py index d2213e86..eb746daa 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_mini_tickers_stream_response_inner.py @@ -36,8 +36,22 @@ class AllMarketMiniTickersStreamResponseInner(BaseModel): l: Optional[StrictStr] = None v: Optional[StrictStr] = None q: Optional[StrictStr] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "s", "c", "o", "h", "l", "v", "q"] + __properties: ClassVar[List[str]] = [ + "e", + "E", + "s", + "c", + "o", + "h", + "l", + "v", + "q", + "ps", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -108,6 +122,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "l": obj.get("l"), "v": obj.get("v"), "q": obj.get("q"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py index f6bf396f..032345b8 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/all_market_tickers_streams_response_inner.py @@ -45,6 +45,8 @@ class AllMarketTickersStreamsResponseInner(BaseModel): F: Optional[StrictInt] = Field(default=None, alias="F") L: Optional[StrictInt] = Field(default=None, alias="L") n: Optional[StrictInt] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -65,6 +67,8 @@ class AllMarketTickersStreamsResponseInner(BaseModel): "F", "L", "n", + "ps", + "st", ] model_config = ConfigDict( @@ -145,6 +149,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "F": obj.get("F"), "L": obj.get("L"), "n": obj.get("n"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/multi_assets_mode_asset_index_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/asset_index_response.py similarity index 85% rename from clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/multi_assets_mode_asset_index_response.py rename to clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/asset_index_response.py index fade6c36..5608a6f7 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/multi_assets_mode_asset_index_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/asset_index_response.py @@ -18,16 +18,16 @@ from pydantic import ConfigDict from typing import Any, ClassVar, Dict -from binance_sdk_derivatives_trading_usds_futures.websocket_streams.models.multi_assets_mode_asset_index_response_inner import ( - MultiAssetsModeAssetIndexResponseInner, +from binance_sdk_derivatives_trading_usds_futures.websocket_streams.models.asset_index_response_inner import ( + AssetIndexResponseInner, ) from typing import Optional, Set, List from typing_extensions import Self -class MultiAssetsModeAssetIndexResponse(MultiAssetsModeAssetIndexResponseInner): +class AssetIndexResponse(AssetIndexResponseInner): """ - MultiAssetsModeAssetIndexResponse + AssetIndexResponse """ # noqa: E501 __properties: ClassVar[List[str]] = [] @@ -49,7 +49,7 @@ def to_json(self) -> str: @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponse from a JSON string""" + """Create an instance of AssetIndexResponse from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: @@ -73,7 +73,7 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponse from a dict""" + """Create an instance of AssetIndexResponse from a dict""" if obj is None: return None diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/multi_assets_mode_asset_index_response_inner.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/asset_index_response_inner.py similarity index 93% rename from clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/multi_assets_mode_asset_index_response_inner.py rename to clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/asset_index_response_inner.py index 948ad409..983af571 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/multi_assets_mode_asset_index_response_inner.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/asset_index_response_inner.py @@ -22,9 +22,9 @@ from typing_extensions import Self -class MultiAssetsModeAssetIndexResponseInner(BaseModel): +class AssetIndexResponseInner(BaseModel): """ - MultiAssetsModeAssetIndexResponseInner + AssetIndexResponseInner """ # noqa: E501 e: Optional[StrictStr] = None @@ -72,7 +72,7 @@ def to_json(self) -> str: @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponseInner from a JSON string""" + """Create an instance of AssetIndexResponseInner from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: @@ -106,7 +106,7 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of MultiAssetsModeAssetIndexResponseInner from a dict""" + """Create an instance of AssetIndexResponseInner from a dict""" if obj is None: return None diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/contract_info_stream_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/contract_info_stream_response.py index 30f2ce1d..9b8380b9 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/contract_info_stream_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/contract_info_stream_response.py @@ -33,23 +33,23 @@ class ContractInfoStreamResponse(BaseModel): e: Optional[StrictStr] = None E: Optional[StrictInt] = Field(default=None, alias="E") s: Optional[StrictStr] = None - ps: Optional[StrictStr] = None ct: Optional[StrictStr] = None dt: Optional[StrictInt] = None ot: Optional[StrictInt] = None cs: Optional[StrictStr] = None bks: Optional[List[ContractInfoStreamResponseBksInner]] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", "E", "s", - "ps", "ct", "dt", "ot", "cs", "bks", + "st", ] model_config = ConfigDict( @@ -122,7 +122,6 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "e": obj.get("e"), "E": obj.get("E"), "s": obj.get("s"), - "ps": obj.get("ps"), "ct": obj.get("ct"), "dt": obj.get("dt"), "ot": obj.get("ot"), @@ -135,6 +134,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("bks") is not None else None ), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/diff_book_depth_streams_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/diff_book_depth_streams_response.py index 7775c9d8..b6aec718 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/diff_book_depth_streams_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/diff_book_depth_streams_response.py @@ -42,8 +42,22 @@ class DiffBookDepthStreamsResponse(BaseModel): pu: Optional[StrictInt] = None b: Optional[List[DiffBookDepthStreamsResponseBItem]] = None a: Optional[List[DiffBookDepthStreamsResponseAItem]] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "T", "s", "U", "u", "pu", "b", "a"] + __properties: ClassVar[List[str]] = [ + "e", + "E", + "T", + "s", + "U", + "u", + "pu", + "b", + "a", + "ps", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -142,6 +156,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("a") is not None else None ), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py index 4ddc5708..a9365b57 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_book_ticker_streams_response.py @@ -29,15 +29,29 @@ class IndividualSymbolBookTickerStreamsResponse(BaseModel): e: Optional[StrictStr] = None u: Optional[StrictInt] = None + s: Optional[StrictStr] = None + ps: Optional[StrictStr] = None E: Optional[StrictInt] = Field(default=None, alias="E") T: Optional[StrictInt] = Field(default=None, alias="T") - s: Optional[StrictStr] = None b: Optional[StrictStr] = None B: Optional[StrictStr] = Field(default=None, alias="B") a: Optional[StrictStr] = None A: Optional[StrictStr] = Field(default=None, alias="A") + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "u", "E", "T", "s", "b", "B", "a", "A"] + __properties: ClassVar[List[str]] = [ + "e", + "u", + "s", + "ps", + "E", + "T", + "b", + "B", + "a", + "A", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -101,13 +115,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: { "e": obj.get("e"), "u": obj.get("u"), + "s": obj.get("s"), + "ps": obj.get("ps"), "E": obj.get("E"), "T": obj.get("T"), - "s": obj.get("s"), "b": obj.get("b"), "B": obj.get("B"), "a": obj.get("a"), "A": obj.get("A"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py index e71c0a9a..02f1b004 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_mini_ticker_stream_response.py @@ -36,8 +36,22 @@ class IndividualSymbolMiniTickerStreamResponse(BaseModel): l: Optional[StrictStr] = None v: Optional[StrictStr] = None q: Optional[StrictStr] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "s", "c", "o", "h", "l", "v", "q"] + __properties: ClassVar[List[str]] = [ + "e", + "E", + "s", + "c", + "o", + "h", + "l", + "v", + "q", + "ps", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -108,6 +122,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "l": obj.get("l"), "v": obj.get("v"), "q": obj.get("q"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py index aff0f9c7..c09d3c03 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/individual_symbol_ticker_streams_response.py @@ -45,6 +45,8 @@ class IndividualSymbolTickerStreamsResponse(BaseModel): F: Optional[StrictInt] = Field(default=None, alias="F") L: Optional[StrictInt] = Field(default=None, alias="L") n: Optional[StrictInt] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = [ "e", @@ -65,6 +67,8 @@ class IndividualSymbolTickerStreamsResponse(BaseModel): "F", "L", "n", + "ps", + "st", ] model_config = ConfigDict( @@ -145,6 +149,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "F": obj.get("F"), "L": obj.get("L"), "n": obj.get("n"), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_for_all_market_response_inner.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_for_all_market_response_inner.py index 1158d102..ec15251f 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_for_all_market_response_inner.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_for_all_market_response_inner.py @@ -36,8 +36,20 @@ class MarkPriceStreamForAllMarketResponseInner(BaseModel): P: Optional[StrictStr] = Field(default=None, alias="P") r: Optional[StrictStr] = None T: Optional[StrictInt] = Field(default=None, alias="T") + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "s", "p", "ap", "i", "P", "r", "T"] + __properties: ClassVar[List[str]] = [ + "e", + "E", + "s", + "p", + "ap", + "i", + "P", + "r", + "T", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -108,6 +120,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "P": obj.get("P"), "r": obj.get("r"), "T": obj.get("T"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_response.py index bf728e5d..4e1b63d9 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/mark_price_stream_response.py @@ -36,8 +36,20 @@ class MarkPriceStreamResponse(BaseModel): P: Optional[StrictStr] = Field(default=None, alias="P") r: Optional[StrictStr] = None T: Optional[StrictInt] = Field(default=None, alias="T") + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "s", "p", "ap", "i", "P", "r", "T"] + __properties: ClassVar[List[str]] = [ + "e", + "E", + "s", + "p", + "ap", + "i", + "P", + "r", + "T", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -108,6 +120,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "P": obj.get("P"), "r": obj.get("r"), "T": obj.get("T"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/partial_book_depth_streams_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/partial_book_depth_streams_response.py index 425e879e..2f34ad64 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/partial_book_depth_streams_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/partial_book_depth_streams_response.py @@ -42,8 +42,22 @@ class PartialBookDepthStreamsResponse(BaseModel): pu: Optional[StrictInt] = None b: Optional[List[PartialBookDepthStreamsResponseBItem]] = None a: Optional[List[PartialBookDepthStreamsResponseAItem]] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "T", "s", "U", "u", "pu", "b", "a"] + __properties: ClassVar[List[str]] = [ + "e", + "E", + "T", + "s", + "U", + "u", + "pu", + "b", + "a", + "ps", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -142,6 +156,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("a") is not None else None ), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/rpi_diff_book_depth_streams_response.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/rpi_diff_book_depth_streams_response.py index 7b447827..e0b3b64a 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/rpi_diff_book_depth_streams_response.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/models/rpi_diff_book_depth_streams_response.py @@ -42,8 +42,22 @@ class RpiDiffBookDepthStreamsResponse(BaseModel): pu: Optional[StrictInt] = None b: Optional[List[RpiDiffBookDepthStreamsResponseBItem]] = None a: Optional[List[RpiDiffBookDepthStreamsResponseAItem]] = None + ps: Optional[StrictStr] = None + st: Optional[StrictInt] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["e", "E", "T", "s", "U", "u", "pu", "b", "a"] + __properties: ClassVar[List[str]] = [ + "e", + "E", + "T", + "s", + "U", + "u", + "pu", + "b", + "a", + "ps", + "st", + ] model_config = ConfigDict( populate_by_name=True, @@ -142,6 +156,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("a") is not None else None ), + "ps": obj.get("ps"), + "st": obj.get("st"), } ) # store additional fields in additional_properties diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/streams/market_api.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/streams/market_api.py index 0a4714f4..877a7a97 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/streams/market_api.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/streams/market_api.py @@ -20,6 +20,7 @@ from ..models import AllMarketLiquidationOrderStreamsResponse from ..models import AllMarketMiniTickersStreamResponse from ..models import AllMarketTickersStreamsResponse +from ..models import AssetIndexResponse from ..models import CompositeIndexSymbolInformationStreamsResponse from ..models import ContinuousContractKlineCandlestickStreamsResponse from ..models import ContractInfoStreamResponse @@ -29,7 +30,6 @@ from ..models import LiquidationOrderStreamsResponse from ..models import MarkPriceStreamResponse from ..models import MarkPriceStreamForAllMarketResponse -from ..models import MultiAssetsModeAssetIndexResponse from ..models import TradingSessionStreamResponse @@ -205,6 +205,44 @@ async def all_market_tickers_streams( stream_url="market", ) + async def asset_index( + self, + id: Optional[str] = None, + ) -> RequestStreamHandle: + r""" + Asset Index + /!assetIndex@arr + https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Asset-Index + + Asset index price. + + Update Speed: 1s + + Args: + id (Optional[str] = None): Unique WebSocket request ID. + + Returns: + RequestStreamHandle + + Raises: + RequiredError: If a required parameter is missing. + + """ + + stream = ws_streams_placeholder( + "/!assetIndex@arr".replace("/", "", 1), + { + "id": id, + }, + ) + + return await RequestStream( + self.websocket_base, + stream=stream, + response_model=AssetIndexResponse, + stream_url="market", + ) + async def composite_index_symbol_information_streams( self, symbol: Union[str, None], @@ -635,44 +673,6 @@ async def mark_price_stream_for_all_market( stream_url="market", ) - async def multi_assets_mode_asset_index( - self, - id: Optional[str] = None, - ) -> RequestStreamHandle: - r""" - Multi-Assets Mode Asset Index - /!assetIndex@arr - https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Multi-Assets-Mode-Asset-Index - - Asset index for multi-assets mode user - - Update Speed: 1s - - Args: - id (Optional[str] = None): Unique WebSocket request ID. - - Returns: - RequestStreamHandle - - Raises: - RequiredError: If a required parameter is missing. - - """ - - stream = ws_streams_placeholder( - "/!assetIndex@arr".replace("/", "", 1), - { - "id": id, - }, - ) - - return await RequestStream( - self.websocket_base, - stream=stream, - response_model=MultiAssetsModeAssetIndexResponse, - stream_url="market", - ) - async def trading_session_stream( self, id: Optional[str] = None, @@ -684,13 +684,13 @@ async def trading_session_stream( Trading session information for the underlying assets of TradFi Perpetual contracts, covering the U.S. equity market, Korean equity market, and the commodity market, is updated every second. Trading session information for different underlying markets is pushed in separate messages. - **Event type:** + **Event type:** - - `EquityUpdate`: Session types for the U.S. equity market include "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", and "NO_TRADING". - - `CommodityUpdate`: Session types for the commodity market include "REGULAR" and "NO_TRADING". - - `KR_EquityUpdate`: Session types for the Korean equity market include "REGULAR" and "NO_TRADING". + - `EquityUpdate`: Session types for the U.S. equity market include "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", and "NO_TRADING". + - `CommodityUpdate`: Session types for the commodity market include "REGULAR" and "NO_TRADING". + - `KR_EquityUpdate`: Session types for the Korean equity market include "REGULAR" and "NO_TRADING". - Update Speed: 1s + Update Speed: 1s Args: id (Optional[str] = None): Unique WebSocket request ID. diff --git a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/websocket_streams.py b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/websocket_streams.py index d2d6bc1b..5ed77ea1 100644 --- a/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/websocket_streams.py +++ b/clients/derivatives_trading_usds_futures/src/binance_sdk_derivatives_trading_usds_futures/websocket_streams/websocket_streams.py @@ -227,6 +227,30 @@ async def all_market_tickers_streams( return await self._marketApi.all_market_tickers_streams(id) + async def asset_index( + self, + id: Optional[str] = None, + ) -> RequestStreamHandle: + r""" + Asset Index + + Asset index price. + + Update Speed: 1s + + Args: + id (Optional[str] = None): Unique WebSocket request ID. + + Returns: + RequestStreamHandle + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return await self._marketApi.asset_index(id) + async def composite_index_symbol_information_streams( self, symbol: Union[str, None], @@ -475,30 +499,6 @@ async def mark_price_stream_for_all_market( return await self._marketApi.mark_price_stream_for_all_market(id, update_speed) - async def multi_assets_mode_asset_index( - self, - id: Optional[str] = None, - ) -> RequestStreamHandle: - r""" - Multi-Assets Mode Asset Index - - Asset index for multi-assets mode user - - Update Speed: 1s - - Args: - id (Optional[str] = None): Unique WebSocket request ID. - - Returns: - RequestStreamHandle - - Raises: - RequiredError: If a required parameter is missing. - - """ - - return await self._marketApi.multi_assets_mode_asset_index(id) - async def trading_session_stream( self, id: Optional[str] = None, @@ -508,13 +508,13 @@ async def trading_session_stream( Trading session information for the underlying assets of TradFi Perpetual contracts, covering the U.S. equity market, Korean equity market, and the commodity market, is updated every second. Trading session information for different underlying markets is pushed in separate messages. - **Event type:** + **Event type:** - - `EquityUpdate`: Session types for the U.S. equity market include "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", and "NO_TRADING". - - `CommodityUpdate`: Session types for the commodity market include "REGULAR" and "NO_TRADING". - - `KR_EquityUpdate`: Session types for the Korean equity market include "REGULAR" and "NO_TRADING". + - `EquityUpdate`: Session types for the U.S. equity market include "PRE_MARKET", "REGULAR", "AFTER_MARKET", "OVERNIGHT", and "NO_TRADING". + - `CommodityUpdate`: Session types for the commodity market include "REGULAR" and "NO_TRADING". + - `KR_EquityUpdate`: Session types for the Korean equity market include "REGULAR" and "NO_TRADING". - Update Speed: 1s + Update Speed: 1s Args: id (Optional[str] = None): Unique WebSocket request ID. diff --git a/clients/derivatives_trading_usds_futures/tests/unit/rest_api/test_market_data_api.py b/clients/derivatives_trading_usds_futures/tests/unit/rest_api/test_market_data_api.py index ada592fe..7929f8cf 100644 --- a/clients/derivatives_trading_usds_futures/tests/unit/rest_api/test_market_data_api.py +++ b/clients/derivatives_trading_usds_futures/tests/unit/rest_api/test_market_data_api.py @@ -21,6 +21,9 @@ from binance_sdk_derivatives_trading_usds_futures.rest_api.api import MarketDataApi from binance_sdk_derivatives_trading_usds_futures.rest_api.models import AdlRiskResponse +from binance_sdk_derivatives_trading_usds_futures.rest_api.models import ( + AssetIndexResponse, +) from binance_sdk_derivatives_trading_usds_futures.rest_api.models import BasisResponse from binance_sdk_derivatives_trading_usds_futures.rest_api.models import ( CheckServerTimeResponse, @@ -58,9 +61,6 @@ from binance_sdk_derivatives_trading_usds_futures.rest_api.models import ( MarkPriceKlineCandlestickDataResponse, ) -from binance_sdk_derivatives_trading_usds_futures.rest_api.models import ( - MultiAssetsModeAssetIndexResponse, -) from binance_sdk_derivatives_trading_usds_futures.rest_api.models import ( OldTradesLookupResponse, ) @@ -271,6 +271,112 @@ def test_adl_risk_server_error(self): with pytest.raises(Exception, match="ResponseError"): self.client.adl_risk() + def test_asset_index_success(self): + """Test asset_index() successfully with required parameters only.""" + + expected_response = { + "symbol": "ADAUSD", + "time": 1635740268004, + "index": "1.92957370", + "bidBuffer": "0.10000000", + "askBuffer": "0.10000000", + "bidRate": "1.73661633", + "askRate": "2.12253107", + "autoExchangeBidBuffer": "0.05000000", + "autoExchangeAskBuffer": "0.05000000", + "autoExchangeBidRate": "1.83309501", + "autoExchangeAskRate": "2.02605238", + } + + self.set_mock_response(expected_response) + + response = self.client.asset_index() + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + self.mock_session.request.assert_called_once() + + assert "url" in request_kwargs + assert "/fapi/v1/assetIndex" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(AssetIndexResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(AssetIndexResponse, "from_dict"): + expected = AssetIndexResponse.from_dict(expected_response) + else: + expected = AssetIndexResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_asset_index_success_with_optional_params(self): + """Test asset_index() successfully with optional parameters.""" + + params = {"symbol": "symbol_example"} + + expected_response = { + "symbol": "ADAUSD", + "time": 1635740268004, + "index": "1.92957370", + "bidBuffer": "0.10000000", + "askBuffer": "0.10000000", + "bidRate": "1.73661633", + "askRate": "2.12253107", + "autoExchangeBidBuffer": "0.05000000", + "autoExchangeAskBuffer": "0.05000000", + "autoExchangeBidRate": "1.83309501", + "autoExchangeAskRate": "2.02605238", + } + + self.set_mock_response(expected_response) + + response = self.client.asset_index(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "/fapi/v1/assetIndex" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(AssetIndexResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(AssetIndexResponse, "from_dict"): + expected = AssetIndexResponse.from_dict(expected_response) + else: + expected = AssetIndexResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_asset_index_server_error(self): + """Test that asset_index() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.client.asset_index = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.asset_index() + def test_basis_success(self): """Test basis() successfully with required parameters only.""" @@ -2052,120 +2158,6 @@ def test_mark_price_kline_candlestick_data_server_error(self): with pytest.raises(Exception, match="ResponseError"): self.client.mark_price_kline_candlestick_data(**params) - def test_multi_assets_mode_asset_index_success(self): - """Test multi_assets_mode_asset_index() successfully with required parameters only.""" - - expected_response = { - "symbol": "ADAUSD", - "time": 1635740268004, - "index": "1.92957370", - "bidBuffer": "0.10000000", - "askBuffer": "0.10000000", - "bidRate": "1.73661633", - "askRate": "2.12253107", - "autoExchangeBidBuffer": "0.05000000", - "autoExchangeAskBuffer": "0.05000000", - "autoExchangeBidRate": "1.83309501", - "autoExchangeAskRate": "2.02605238", - } - - self.set_mock_response(expected_response) - - response = self.client.multi_assets_mode_asset_index() - - actual_call_args = self.mock_session.request.call_args - request_kwargs = actual_call_args.kwargs - - self.mock_session.request.assert_called_once() - - assert "url" in request_kwargs - assert "/fapi/v1/assetIndex" in request_kwargs["url"] - assert request_kwargs["method"] == "GET" - - assert response is not None - is_list = isinstance(expected_response, list) - is_flat_list = ( - is_list and not isinstance(expected_response[0], list) if is_list else False - ) - is_oneof = is_one_of_model(MultiAssetsModeAssetIndexResponse) - - if is_list and not is_flat_list: - expected = expected_response - elif ( - is_oneof - or is_list - or hasattr(MultiAssetsModeAssetIndexResponse, "from_dict") - ): - expected = MultiAssetsModeAssetIndexResponse.from_dict(expected_response) - else: - expected = MultiAssetsModeAssetIndexResponse.model_validate_json( - json.dumps(expected_response) - ) - - assert response.data() == expected - - def test_multi_assets_mode_asset_index_success_with_optional_params(self): - """Test multi_assets_mode_asset_index() successfully with optional parameters.""" - - params = {"symbol": "symbol_example"} - - expected_response = { - "symbol": "ADAUSD", - "time": 1635740268004, - "index": "1.92957370", - "bidBuffer": "0.10000000", - "askBuffer": "0.10000000", - "bidRate": "1.73661633", - "askRate": "2.12253107", - "autoExchangeBidBuffer": "0.05000000", - "autoExchangeAskBuffer": "0.05000000", - "autoExchangeBidRate": "1.83309501", - "autoExchangeAskRate": "2.02605238", - } - - self.set_mock_response(expected_response) - - response = self.client.multi_assets_mode_asset_index(**params) - - actual_call_args = self.mock_session.request.call_args - request_kwargs = actual_call_args.kwargs - - assert "url" in request_kwargs - assert "/fapi/v1/assetIndex" in request_kwargs["url"] - assert request_kwargs["method"] == "GET" - - self.mock_session.request.assert_called_once() - assert response is not None - is_list = isinstance(expected_response, list) - is_flat_list = ( - is_list and not isinstance(expected_response[0], list) if is_list else False - ) - is_oneof = is_one_of_model(MultiAssetsModeAssetIndexResponse) - - if is_list and not is_flat_list: - expected = expected_response - elif ( - is_oneof - or is_list - or hasattr(MultiAssetsModeAssetIndexResponse, "from_dict") - ): - expected = MultiAssetsModeAssetIndexResponse.from_dict(expected_response) - else: - expected = MultiAssetsModeAssetIndexResponse.model_validate_json( - json.dumps(expected_response) - ) - - assert response.data() == expected - - def test_multi_assets_mode_asset_index_server_error(self): - """Test that multi_assets_mode_asset_index() raises an error when the server returns an error.""" - - mock_error = Exception("ResponseError") - self.client.multi_assets_mode_asset_index = MagicMock(side_effect=mock_error) - - with pytest.raises(Exception, match="ResponseError"): - self.client.multi_assets_mode_asset_index() - def test_old_trades_lookup_success(self): """Test old_trades_lookup() successfully with required parameters only.""" diff --git a/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_market_api_ws_streams.py b/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_market_api_ws_streams.py index b56a099a..a290ab6e 100644 --- a/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_market_api_ws_streams.py +++ b/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_market_api_ws_streams.py @@ -57,6 +57,7 @@ async def test_aggregate_trade_streams_subscription(self): "l": 105, "T": 123456785, "m": True, + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@aggTrade".replace("/", "", 1), @@ -98,6 +99,7 @@ async def test_aggregate_trade_streams_success(self): "l": 105, "T": 123456785, "m": True, + "st": 1, } self.ws_streams.aggregate_trade_streams = AsyncMock( return_value=expected_response @@ -125,6 +127,7 @@ async def test_aggregate_trade_streams_success_with_optional_params(self): "l": 105, "T": 123456785, "m": True, + "st": 1, } self.ws_streams.aggregate_trade_streams = AsyncMock( @@ -180,6 +183,8 @@ async def test_all_market_liquidation_order_streams_subscription(self): "z": "0.014", "T": 1568014460893, }, + "ps": "BTCUSDT", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/!forceOrder@arr".replace("/", "", 1), @@ -221,6 +226,8 @@ async def test_all_market_liquidation_order_streams_success(self): "z": "0.014", "T": 1568014460893, }, + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.all_market_liquidation_order_streams = AsyncMock( return_value=expected_response @@ -254,6 +261,8 @@ async def test_all_market_liquidation_order_streams_success_with_optional_params "z": "0.014", "T": 1568014460893, }, + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.all_market_liquidation_order_streams = AsyncMock( @@ -291,6 +300,8 @@ async def test_all_market_mini_tickers_stream_subscription(self): "l": "0.0010", "v": "10000", "q": "18", + "ps": "BTCUSDT", + "st": 1, } ] stream_endpoint = ws_streams_placeholder( @@ -328,6 +339,8 @@ async def test_all_market_mini_tickers_stream_success(self): "l": "0.0010", "v": "10000", "q": "18", + "ps": "BTCUSDT", + "st": 1, } ] self.ws_streams.all_market_mini_tickers_stream = AsyncMock( @@ -355,6 +368,8 @@ async def test_all_market_mini_tickers_stream_success_with_optional_params(self) "l": "0.0010", "v": "10000", "q": "18", + "ps": "BTCUSDT", + "st": 1, } ] @@ -402,6 +417,8 @@ async def test_all_market_tickers_streams_subscription(self): "F": 0, "L": 18150, "n": 18151, + "ps": "BTCUSDT", + "st": 1, } ] stream_endpoint = ws_streams_placeholder( @@ -448,6 +465,8 @@ async def test_all_market_tickers_streams_success(self): "F": 0, "L": 18150, "n": 18151, + "ps": "BTCUSDT", + "st": 1, } ] self.ws_streams.all_market_tickers_streams = AsyncMock( @@ -484,6 +503,8 @@ async def test_all_market_tickers_streams_success_with_optional_params(self): "F": 0, "L": 18150, "n": 18151, + "ps": "BTCUSDT", + "st": 1, } ] @@ -505,6 +526,153 @@ async def test_all_market_tickers_streams_server_error(self): with pytest.raises(Exception, match="ResponseError"): await self.ws_streams.all_market_tickers_streams() + @pytest.mark.asyncio + async def test_asset_index_subscription(self): + """Test that asset_index() subscribes to the correct WebSocket stream.""" + + expected_response = [ + { + "e": "assetIndexUpdate", + "E": 1686749230000, + "s": "ADAUSD", + "i": "0.27462452", + "b": "0.10000000", + "a": "0.10000000", + "B": "0.24716207", + "A": "0.30208698", + "q": "0.05000000", + "g": "0.05000000", + "Q": "0.26089330", + "G": "0.28835575", + }, + { + "e": "assetIndexUpdate", + "E": 1686749230000, + "s": "USDTUSD", + "i": "0.99987691", + "b": "0.00010000", + "a": "0.00010000", + "B": "0.99977692", + "A": "0.99997689", + "q": "0.00010000", + "g": "0.00010000", + "Q": "0.99977692", + "G": "0.99997689", + }, + ] + stream_endpoint = ws_streams_placeholder( + "/!assetIndex@arr".replace("/", "", 1), + {}, + ) + + def mock_on(event, callback, stream): + if event == "message" and stream == stream_endpoint: + callback(expected_response) + + self.websocket_client.on = MagicMock(side_effect=mock_on) + + mock_callback = MagicMock() + + stream = await self.ws_streams.asset_index() + assert isinstance(stream, RequestStreamHandle) + assert callable(stream.on) + assert callable(stream.unsubscribe) + stream.on("message", mock_callback) + mock_callback.assert_called_once_with(expected_response) + + @pytest.mark.asyncio + async def test_asset_index_success(self): + """Test asset_index() successfully with required parameters only.""" + + expected_response = [ + { + "e": "assetIndexUpdate", + "E": 1686749230000, + "s": "ADAUSD", + "i": "0.27462452", + "b": "0.10000000", + "a": "0.10000000", + "B": "0.24716207", + "A": "0.30208698", + "q": "0.05000000", + "g": "0.05000000", + "Q": "0.26089330", + "G": "0.28835575", + }, + { + "e": "assetIndexUpdate", + "E": 1686749230000, + "s": "USDTUSD", + "i": "0.99987691", + "b": "0.00010000", + "a": "0.00010000", + "B": "0.99977692", + "A": "0.99997689", + "q": "0.00010000", + "g": "0.00010000", + "Q": "0.99977692", + "G": "0.99997689", + }, + ] + self.ws_streams.asset_index = AsyncMock(return_value=expected_response) + + response = await self.ws_streams.asset_index() + assert response is not None + assert response == expected_response + + @pytest.mark.asyncio + async def test_asset_index_success_with_optional_params(self): + """Test asset_index() successfully with optional parameters.""" + + params = {"id": "e9d6b4349871b40611412680b3445fac"} + + expected_response = [ + { + "e": "assetIndexUpdate", + "E": 1686749230000, + "s": "ADAUSD", + "i": "0.27462452", + "b": "0.10000000", + "a": "0.10000000", + "B": "0.24716207", + "A": "0.30208698", + "q": "0.05000000", + "g": "0.05000000", + "Q": "0.26089330", + "G": "0.28835575", + }, + { + "e": "assetIndexUpdate", + "E": 1686749230000, + "s": "USDTUSD", + "i": "0.99987691", + "b": "0.00010000", + "a": "0.00010000", + "B": "0.99977692", + "A": "0.99997689", + "q": "0.00010000", + "g": "0.00010000", + "Q": "0.99977692", + "G": "0.99997689", + }, + ] + + self.ws_streams.asset_index = AsyncMock(return_value=expected_response) + + response = await self.ws_streams.asset_index(**params) + assert response is not None + assert response == expected_response + + @pytest.mark.asyncio + async def test_asset_index_server_error(self): + """Test that asset_index() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.ws_streams.asset_index = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + await self.ws_streams.asset_index() + @pytest.mark.asyncio async def test_composite_index_symbol_information_streams_subscription(self): """Test that composite_index_symbol_information_streams() subscribes to the correct WebSocket stream.""" @@ -901,7 +1069,6 @@ async def test_contract_info_stream_subscription(self): "e": "contractInfo", "E": 1669356423908, "s": "IOTAUSDT", - "ps": "IOTAUSDT", "ct": "PERPETUAL", "dt": 4133404800000, "ot": 1569398400000, @@ -926,6 +1093,7 @@ async def test_contract_info_stream_subscription(self): "ma": 20, }, ], + "st": 1, } stream_endpoint = ws_streams_placeholder( "/!contractInfo".replace("/", "", 1), @@ -955,7 +1123,6 @@ async def test_contract_info_stream_success(self): "e": "contractInfo", "E": 1669356423908, "s": "IOTAUSDT", - "ps": "IOTAUSDT", "ct": "PERPETUAL", "dt": 4133404800000, "ot": 1569398400000, @@ -980,6 +1147,7 @@ async def test_contract_info_stream_success(self): "ma": 20, }, ], + "st": 1, } self.ws_streams.contract_info_stream = AsyncMock(return_value=expected_response) @@ -997,7 +1165,6 @@ async def test_contract_info_stream_success_with_optional_params(self): "e": "contractInfo", "E": 1669356423908, "s": "IOTAUSDT", - "ps": "IOTAUSDT", "ct": "PERPETUAL", "dt": 4133404800000, "ot": 1569398400000, @@ -1022,6 +1189,7 @@ async def test_contract_info_stream_success_with_optional_params(self): "ma": 20, }, ], + "st": 1, } self.ws_streams.contract_info_stream = AsyncMock(return_value=expected_response) @@ -1058,6 +1226,8 @@ async def test_individual_symbol_mini_ticker_stream_subscription(self): "l": "0.0010", "v": "10000", "q": "18", + "ps": "BTCUSDT", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@miniTicker".replace("/", "", 1), @@ -1097,6 +1267,8 @@ async def test_individual_symbol_mini_ticker_stream_success(self): "l": "0.0010", "v": "10000", "q": "18", + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.individual_symbol_mini_ticker_stream = AsyncMock( return_value=expected_response @@ -1124,6 +1296,8 @@ async def test_individual_symbol_mini_ticker_stream_success_with_optional_params "l": "0.0010", "v": "10000", "q": "18", + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.individual_symbol_mini_ticker_stream = AsyncMock( @@ -1190,6 +1364,8 @@ async def test_individual_symbol_ticker_streams_subscription(self): "F": 0, "L": 18150, "n": 18151, + "ps": "BTCUSDT", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@ticker".replace("/", "", 1), @@ -1238,6 +1414,8 @@ async def test_individual_symbol_ticker_streams_success(self): "F": 0, "L": 18150, "n": 18151, + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.individual_symbol_ticker_streams = AsyncMock( return_value=expected_response @@ -1272,6 +1450,8 @@ async def test_individual_symbol_ticker_streams_success_with_optional_params(sel "F": 0, "L": 18150, "n": 18151, + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.individual_symbol_ticker_streams = AsyncMock( @@ -1640,6 +1820,7 @@ async def test_mark_price_stream_subscription(self): "P": "11784.25641265", "r": "0.00038167", "T": 1562306400000, + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@markPrice@".replace("/", "", 1), @@ -1679,6 +1860,7 @@ async def test_mark_price_stream_success(self): "P": "11784.25641265", "r": "0.00038167", "T": 1562306400000, + "st": 1, } self.ws_streams.mark_price_stream = AsyncMock(return_value=expected_response) @@ -1706,6 +1888,7 @@ async def test_mark_price_stream_success_with_optional_params(self): "P": "11784.25641265", "r": "0.00038167", "T": 1562306400000, + "st": 1, } self.ws_streams.mark_price_stream = AsyncMock(return_value=expected_response) @@ -1754,6 +1937,7 @@ async def test_mark_price_stream_for_all_market_subscription(self): "P": "11784.25641265", "r": "0.00030000", "T": 1562306400000, + "st": 1, } ] stream_endpoint = ws_streams_placeholder( @@ -1791,6 +1975,7 @@ async def test_mark_price_stream_for_all_market_success(self): "P": "11784.25641265", "r": "0.00030000", "T": 1562306400000, + "st": 1, } ] self.ws_streams.mark_price_stream_for_all_market = AsyncMock( @@ -1821,6 +2006,7 @@ async def test_mark_price_stream_for_all_market_success_with_optional_params(sel "P": "11784.25641265", "r": "0.00030000", "T": 1562306400000, + "st": 1, } ] @@ -1844,169 +2030,16 @@ async def test_mark_price_stream_for_all_market_server_error(self): with pytest.raises(Exception, match="ResponseError"): await self.ws_streams.mark_price_stream_for_all_market() - @pytest.mark.asyncio - async def test_multi_assets_mode_asset_index_subscription(self): - """Test that multi_assets_mode_asset_index() subscribes to the correct WebSocket stream.""" - - expected_response = [ - { - "e": "assetIndexUpdate", - "E": 1686749230000, - "s": "ADAUSD", - "i": "0.27462452", - "b": "0.10000000", - "a": "0.10000000", - "B": "0.24716207", - "A": "0.30208698", - "q": "0.05000000", - "g": "0.05000000", - "Q": "0.26089330", - "G": "0.28835575", - }, - { - "e": "assetIndexUpdate", - "E": 1686749230000, - "s": "USDTUSD", - "i": "0.99987691", - "b": "0.00010000", - "a": "0.00010000", - "B": "0.99977692", - "A": "0.99997689", - "q": "0.00010000", - "g": "0.00010000", - "Q": "0.99977692", - "G": "0.99997689", - }, - ] - stream_endpoint = ws_streams_placeholder( - "/!assetIndex@arr".replace("/", "", 1), - {}, - ) - - def mock_on(event, callback, stream): - if event == "message" and stream == stream_endpoint: - callback(expected_response) - - self.websocket_client.on = MagicMock(side_effect=mock_on) - - mock_callback = MagicMock() - - stream = await self.ws_streams.multi_assets_mode_asset_index() - assert isinstance(stream, RequestStreamHandle) - assert callable(stream.on) - assert callable(stream.unsubscribe) - stream.on("message", mock_callback) - mock_callback.assert_called_once_with(expected_response) - - @pytest.mark.asyncio - async def test_multi_assets_mode_asset_index_success(self): - """Test multi_assets_mode_asset_index() successfully with required parameters only.""" - - expected_response = [ - { - "e": "assetIndexUpdate", - "E": 1686749230000, - "s": "ADAUSD", - "i": "0.27462452", - "b": "0.10000000", - "a": "0.10000000", - "B": "0.24716207", - "A": "0.30208698", - "q": "0.05000000", - "g": "0.05000000", - "Q": "0.26089330", - "G": "0.28835575", - }, - { - "e": "assetIndexUpdate", - "E": 1686749230000, - "s": "USDTUSD", - "i": "0.99987691", - "b": "0.00010000", - "a": "0.00010000", - "B": "0.99977692", - "A": "0.99997689", - "q": "0.00010000", - "g": "0.00010000", - "Q": "0.99977692", - "G": "0.99997689", - }, - ] - self.ws_streams.multi_assets_mode_asset_index = AsyncMock( - return_value=expected_response - ) - - response = await self.ws_streams.multi_assets_mode_asset_index() - assert response is not None - assert response == expected_response - - @pytest.mark.asyncio - async def test_multi_assets_mode_asset_index_success_with_optional_params(self): - """Test multi_assets_mode_asset_index() successfully with optional parameters.""" - - params = {"id": "e9d6b4349871b40611412680b3445fac"} - - expected_response = [ - { - "e": "assetIndexUpdate", - "E": 1686749230000, - "s": "ADAUSD", - "i": "0.27462452", - "b": "0.10000000", - "a": "0.10000000", - "B": "0.24716207", - "A": "0.30208698", - "q": "0.05000000", - "g": "0.05000000", - "Q": "0.26089330", - "G": "0.28835575", - }, - { - "e": "assetIndexUpdate", - "E": 1686749230000, - "s": "USDTUSD", - "i": "0.99987691", - "b": "0.00010000", - "a": "0.00010000", - "B": "0.99977692", - "A": "0.99997689", - "q": "0.00010000", - "g": "0.00010000", - "Q": "0.99977692", - "G": "0.99997689", - }, - ] - - self.ws_streams.multi_assets_mode_asset_index = AsyncMock( - return_value=expected_response - ) - - response = await self.ws_streams.multi_assets_mode_asset_index(**params) - assert response is not None - assert response == expected_response - - @pytest.mark.asyncio - async def test_multi_assets_mode_asset_index_server_error(self): - """Test that multi_assets_mode_asset_index() raises an error when the server returns an error.""" - - mock_error = Exception("ResponseError") - self.ws_streams.multi_assets_mode_asset_index = MagicMock( - side_effect=mock_error - ) - - with pytest.raises(Exception, match="ResponseError"): - await self.ws_streams.multi_assets_mode_asset_index() - @pytest.mark.asyncio async def test_trading_session_stream_subscription(self): """Test that trading_session_stream() subscribes to the correct WebSocket stream.""" expected_response = { - "e": "KR_EquityUpdate", - "E": 1779962686695, - "t": 1779958800000, - "T": 1780009200000, - "S": "NO_TRADING", + "e": "EquityUpdate", + "E": 1765244143062, + "t": 1765242000000, + "T": 1765270800000, + "S": "OVERNIGHT", } stream_endpoint = ws_streams_placeholder( "/tradingSession".replace("/", "", 1), @@ -2033,11 +2066,11 @@ async def test_trading_session_stream_success(self): """Test trading_session_stream() successfully with required parameters only.""" expected_response = { - "e": "KR_EquityUpdate", - "E": 1779962686695, - "t": 1779958800000, - "T": 1780009200000, - "S": "NO_TRADING", + "e": "EquityUpdate", + "E": 1765244143062, + "t": 1765242000000, + "T": 1765270800000, + "S": "OVERNIGHT", } self.ws_streams.trading_session_stream = AsyncMock( return_value=expected_response @@ -2054,11 +2087,11 @@ async def test_trading_session_stream_success_with_optional_params(self): params = {"id": "e9d6b4349871b40611412680b3445fac"} expected_response = { - "e": "KR_EquityUpdate", - "E": 1779962686695, - "t": 1779958800000, - "T": 1780009200000, - "S": "NO_TRADING", + "e": "EquityUpdate", + "E": 1765244143062, + "t": 1765242000000, + "T": 1765270800000, + "S": "OVERNIGHT", } self.ws_streams.trading_session_stream = AsyncMock( diff --git a/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_public_api_ws_streams.py b/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_public_api_ws_streams.py index bcff4379..556dd6c8 100644 --- a/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_public_api_ws_streams.py +++ b/clients/derivatives_trading_usds_futures/tests/unit/websocket_streams/test_public_api_ws_streams.py @@ -51,6 +51,8 @@ async def test_all_book_tickers_stream_subscription(self): "B": "31.21000000", "a": "25.36520000", "A": "40.66000000", + "ps": "BTCUSDT", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/!bookTicker".replace("/", "", 1), @@ -86,6 +88,8 @@ async def test_all_book_tickers_stream_success(self): "B": "31.21000000", "a": "25.36520000", "A": "40.66000000", + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.all_book_tickers_stream = AsyncMock( return_value=expected_response @@ -111,6 +115,8 @@ async def test_all_book_tickers_stream_success_with_optional_params(self): "B": "31.21000000", "a": "25.36520000", "A": "40.66000000", + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.all_book_tickers_stream = AsyncMock( @@ -149,6 +155,8 @@ async def test_diff_book_depth_streams_subscription(self): "pu": 149, "b": [["0.0024", "10"]], "a": [["0.0026", "100"]], + "ps": "BTCUSDT", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@depth@".replace("/", "", 1), @@ -188,6 +196,8 @@ async def test_diff_book_depth_streams_success(self): "pu": 149, "b": [["0.0024", "10"]], "a": [["0.0026", "100"]], + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.diff_book_depth_streams = AsyncMock( return_value=expected_response @@ -217,6 +227,8 @@ async def test_diff_book_depth_streams_success_with_optional_params(self): "pu": 149, "b": [["0.0024", "10"]], "a": [["0.0026", "100"]], + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.diff_book_depth_streams = AsyncMock( @@ -263,13 +275,15 @@ async def test_individual_symbol_book_ticker_streams_subscription(self): expected_response = { "e": "bookTicker", "u": 400900217, + "s": "BNBUSDT", + "ps": "BNBUSDT", "E": 1568014460893, "T": 1568014460891, - "s": "BNBUSDT", "b": "25.35190000", "B": "31.21000000", "a": "25.36520000", "A": "40.66000000", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@bookTicker".replace("/", "", 1), @@ -302,13 +316,15 @@ async def test_individual_symbol_book_ticker_streams_success(self): expected_response = { "e": "bookTicker", "u": 400900217, + "s": "BNBUSDT", + "ps": "BNBUSDT", "E": 1568014460893, "T": 1568014460891, - "s": "BNBUSDT", "b": "25.35190000", "B": "31.21000000", "a": "25.36520000", "A": "40.66000000", + "st": 1, } self.ws_streams.individual_symbol_book_ticker_streams = AsyncMock( return_value=expected_response @@ -329,13 +345,15 @@ async def test_individual_symbol_book_ticker_streams_success_with_optional_param expected_response = { "e": "bookTicker", "u": 400900217, + "s": "BNBUSDT", + "ps": "BNBUSDT", "E": 1568014460893, "T": 1568014460891, - "s": "BNBUSDT", "b": "25.35190000", "B": "31.21000000", "a": "25.36520000", "A": "40.66000000", + "st": 1, } self.ws_streams.individual_symbol_book_ticker_streams = AsyncMock( @@ -406,6 +424,8 @@ async def test_partial_book_depth_streams_subscription(self): ["7407.15", "4.800"], ["7407.20", "0.175"], ], + "ps": "BTCUSDT", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@depth@".replace("/", "", 1), @@ -458,6 +478,8 @@ async def test_partial_book_depth_streams_success(self): ["7407.15", "4.800"], ["7407.20", "0.175"], ], + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.partial_book_depth_streams = AsyncMock( return_value=expected_response @@ -500,6 +522,8 @@ async def test_partial_book_depth_streams_success_with_optional_params(self): ["7407.15", "4.800"], ["7407.20", "0.175"], ], + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.partial_book_depth_streams = AsyncMock( @@ -567,6 +591,8 @@ async def test_rpi_diff_book_depth_streams_subscription(self): "pu": 149, "b": [["0.0024", "10"]], "a": [["0.0026", "100"]], + "ps": "BTCUSDT", + "st": 1, } stream_endpoint = ws_streams_placeholder( "/@rpiDepth@500ms".replace("/", "", 1), @@ -606,6 +632,8 @@ async def test_rpi_diff_book_depth_streams_success(self): "pu": 149, "b": [["0.0024", "10"]], "a": [["0.0026", "100"]], + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.rpi_diff_book_depth_streams = AsyncMock( return_value=expected_response @@ -631,6 +659,8 @@ async def test_rpi_diff_book_depth_streams_success_with_optional_params(self): "pu": 149, "b": [["0.0024", "10"]], "a": [["0.0026", "100"]], + "ps": "BTCUSDT", + "st": 1, } self.ws_streams.rpi_diff_book_depth_streams = AsyncMock( diff --git a/clients/vip_loan/CHANGELOG.md b/clients/vip_loan/CHANGELOG.md index 8fa395fa..9983a40d 100644 --- a/clients/vip_loan/CHANGELOG.md +++ b/clients/vip_loan/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 6.0.0 - 2026-06-29 + +### Added (2) + +- `query_vip_loan_fixed_rate_market()` (`GET /sapi/v1/loan/vip/fixed/market`) +- `vip_loan_fixed_rate_borrow()` (`POST /sapi/v1/loan/vip/fixed/borrow`) + ## 5.9.0 - 2026-06-09 ### Changed (2) diff --git a/clients/vip_loan/examples/rest_api/MarketData/query_vip_loan_fixed_rate_market.py b/clients/vip_loan/examples/rest_api/MarketData/query_vip_loan_fixed_rate_market.py new file mode 100644 index 00000000..02f47acd --- /dev/null +++ b/clients/vip_loan/examples/rest_api/MarketData/query_vip_loan_fixed_rate_market.py @@ -0,0 +1,41 @@ +import os +import logging + +from binance_sdk_vip_loan.vip_loan import ( + VipLoan, + ConfigurationRestAPI, + VIP_LOAN_REST_API_PROD_URL, +) + + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", VIP_LOAN_REST_API_PROD_URL), +) + +# Initialize VipLoan client +client = VipLoan(config_rest_api=configuration_rest_api) + + +def query_vip_loan_fixed_rate_market(): + try: + response = client.rest_api.query_vip_loan_fixed_rate_market( + loan_coin="loan_coin_example", + ) + + rate_limits = response.rate_limits + logging.info(f"query_vip_loan_fixed_rate_market() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_vip_loan_fixed_rate_market() response: {data}") + except Exception as e: + logging.error(f"query_vip_loan_fixed_rate_market() error: {e}") + + +if __name__ == "__main__": + query_vip_loan_fixed_rate_market() diff --git a/clients/vip_loan/examples/rest_api/Trade/vip_loan_fixed_rate_borrow.py b/clients/vip_loan/examples/rest_api/Trade/vip_loan_fixed_rate_borrow.py new file mode 100644 index 00000000..9038dc77 --- /dev/null +++ b/clients/vip_loan/examples/rest_api/Trade/vip_loan_fixed_rate_borrow.py @@ -0,0 +1,46 @@ +import os +import logging + +from binance_sdk_vip_loan.vip_loan import ( + VipLoan, + ConfigurationRestAPI, + VIP_LOAN_REST_API_PROD_URL, +) + + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", VIP_LOAN_REST_API_PROD_URL), +) + +# Initialize VipLoan client +client = VipLoan(config_rest_api=configuration_rest_api) + + +def vip_loan_fixed_rate_borrow(): + try: + response = client.rest_api.vip_loan_fixed_rate_borrow( + supply_request="supply_request_example", + borrow_coin="borrow_coin_example", + loan_term=56, + borrow_uid=56, + collateral_coin="collateral_coin_example", + collateral_account_id="1", + ) + + rate_limits = response.rate_limits + logging.info(f"vip_loan_fixed_rate_borrow() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"vip_loan_fixed_rate_borrow() response: {data}") + except Exception as e: + logging.error(f"vip_loan_fixed_rate_borrow() error: {e}") + + +if __name__ == "__main__": + vip_loan_fixed_rate_borrow() diff --git a/clients/vip_loan/pyproject.toml b/clients/vip_loan/pyproject.toml index 8ddb925c..97ed9650 100644 --- a/clients/vip_loan/pyproject.toml +++ b/clients/vip_loan/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "binance-sdk-vip-loan" -version = "5.9.0" +version = "6.0.0" description = "Official Binance Vip Loan SDK - A lightweight library that provides a convenient interface to Binance's VipLoan REST API" authors = ["Binance"] license = "MIT" diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/market_data_api.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/market_data_api.py index e5871deb..ffa978cf 100644 --- a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/market_data_api.py +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/market_data_api.py @@ -20,6 +20,7 @@ from ..models import GetCollateralAssetDataResponse from ..models import GetLoanableAssetsDataResponse from ..models import GetVIPLoanInterestRateHistoryResponse +from ..models import QueryVIPLoanFixedRateMarketResponse class MarketDataApi: @@ -200,7 +201,7 @@ def get_vip_loan_interest_rate_history( recv_window (Union[int, None]): start_time (Optional[int] = None): end_time (Optional[int] = None): - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 Returns: @@ -243,3 +244,63 @@ def get_vip_loan_interest_rate_history( is_signed=True, signer=self._signer, ) + + def query_vip_loan_fixed_rate_market( + self, + loan_coin: Union[str, None], + duration: Optional[int] = None, + current: Optional[int] = None, + size: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryVIPLoanFixedRateMarketResponse]: + """ + Query VIP Loan Fixed Rate Market(USER_DATA) + GET /sapi/v1/loan/vip/fixed/market + https://developers.binance.com/docs/vip_loan/market-data/Query-VIP-Loan-Fixed-Rate-Market + + Query the VIP Loan fixed rate market. Returns a paginated list of fixed-rate supply orders. + + Weight: 6000 + + Args: + loan_coin (Union[str, None]): + duration (Optional[int] = None): Duration in days, minimum 1 + current (Optional[int] = None): Page number, default 1, minimum 1 + size (Optional[int] = None): Page size, default 10, range [1, 100] + recv_window (Optional[int] = None): + + Returns: + ApiResponse[QueryVIPLoanFixedRateMarketResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if loan_coin is None: + raise RequiredError( + field="loan_coin", + error_message="Missing required parameter 'loan_coin'", + ) + + body = {} + payload = { + "loan_coin": loan_coin, + "duration": duration, + "current": current, + "size": size, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/loan/vip/fixed/market", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryVIPLoanFixedRateMarketResponse, + is_signed=True, + signer=self._signer, + ) diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/trade_api.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/trade_api.py index da513fed..1024d1eb 100644 --- a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/trade_api.py +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/trade_api.py @@ -17,6 +17,7 @@ from binance_common.utils import send_request from ..models import VipLoanBorrowResponse +from ..models import VipLoanFixedRateBorrowResponse from ..models import VipLoanRenewResponse from ..models import VipLoanRepayResponse @@ -64,7 +65,7 @@ def vip_loan_borrow( loan_coin (Union[str, None]): loan_amount (Union[float, None]): collateral_account_id (Union[str, None]): Multiple split by `,` - collateral_coin (Union[str, None]): Multiple split by `,` + collateral_coin (Union[str, None]): Collateral coin(s), multiple separated by `,`. Only coin names, no amount (VIP loan collateral amount = entire spot account balance) is_flexible_rate (Union[bool, None]): Default: TRUE. TRUE : flexible rate; FALSE: fixed rate loan_term (Optional[int] = None): Mandatory for fixed rate. Optional for fixed interest rate. Eg: 30/60 days recv_window (Optional[int] = None): @@ -133,6 +134,103 @@ def vip_loan_borrow( signer=self._signer, ) + def vip_loan_fixed_rate_borrow( + self, + supply_request: Union[str, None], + borrow_coin: Union[str, None], + loan_term: Union[int, None], + borrow_uid: Union[int, None], + collateral_coin: Union[str, None], + collateral_account_id: Union[str, None], + auto_repay: Optional[bool] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[VipLoanFixedRateBorrowResponse]: + """ + VIP Loan Fixed Rate Borrow(TRADE) + POST /sapi/v1/loan/vip/fixed/borrow + https://developers.binance.com/docs/vip_loan/trade/VIP-Loan-Fixed-Rate-Borrow + + Submit a fixed rate borrow request by matching market supply orders. + + * **Rate limit:** 2 requests per second per account. + * When multiple `supplyRequest` entries are provided, all `requestId` values must correspond to the same `borrowCoin` and `loanTerm` (validated by collateral facade). + + Weight: 6000 + + Args: + supply_request (Union[str, None]): Supply request string, positional encoding (no key). Multiple entries separated by `;`, fields separated by `:`, order: `::`. Example: `1212:0.12:100;3434:0.13:50` + borrow_coin (Union[str, None]): Borrow coin + loan_term (Union[int, None]): 30/60 days + borrow_uid (Union[int, None]): Borrow receiving account UID + collateral_coin (Union[str, None]): Collateral coin(s), multiple separated by `,`. Only coin names, no amount (VIP loan collateral amount = entire spot account balance) + collateral_account_id (Union[str, None]): Multiple split by `,` + auto_repay (Optional[bool] = None): Default: `true`. `true`: auto repay at expiration; `false`: auto-convert to flexible (floating rate) at expiration + recv_window (Optional[int] = None): + + Returns: + ApiResponse[VipLoanFixedRateBorrowResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if supply_request is None: + raise RequiredError( + field="supply_request", + error_message="Missing required parameter 'supply_request'", + ) + if borrow_coin is None: + raise RequiredError( + field="borrow_coin", + error_message="Missing required parameter 'borrow_coin'", + ) + if loan_term is None: + raise RequiredError( + field="loan_term", + error_message="Missing required parameter 'loan_term'", + ) + if borrow_uid is None: + raise RequiredError( + field="borrow_uid", + error_message="Missing required parameter 'borrow_uid'", + ) + if collateral_coin is None: + raise RequiredError( + field="collateral_coin", + error_message="Missing required parameter 'collateral_coin'", + ) + if collateral_account_id is None: + raise RequiredError( + field="collateral_account_id", + error_message="Missing required parameter 'collateral_account_id'", + ) + + body = {} + payload = { + "supply_request": supply_request, + "borrow_coin": borrow_coin, + "loan_term": loan_term, + "borrow_uid": borrow_uid, + "collateral_coin": collateral_coin, + "collateral_account_id": collateral_account_id, + "auto_repay": auto_repay, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="POST", + path="/sapi/v1/loan/vip/fixed/borrow", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=VipLoanFixedRateBorrowResponse, + is_signed=True, + signer=self._signer, + ) + def vip_loan_renew( self, order_id: Union[int, None], diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/user_information_api.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/user_information_api.py index a026043b..a614862c 100644 --- a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/user_information_api.py +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/api/user_information_api.py @@ -112,7 +112,7 @@ def get_vip_loan_accrued_interest( loan_coin (Optional[str] = None): start_time (Optional[int] = None): end_time (Optional[int] = None): - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 recv_window (Optional[int] = None): @@ -172,7 +172,7 @@ def get_vip_loan_ongoing_orders( collateral_account_id (Optional[int] = None): loan_coin (Optional[str] = None): collateral_coin (Optional[str] = None): - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 recv_window (Optional[int] = None): @@ -224,7 +224,7 @@ def query_application_status( Weight: 400 Args: - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 recv_window (Optional[int] = None): diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/__init__.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/__init__.py index 167eebcc..d72c9348 100644 --- a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/__init__.py +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/__init__.py @@ -56,6 +56,15 @@ from .query_application_status_response_rows_inner import ( QueryApplicationStatusResponseRowsInner as QueryApplicationStatusResponseRowsInner, ) +from .query_vip_loan_fixed_rate_market_response import ( + QueryVIPLoanFixedRateMarketResponse as QueryVIPLoanFixedRateMarketResponse, +) +from .query_vip_loan_fixed_rate_market_response_rows_inner import ( + QueryVIPLoanFixedRateMarketResponseRowsInner as QueryVIPLoanFixedRateMarketResponseRowsInner, +) from .vip_loan_borrow_response import VipLoanBorrowResponse as VipLoanBorrowResponse +from .vip_loan_fixed_rate_borrow_response import ( + VipLoanFixedRateBorrowResponse as VipLoanFixedRateBorrowResponse, +) from .vip_loan_renew_response import VipLoanRenewResponse as VipLoanRenewResponse from .vip_loan_repay_response import VipLoanRepayResponse as VipLoanRepayResponse diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/query_vip_loan_fixed_rate_market_response.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/query_vip_loan_fixed_rate_market_response.py new file mode 100644 index 00000000..c5c75f55 --- /dev/null +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/query_vip_loan_fixed_rate_market_response.py @@ -0,0 +1,125 @@ +# coding: utf-8 + +""" +Binance VIP Loan REST API + +OpenAPI Specification for the Binance VIP Loan REST API +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_vip_loan.rest_api.models.query_vip_loan_fixed_rate_market_response_rows_inner import ( + QueryVIPLoanFixedRateMarketResponseRowsInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryVIPLoanFixedRateMarketResponse(BaseModel): + """ + QueryVIPLoanFixedRateMarketResponse + """ # noqa: E501 + + total: Optional[StrictInt] = None + rows: Optional[List[QueryVIPLoanFixedRateMarketResponseRowsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["total", "rows"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryVIPLoanFixedRateMarketResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in rows (list) + _items = [] + if self.rows: + for _item_rows in self.rows: + if _item_rows: + _items.append(_item_rows.to_dict()) + _dict["rows"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryVIPLoanFixedRateMarketResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "total": obj.get("total"), + "rows": ( + [ + QueryVIPLoanFixedRateMarketResponseRowsInner.from_dict(_item) + for _item in obj["rows"] + ] + if obj.get("rows") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/query_vip_loan_fixed_rate_market_response_rows_inner.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/query_vip_loan_fixed_rate_market_response_rows_inner.py new file mode 100644 index 00000000..38693992 --- /dev/null +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/query_vip_loan_fixed_rate_market_response_rows_inner.py @@ -0,0 +1,131 @@ +# coding: utf-8 + +""" +Binance VIP Loan REST API + +OpenAPI Specification for the Binance VIP Loan REST API +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryVIPLoanFixedRateMarketResponseRowsInner(BaseModel): + """ + QueryVIPLoanFixedRateMarketResponseRowsInner + """ # noqa: E501 + + request_id: Optional[StrictInt] = Field(default=None, alias="requestId") + request_no: Optional[StrictInt] = Field(default=None, alias="requestNo") + coin: Optional[StrictStr] = None + interest_rate: Optional[StrictStr] = Field(default=None, alias="interestRate") + duration: Optional[StrictInt] = None + minimum_amount: Optional[StrictStr] = Field(default=None, alias="minimumAmount") + available_amount: Optional[StrictStr] = Field(default=None, alias="availableAmount") + estimated_interest: Optional[StrictStr] = Field( + default=None, alias="estimatedInterest" + ) + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "requestId", + "requestNo", + "coin", + "interestRate", + "duration", + "minimumAmount", + "availableAmount", + "estimatedInterest", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryVIPLoanFixedRateMarketResponseRowsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryVIPLoanFixedRateMarketResponseRowsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "requestId": obj.get("requestId"), + "requestNo": obj.get("requestNo"), + "coin": obj.get("coin"), + "interestRate": obj.get("interestRate"), + "duration": obj.get("duration"), + "minimumAmount": obj.get("minimumAmount"), + "availableAmount": obj.get("availableAmount"), + "estimatedInterest": obj.get("estimatedInterest"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/vip_loan_fixed_rate_borrow_response.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/vip_loan_fixed_rate_borrow_response.py new file mode 100644 index 00000000..32f60c52 --- /dev/null +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/models/vip_loan_fixed_rate_borrow_response.py @@ -0,0 +1,141 @@ +# coding: utf-8 + +""" +Binance VIP Loan REST API + +OpenAPI Specification for the Binance VIP Loan REST API +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class VipLoanFixedRateBorrowResponse(BaseModel): + """ + VipLoanFixedRateBorrowResponse + """ # noqa: E501 + + borrow_coin: Optional[StrictStr] = Field(default=None, alias="borrowCoin") + borrow_amount: Optional[StrictStr] = Field(default=None, alias="borrowAmount") + actual_received_amount: Optional[StrictStr] = Field( + default=None, alias="actualReceivedAmount" + ) + collateral_coin: Optional[StrictStr] = Field(default=None, alias="collateralCoin") + collateral_account_id: Optional[StrictStr] = Field( + default=None, alias="collateralAccountId" + ) + borrow_interest_rate: Optional[StrictStr] = Field( + default=None, alias="borrowInterestRate" + ) + duration: Optional[StrictStr] = None + auto_repay: Optional[StrictBool] = Field(default=None, alias="autoRepay") + order_id: Optional[StrictInt] = Field(default=None, alias="orderId") + status: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "borrowCoin", + "borrowAmount", + "actualReceivedAmount", + "collateralCoin", + "collateralAccountId", + "borrowInterestRate", + "duration", + "autoRepay", + "orderId", + "status", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of VipLoanFixedRateBorrowResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of VipLoanFixedRateBorrowResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "borrowCoin": obj.get("borrowCoin"), + "borrowAmount": obj.get("borrowAmount"), + "actualReceivedAmount": obj.get("actualReceivedAmount"), + "collateralCoin": obj.get("collateralCoin"), + "collateralAccountId": obj.get("collateralAccountId"), + "borrowInterestRate": obj.get("borrowInterestRate"), + "duration": obj.get("duration"), + "autoRepay": obj.get("autoRepay"), + "orderId": obj.get("orderId"), + "status": obj.get("status"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/rest_api.py b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/rest_api.py index ae7cdd24..810a42b2 100644 --- a/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/rest_api.py +++ b/clients/vip_loan/src/binance_sdk_vip_loan/rest_api/rest_api.py @@ -22,7 +22,9 @@ from .models import GetCollateralAssetDataResponse from .models import GetLoanableAssetsDataResponse from .models import GetVIPLoanInterestRateHistoryResponse +from .models import QueryVIPLoanFixedRateMarketResponse from .models import VipLoanBorrowResponse +from .models import VipLoanFixedRateBorrowResponse from .models import VipLoanRenewResponse from .models import VipLoanRepayResponse from .models import CheckVIPLoanCollateralAccountResponse @@ -224,7 +226,7 @@ def get_vip_loan_interest_rate_history( recv_window (Union[int, None]): start_time (Optional[int] = None): end_time (Optional[int] = None): - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 Returns: @@ -239,6 +241,40 @@ def get_vip_loan_interest_rate_history( coin, recv_window, start_time, end_time, current, limit ) + def query_vip_loan_fixed_rate_market( + self, + loan_coin: Union[str, None], + duration: Optional[int] = None, + current: Optional[int] = None, + size: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryVIPLoanFixedRateMarketResponse]: + """ + Query VIP Loan Fixed Rate Market(USER_DATA) + + Query the VIP Loan fixed rate market. Returns a paginated list of fixed-rate supply orders. + + Weight: 6000 + + Args: + loan_coin (Union[str, None]): + duration (Optional[int] = None): Duration in days, minimum 1 + current (Optional[int] = None): Page number, default 1, minimum 1 + size (Optional[int] = None): Page size, default 10, range [1, 100] + recv_window (Optional[int] = None): + + Returns: + ApiResponse[QueryVIPLoanFixedRateMarketResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.query_vip_loan_fixed_rate_market( + loan_coin, duration, current, size, recv_window + ) + def vip_loan_borrow( self, loan_account_id: Union[int, None], @@ -267,7 +303,7 @@ def vip_loan_borrow( loan_coin (Union[str, None]): loan_amount (Union[float, None]): collateral_account_id (Union[str, None]): Multiple split by `,` - collateral_coin (Union[str, None]): Multiple split by `,` + collateral_coin (Union[str, None]): Collateral coin(s), multiple separated by `,`. Only coin names, no amount (VIP loan collateral amount = entire spot account balance) is_flexible_rate (Union[bool, None]): Default: TRUE. TRUE : flexible rate; FALSE: fixed rate loan_term (Optional[int] = None): Mandatory for fixed rate. Optional for fixed interest rate. Eg: 30/60 days recv_window (Optional[int] = None): @@ -291,6 +327,56 @@ def vip_loan_borrow( recv_window, ) + def vip_loan_fixed_rate_borrow( + self, + supply_request: Union[str, None], + borrow_coin: Union[str, None], + loan_term: Union[int, None], + borrow_uid: Union[int, None], + collateral_coin: Union[str, None], + collateral_account_id: Union[str, None], + auto_repay: Optional[bool] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[VipLoanFixedRateBorrowResponse]: + """ + VIP Loan Fixed Rate Borrow(TRADE) + + Submit a fixed rate borrow request by matching market supply orders. + + * **Rate limit:** 2 requests per second per account. + * When multiple `supplyRequest` entries are provided, all `requestId` values must correspond to the same `borrowCoin` and `loanTerm` (validated by collateral facade). + + Weight: 6000 + + Args: + supply_request (Union[str, None]): Supply request string, positional encoding (no key). Multiple entries separated by `;`, fields separated by `:`, order: `::`. Example: `1212:0.12:100;3434:0.13:50` + borrow_coin (Union[str, None]): Borrow coin + loan_term (Union[int, None]): 30/60 days + borrow_uid (Union[int, None]): Borrow receiving account UID + collateral_coin (Union[str, None]): Collateral coin(s), multiple separated by `,`. Only coin names, no amount (VIP loan collateral amount = entire spot account balance) + collateral_account_id (Union[str, None]): Multiple split by `,` + auto_repay (Optional[bool] = None): Default: `true`. `true`: auto repay at expiration; `false`: auto-convert to flexible (floating rate) at expiration + recv_window (Optional[int] = None): + + Returns: + ApiResponse[VipLoanFixedRateBorrowResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._tradeApi.vip_loan_fixed_rate_borrow( + supply_request, + borrow_coin, + loan_term, + borrow_uid, + collateral_coin, + collateral_account_id, + auto_repay, + recv_window, + ) + def vip_loan_renew( self, order_id: Union[int, None], @@ -405,7 +491,7 @@ def get_vip_loan_accrued_interest( loan_coin (Optional[str] = None): start_time (Optional[int] = None): end_time (Optional[int] = None): - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 recv_window (Optional[int] = None): @@ -443,7 +529,7 @@ def get_vip_loan_ongoing_orders( collateral_account_id (Optional[int] = None): loan_coin (Optional[str] = None): collateral_coin (Optional[str] = None): - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 recv_window (Optional[int] = None): @@ -479,7 +565,7 @@ def query_application_status( Weight: 400 Args: - current (Optional[int] = None): Current querying page. Start from 1; default: 1; max: 1000 + current (Optional[int] = None): Page number, default 1, minimum 1 limit (Optional[int] = None): Default: 10; max: 100 recv_window (Optional[int] = None): diff --git a/clients/vip_loan/tests/unit/rest_api/test_market_data_api.py b/clients/vip_loan/tests/unit/rest_api/test_market_data_api.py index 37e6a547..0a72e089 100644 --- a/clients/vip_loan/tests/unit/rest_api/test_market_data_api.py +++ b/clients/vip_loan/tests/unit/rest_api/test_market_data_api.py @@ -24,6 +24,7 @@ from binance_sdk_vip_loan.rest_api.models import GetCollateralAssetDataResponse from binance_sdk_vip_loan.rest_api.models import GetLoanableAssetsDataResponse from binance_sdk_vip_loan.rest_api.models import GetVIPLoanInterestRateHistoryResponse +from binance_sdk_vip_loan.rest_api.models import QueryVIPLoanFixedRateMarketResponse class TestMarketDataApi: @@ -601,3 +602,158 @@ def test_get_vip_loan_interest_rate_history_server_error(self): with pytest.raises(Exception, match="ResponseError"): self.client.get_vip_loan_interest_rate_history(**params) + + @patch("binance_common.utils.get_signature") + def test_query_vip_loan_fixed_rate_market_success(self, mock_get_signature): + """Test query_vip_loan_fixed_rate_market() successfully with required parameters only.""" + + params = { + "loan_coin": "loan_coin_example", + } + + expected_response = { + "total": 25, + "rows": [ + { + "requestId": 1234567890, + "requestNo": 100001, + "coin": "USDT", + "interestRate": "0.05", + "duration": 30, + "minimumAmount": "100", + "availableAmount": "1000000", + "estimatedInterest": "4109.59", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_vip_loan_fixed_rate_market(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/loan/vip/fixed/market" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert normalized["loanCoin"] == "loan_coin_example" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryVIPLoanFixedRateMarketResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof + or is_list + or hasattr(QueryVIPLoanFixedRateMarketResponse, "from_dict") + ): + expected = QueryVIPLoanFixedRateMarketResponse.from_dict(expected_response) + else: + expected = QueryVIPLoanFixedRateMarketResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_vip_loan_fixed_rate_market_success_with_optional_params( + self, mock_get_signature + ): + """Test query_vip_loan_fixed_rate_market() successfully with optional parameters.""" + + params = { + "loan_coin": "loan_coin_example", + "duration": 56, + "current": 1, + "size": 5000, + "recv_window": 5000, + } + + expected_response = { + "total": 25, + "rows": [ + { + "requestId": 1234567890, + "requestNo": 100001, + "coin": "USDT", + "interestRate": "0.05", + "duration": 30, + "minimumAmount": "100", + "availableAmount": "1000000", + "estimatedInterest": "4109.59", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_vip_loan_fixed_rate_market(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/loan/vip/fixed/market" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryVIPLoanFixedRateMarketResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof + or is_list + or hasattr(QueryVIPLoanFixedRateMarketResponse, "from_dict") + ): + expected = QueryVIPLoanFixedRateMarketResponse.from_dict(expected_response) + else: + expected = QueryVIPLoanFixedRateMarketResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_vip_loan_fixed_rate_market_missing_required_param_loan_coin(self): + """Test that query_vip_loan_fixed_rate_market() raises RequiredError when 'loan_coin' is missing.""" + params = { + "loan_coin": "loan_coin_example", + } + params["loan_coin"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'loan_coin'" + ): + self.client.query_vip_loan_fixed_rate_market(**params) + + def test_query_vip_loan_fixed_rate_market_server_error(self): + """Test that query_vip_loan_fixed_rate_market() raises an error when the server returns an error.""" + + params = { + "loan_coin": "loan_coin_example", + } + + mock_error = Exception("ResponseError") + self.client.query_vip_loan_fixed_rate_market = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_vip_loan_fixed_rate_market(**params) diff --git a/clients/vip_loan/tests/unit/rest_api/test_trade_api.py b/clients/vip_loan/tests/unit/rest_api/test_trade_api.py index 6c31b719..b22ec852 100644 --- a/clients/vip_loan/tests/unit/rest_api/test_trade_api.py +++ b/clients/vip_loan/tests/unit/rest_api/test_trade_api.py @@ -21,6 +21,7 @@ from binance_sdk_vip_loan.rest_api.api import TradeApi from binance_sdk_vip_loan.rest_api.models import VipLoanBorrowResponse +from binance_sdk_vip_loan.rest_api.models import VipLoanFixedRateBorrowResponse from binance_sdk_vip_loan.rest_api.models import VipLoanRenewResponse from binance_sdk_vip_loan.rest_api.models import VipLoanRepayResponse @@ -292,6 +293,261 @@ def test_vip_loan_borrow_server_error(self): with pytest.raises(Exception, match="ResponseError"): self.client.vip_loan_borrow(**params) + @patch("binance_common.utils.get_signature") + def test_vip_loan_fixed_rate_borrow_success(self, mock_get_signature): + """Test vip_loan_fixed_rate_borrow() successfully with required parameters only.""" + + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + + expected_response = { + "borrowCoin": "BUSD", + "borrowAmount": "100.5", + "actualReceivedAmount": "98.75", + "collateralCoin": "BNB,ETH,BTC", + "collateralAccountId": "12345,67890,13579", + "borrowInterestRate": "0.01501231", + "duration": "30Days", + "autoRepay": True, + "orderId": 123456789, + "status": "Succeeds", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.vip_loan_fixed_rate_borrow(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/loan/vip/fixed/borrow" in request_kwargs["url"] + assert request_kwargs["method"] == "POST" + assert normalized["supplyRequest"] == "supply_request_example" + assert normalized["borrowCoin"] == "borrow_coin_example" + assert normalized["loanTerm"] == 56 + assert normalized["borrowUid"] == 56 + assert normalized["collateralCoin"] == "collateral_coin_example" + assert normalized["collateralAccountId"] == "1" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(VipLoanFixedRateBorrowResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof or is_list or hasattr(VipLoanFixedRateBorrowResponse, "from_dict") + ): + expected = VipLoanFixedRateBorrowResponse.from_dict(expected_response) + else: + expected = VipLoanFixedRateBorrowResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_vip_loan_fixed_rate_borrow_success_with_optional_params( + self, mock_get_signature + ): + """Test vip_loan_fixed_rate_borrow() successfully with optional parameters.""" + + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + "auto_repay": False, + "recv_window": 5000, + } + + expected_response = { + "borrowCoin": "BUSD", + "borrowAmount": "100.5", + "actualReceivedAmount": "98.75", + "collateralCoin": "BNB,ETH,BTC", + "collateralAccountId": "12345,67890,13579", + "borrowInterestRate": "0.01501231", + "duration": "30Days", + "autoRepay": True, + "orderId": 123456789, + "status": "Succeeds", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.vip_loan_fixed_rate_borrow(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/loan/vip/fixed/borrow" in request_kwargs["url"] + assert request_kwargs["method"] == "POST" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(VipLoanFixedRateBorrowResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof or is_list or hasattr(VipLoanFixedRateBorrowResponse, "from_dict") + ): + expected = VipLoanFixedRateBorrowResponse.from_dict(expected_response) + else: + expected = VipLoanFixedRateBorrowResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_vip_loan_fixed_rate_borrow_missing_required_param_supply_request(self): + """Test that vip_loan_fixed_rate_borrow() raises RequiredError when 'supply_request' is missing.""" + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + params["supply_request"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'supply_request'" + ): + self.client.vip_loan_fixed_rate_borrow(**params) + + def test_vip_loan_fixed_rate_borrow_missing_required_param_borrow_coin(self): + """Test that vip_loan_fixed_rate_borrow() raises RequiredError when 'borrow_coin' is missing.""" + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + params["borrow_coin"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'borrow_coin'" + ): + self.client.vip_loan_fixed_rate_borrow(**params) + + def test_vip_loan_fixed_rate_borrow_missing_required_param_loan_term(self): + """Test that vip_loan_fixed_rate_borrow() raises RequiredError when 'loan_term' is missing.""" + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + params["loan_term"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'loan_term'" + ): + self.client.vip_loan_fixed_rate_borrow(**params) + + def test_vip_loan_fixed_rate_borrow_missing_required_param_borrow_uid(self): + """Test that vip_loan_fixed_rate_borrow() raises RequiredError when 'borrow_uid' is missing.""" + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + params["borrow_uid"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'borrow_uid'" + ): + self.client.vip_loan_fixed_rate_borrow(**params) + + def test_vip_loan_fixed_rate_borrow_missing_required_param_collateral_coin(self): + """Test that vip_loan_fixed_rate_borrow() raises RequiredError when 'collateral_coin' is missing.""" + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + params["collateral_coin"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'collateral_coin'" + ): + self.client.vip_loan_fixed_rate_borrow(**params) + + def test_vip_loan_fixed_rate_borrow_missing_required_param_collateral_account_id( + self, + ): + """Test that vip_loan_fixed_rate_borrow() raises RequiredError when 'collateral_account_id' is missing.""" + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + params["collateral_account_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'collateral_account_id'" + ): + self.client.vip_loan_fixed_rate_borrow(**params) + + def test_vip_loan_fixed_rate_borrow_server_error(self): + """Test that vip_loan_fixed_rate_borrow() raises an error when the server returns an error.""" + + params = { + "supply_request": "supply_request_example", + "borrow_coin": "borrow_coin_example", + "loan_term": 56, + "borrow_uid": 56, + "collateral_coin": "collateral_coin_example", + "collateral_account_id": "1", + } + + mock_error = Exception("ResponseError") + self.client.vip_loan_fixed_rate_borrow = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.vip_loan_fixed_rate_borrow(**params) + @patch("binance_common.utils.get_signature") def test_vip_loan_renew_success(self, mock_get_signature): """Test vip_loan_renew() successfully with required parameters only.""" diff --git a/clients/w3w_prediction/.gitignore b/clients/w3w_prediction/.gitignore new file mode 100644 index 00000000..2bde93d1 --- /dev/null +++ b/clients/w3w_prediction/.gitignore @@ -0,0 +1,23 @@ +build +dist + +__pycache__ +*.pyc +.tox +.python-version +.DS_Store +poetry.lock + +# Environments +.env +.venv +venv/ + +# IDE +.idea/ +.vscode/ + +# document build +docs/build/ + +examples/*.ini \ No newline at end of file diff --git a/clients/w3w_prediction/CHANGELOG.md b/clients/w3w_prediction/CHANGELOG.md new file mode 100644 index 00000000..7c97bd67 --- /dev/null +++ b/clients/w3w_prediction/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 1.0.0 - 2026-06-29 + +- Initial release diff --git a/clients/w3w_prediction/LICENCE b/clients/w3w_prediction/LICENCE new file mode 100644 index 00000000..d5f7a7cf --- /dev/null +++ b/clients/w3w_prediction/LICENCE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Binance + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/clients/w3w_prediction/README.md b/clients/w3w_prediction/README.md new file mode 100644 index 00000000..68b2d223 --- /dev/null +++ b/clients/w3w_prediction/README.md @@ -0,0 +1,172 @@ +# Binance Python W3W Prediction SDK + +[![Build Status](https://img.shields.io/github/actions/workflow/status/binance/binance-connector-python/ci.yaml)](https://github.com/binance/binance-connector-python/actions) +[![Open Issues](https://img.shields.io/github/issues/binance/binance-connector-python)](https://github.com/binance/binance-connector-python/issues) +[![Code Style: Black](https://img.shields.io/badge/code_style-black-black)](https://black.readthedocs.io/en/stable/) +[![PyPI version](https://img.shields.io/pypi/v/binance-sdk-w3w-prediction)](https://pypi.python.org/pypi/binance-sdk-w3w-prediction) +[![PyPI Downloads](https://img.shields.io/pypi/dm/binance-sdk-w3w-prediction.svg)](https://pypi.org/project/binance-sdk-w3w-prediction/) +[![Python version](https://img.shields.io/pypi/pyversions/binance-sdk-w3w-prediction)](https://www.python.org/downloads/) +[![Known Vulnerabilities](https://img.shields.io/badge/security-scanned-brightgreen)](https://github.com/binance/binance-connector-python/security) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + +This is a client library for the Binance W3W Prediction API, enabling developers to interact programmatically with Binance's W3W Prediction trading platform. The library provides tools to place and manage prediction market orders, query positions and transfer funds through the REST API: + +- [REST API](./src/binance_sdk_w3w_prediction/rest_api/rest_api.py) + +## Table of Contents + +- [Supported Features](#supported-features) +- [Installation](#installation) +- [Documentation](#documentation) +- [REST APIs](#rest-apis) +- [Testing](#testing) +- [Contributing](#contributing) +- [Licence](#licence) + +## Supported Features + +- REST API Endpoints: + - `/sapi/v1/w3w/wallet/prediction/*` +- Inclusion of test cases and examples for quick onboarding. + +## Installation + +To use this library, ensure your environment is running Python version **3.10** or later. + +```bash +pip install binance-sdk-w3w-prediction +``` + +## Documentation + +For detailed information, refer to the [Binance API Documentation](https://developers.binance.com/docs/w3w_prediction). + +### REST APIs + +All REST API endpoints are available through the [`rest_api`](./src/binance_sdk_w3w_prediction/rest_api/rest_api.py) module. The REST API enables you to fetch market data, manage trades, and access account information. Note that some endpoints require authentication using your Binance API credentials. + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_common.constants import W3W_PREDICTION_REST_API_PROD_URL +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +logging.basicConfig(level=logging.INFO) +configuration = ConfigurationRestAPI(api_key="your-api-key", api_secret="your-api-secret", base_path=W3W_PREDICTION_REST_API_PROD_URL) + +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + + data: ListPredictionCategoriesResponse = response.data() + logging.info(f"list_prediction_categories() response: {data}") +except Exception as e: + logging.error(f"list_prediction_categories() error: {e}") +``` + +More examples can be found in the [`examples/rest_api`](./examples/rest_api/) folder. + +#### Configuration Options + +The REST API supports the following advanced configuration options: + +- `timeout`: Timeout for requests in milliseconds (default: 1000 ms). +- `proxy`: Proxy configuration: + - `host`: Proxy server hostname. + - `port`: Proxy server port. + - `protocol`: Proxy protocol (http or https). + - `auth`: Proxy authentication credentials: + - `username`: Proxy username. + - `password`: Proxy password. +- `keep_alive`: Enable HTTP keep-alive (default: true). +- `compression`: Enable response compression (default: true). +- `retries`: Number of retry attempts for failed requests (default: 3). +- `backoff`: Delay in milliseconds between retries (default: 1000 ms). +- `https_agent`: Custom HTTPS agent for advanced TLS configuration. +- `private_key`: RSA or ED25519 private key for authentication. +- `private_key_passphrase`: Passphrase for the private key, if encrypted. + +##### Timeout + +You can configure a timeout for requests in milliseconds. If the request exceeds the specified timeout, it will be aborted. See the [Timeout example](./docs/rest_api/timeout.md) for detailed usage. + +##### Proxy + +The REST API supports HTTP/HTTPS proxy configurations. See the [Proxy example](./docs/rest_api/proxy.md) for detailed usage. + +##### Keep-Alive + +Enable HTTP keep-alive for persistent connections. See the [Keep-Alive example](./docs/rest_api/keepAlive.md) for detailed usage. + +##### Compression + +Enable or disable response compression. See the [Compression example](./docs/rest_api/compression.md) for detailed usage. + +##### Retries + +Configure the number of retry attempts and delay in milliseconds between retries for failed requests. See the [Retries example](./docs/rest_api/retries.md) for detailed usage. + +##### HTTPS Agent + +Customize the HTTPS agent for advanced TLS configurations. See the [HTTPS Agent example](./docs/rest_api/httpsAgent.md) for detailed usage. + +##### Key Pair Based Authentication + +The REST API supports key pair-based authentication for secure communication. You can use `RSA` or `ED25519` keys for signing requests. See the [Key Pair Based Authentication example](./docs/rest_api/key-pair-authentication.md) for detailed usage. + +##### Certificate Pinning + +To enhance security, you can use certificate pinning with the `https_agent` option in the configuration. This ensures the client only communicates with servers using specific certificates. See the [Certificate Pinning example](./docs/rest_api/certificate-pinning.md) for detailed usage. + +#### Error Handling + +The REST API provides detailed error types to help you handle issues effectively: + +- `ClientError`: Represents an error that occurred in the SDK client. +- `RequiredError`: Thrown when a required parameter is missing or undefined. +- `UnauthorizedError`: Indicates missing or invalid authentication credentials. +- `ForbiddenError`: Access to the requested resource is forbidden. +- `TooManyRequestsError`: Rate limit exceeded. +- `RateLimitBanError`: IP address banned for exceeding rate limits. +- `ServerError`: Internal server error, optionally includes a status code. +- `NetworkError`: Issues with network connectivity. +- `NotFoundError`: Resource not found. +- `BadRequestError`: Invalid request or one that cannot be served. + +See the [Error Handling example](./docs/rest_api/error-handling.md) for detailed usage. + +If `base_path` is not provided, it defaults to `https://api.binance.com`. + +## Testing + +To run the tests, ensure you have [Poetry](https://python-poetry.org/) installed, then execute the following commands: + +```bash +poetry install +poetry run pytest ./tests +``` + +The tests cover: +* REST API endpoints +* Error handling +* Edge cases + +## Contributing + +Contributions are welcome! + +Since this repository contains auto-generated code, we encourage you to start by opening a GitHub issue to discuss your ideas or suggest improvements. This helps ensure that changes align with the project's goals and auto-generation processes. + +To contribute: + +1. Open a GitHub issue describing your suggestion or the bug you've identified. +2. If it's determined that changes are necessary, the maintainers will merge the changes into the main branch. + +Please ensure that all tests pass if you're making a direct contribution. Submit a pull request only after discussing and confirming the change. + +Thank you for your contributions! + +## Licence + +This project is licensed under the MIT License. See the [LICENCE](./LICENCE) file for details. diff --git a/clients/w3w_prediction/docs/rest_api/certificate-pinning.md b/clients/w3w_prediction/docs/rest_api/certificate-pinning.md new file mode 100644 index 00000000..fe4d3fc5 --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/certificate-pinning.md @@ -0,0 +1,65 @@ +# Certificate Pinning + +```python +import ssl +import base64 +import hashlib + +from socket import create_connection +from OpenSSL.crypto import dump_publickey, load_certificate, FILETYPE_ASN1 + +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +PINNED_PUBLIC_KEY = "YOUR-PINNED-PUBLIC-KEY" +CA_CERT_PATH = "/path/to/certificate.pem" + +def verify_certificate(hostname, port=443): + """Retrieve the certificate, extract the public key, and verify its hash.""" + # Establish an SSL connection + context = ssl.create_default_context() + conn = context.wrap_socket(create_connection((hostname, port)), server_hostname=hostname) + + # Get the certificate in DER format + der_cert = conn.getpeercert(binary_form=True) + conn.close() + + # Convert DER to X.509 certificate + x509 = load_certificate(FILETYPE_ASN1, der_cert) + + # Extract public key + pubkey_der = dump_publickey(FILETYPE_ASN1, x509.get_pubkey()) + + # Compute the SHA-256 hash of the public key + public_key_hash = base64.b64encode(hashlib.sha256(pubkey_der).digest()).decode() + + # Validate public key hash against the pinned key + if public_key_hash != PINNED_PUBLIC_KEY: + raise ssl.SSLError(f"Certificate pinning validation failed: expected {PINNED_PUBLIC_KEY}, got {public_key_hash}") + +class PinnedSSLContext(ssl.SSLContext): + def __init__(self, hostname): + super().__init__(ssl.PROTOCOL_TLS_CLIENT) + self.verify_mode = ssl.CERT_REQUIRED + self.load_verify_locations(CA_CERT_PATH) + verify_certificate(hostname) + +ssl_context = PinnedSSLContext("api.binance.com") + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret", + https_agent=ssl_context, +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except ssl.SSLError as ssl_err: + print("SSL Certificate validation failed! Possible MITM attack.", ssl_err) +except Exception as err: + print("An error occurred:", err) +``` diff --git a/clients/w3w_prediction/docs/rest_api/compression.md b/clients/w3w_prediction/docs/rest_api/compression.md new file mode 100644 index 00000000..be20db10 --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/compression.md @@ -0,0 +1,21 @@ +# Compression Configuration + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret", + compression=False +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except Exception as e: + print(e) +``` diff --git a/clients/w3w_prediction/docs/rest_api/error-handling.md b/clients/w3w_prediction/docs/rest_api/error-handling.md new file mode 100644 index 00000000..16fae5e7 --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/error-handling.md @@ -0,0 +1,53 @@ +# Error Handling + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import ( + ClientError, + UnauthorizedError, + ForbiddenError, + TooManyRequestsError, + RequiredError, + RateLimitBanError, + ServerError, + NetworkError, + NotFoundError, + BadRequestError +) +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret", + keep_alive=False +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except ClientError as e: + print("Client error: Check your request parameters.", e) +except RequiredError as e: + print("Missing required parameters.", e) +except UnauthorizedError as e: + print("Unauthorized: Invalid API credentials.", e) +except ForbiddenError as e: + print("Forbidden: Check your API key permissions.", e) +except TooManyRequestsError as e: + print("Rate limit exceeded. Please wait and try again.", e) +except RateLimitBanError as e: + print("IP address banned due to excessive rate limits.", e) +except ServerError as e: + print("Server error: Try again later.", e) +except NetworkError as e: + print("Network error: Check your internet connection.", e) +except NotFoundError as e: + print("Resource not found.", e) +except BadRequestError as e: + print("Bad request: Verify your input parameters.", e) +except Exception as e: + print("An unexpected error occurred:", e) +``` diff --git a/clients/w3w_prediction/docs/rest_api/httpsAgent.md b/clients/w3w_prediction/docs/rest_api/httpsAgent.md new file mode 100644 index 00000000..04d02f0b --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/httpsAgent.md @@ -0,0 +1,23 @@ +# HTTPS Agent Configuration + +```python +import ssl + +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret", + https_agent=ssl.create_default_context() +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except Exception as e: + print(e) +``` diff --git a/clients/w3w_prediction/docs/rest_api/keepAlive.md b/clients/w3w_prediction/docs/rest_api/keepAlive.md new file mode 100644 index 00000000..88275cb2 --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/keepAlive.md @@ -0,0 +1,21 @@ +# Keep-Alive Configuration + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret", + keep_alive=False +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except Exception as e: + print(e) +``` diff --git a/clients/w3w_prediction/docs/rest_api/key-pair-authentication.md b/clients/w3w_prediction/docs/rest_api/key-pair-authentication.md new file mode 100644 index 00000000..8a04fd7c --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/key-pair-authentication.md @@ -0,0 +1,25 @@ +# Key Pair Based Authentication + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +with open("/path/to/private_key.pem", "r") as key_file: + private_key = key_file.read() +private_key_passphrase = "your-passphrase" + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + private_key=private_key, + private_key_passphrase=private_key_passphrase, +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except Exception as e: + print(e) +``` diff --git a/clients/w3w_prediction/docs/rest_api/proxy.md b/clients/w3w_prediction/docs/rest_api/proxy.md new file mode 100644 index 00000000..b8da0043 --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/proxy.md @@ -0,0 +1,29 @@ +# Proxy Configuration + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret", + proxy = { + "host": "127.0.0.1", + "port": 8080, + "protocol": "http", # or 'https' + "auth": { + "username": "proxy-user", + "password": "proxy-password", + }, + } +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except Exception as e: + print(e) +``` diff --git a/clients/w3w_prediction/docs/rest_api/retries.md b/clients/w3w_prediction/docs/rest_api/retries.md new file mode 100644 index 00000000..9fb23098 --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/retries.md @@ -0,0 +1,21 @@ +# Retries Configuration + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret" + retries=2 +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except Exception as e: + print(e) +``` diff --git a/clients/w3w_prediction/docs/rest_api/timeout.md b/clients/w3w_prediction/docs/rest_api/timeout.md new file mode 100644 index 00000000..576aa969 --- /dev/null +++ b/clients/w3w_prediction/docs/rest_api/timeout.md @@ -0,0 +1,20 @@ +# Timeout + +```python +from binance_common.configuration import ConfigurationRestAPI +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse + +configuration = ConfigurationRestAPI( + api_key="your-api-key", + api_secret="your-api-secret" +) +client = W3wPrediction(config_rest_api=configuration) + +try: + response = client.rest_api.list_prediction_categories() + data: ListPredictionCategoriesResponse = response.data() + print(data) +except Exception as e: + logging.error(f"error: {e}") +``` diff --git a/clients/w3w_prediction/examples/rest_api/MarketData/get_market_detail.py b/clients/w3w_prediction/examples/rest_api/MarketData/get_market_detail.py new file mode 100644 index 00000000..7232cc37 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/MarketData/get_market_detail.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def get_market_detail(): + try: + response = client.rest_api.get_market_detail(market_topic_id=4229564) + + rate_limits = response.rate_limits + logging.info(f"get_market_detail() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"get_market_detail() response: {data}") + except Exception as e: + logging.error(f"get_market_detail() error: {e}") + + +if __name__ == "__main__": + get_market_detail() diff --git a/clients/w3w_prediction/examples/rest_api/MarketData/list_prediction_categories.py b/clients/w3w_prediction/examples/rest_api/MarketData/list_prediction_categories.py new file mode 100644 index 00000000..7ee2c3b6 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/MarketData/list_prediction_categories.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def list_prediction_categories(): + try: + response = client.rest_api.list_prediction_categories() + + rate_limits = response.rate_limits + logging.info(f"list_prediction_categories() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"list_prediction_categories() response: {data}") + except Exception as e: + logging.error(f"list_prediction_categories() error: {e}") + + +if __name__ == "__main__": + list_prediction_categories() diff --git a/clients/w3w_prediction/examples/rest_api/MarketData/list_prediction_markets.py b/clients/w3w_prediction/examples/rest_api/MarketData/list_prediction_markets.py new file mode 100644 index 00000000..e743d063 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/MarketData/list_prediction_markets.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def list_prediction_markets(): + try: + response = client.rest_api.list_prediction_markets() + + rate_limits = response.rate_limits + logging.info(f"list_prediction_markets() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"list_prediction_markets() response: {data}") + except Exception as e: + logging.error(f"list_prediction_markets() error: {e}") + + +if __name__ == "__main__": + list_prediction_markets() diff --git a/clients/w3w_prediction/examples/rest_api/MarketData/market_search.py b/clients/w3w_prediction/examples/rest_api/MarketData/market_search.py new file mode 100644 index 00000000..cc0109c9 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/MarketData/market_search.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def market_search(): + try: + response = client.rest_api.market_search( + query="BTC price", + ) + + rate_limits = response.rate_limits + logging.info(f"market_search() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"market_search() response: {data}") + except Exception as e: + logging.error(f"market_search() error: {e}") + + +if __name__ == "__main__": + market_search() diff --git a/clients/w3w_prediction/examples/rest_api/MarketData/query_last_trade_price.py b/clients/w3w_prediction/examples/rest_api/MarketData/query_last_trade_price.py new file mode 100644 index 00000000..4f6ed007 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/MarketData/query_last_trade_price.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_last_trade_price(): + try: + response = client.rest_api.query_last_trade_price(market_id=5567895) + + rate_limits = response.rate_limits + logging.info(f"query_last_trade_price() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_last_trade_price() response: {data}") + except Exception as e: + logging.error(f"query_last_trade_price() error: {e}") + + +if __name__ == "__main__": + query_last_trade_price() diff --git a/clients/w3w_prediction/examples/rest_api/MarketData/query_order_book.py b/clients/w3w_prediction/examples/rest_api/MarketData/query_order_book.py new file mode 100644 index 00000000..88b05b78 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/MarketData/query_order_book.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_order_book(): + try: + response = client.rest_api.query_order_book( + vendor="predict_fun", market_id=5567895, token_id="112233" + ) + + rate_limits = response.rate_limits + logging.info(f"query_order_book() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_order_book() response: {data}") + except Exception as e: + logging.error(f"query_order_book() error: {e}") + + +if __name__ == "__main__": + query_order_book() diff --git a/clients/w3w_prediction/examples/rest_api/Position/get_position_by_token.py b/clients/w3w_prediction/examples/rest_api/Position/get_position_by_token.py new file mode 100644 index 00000000..ec57988d --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Position/get_position_by_token.py @@ -0,0 +1,41 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def get_position_by_token(): + try: + response = client.rest_api.get_position_by_token( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + token_id="112233", + ) + + rate_limits = response.rate_limits + logging.info(f"get_position_by_token() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"get_position_by_token() response: {data}") + except Exception as e: + logging.error(f"get_position_by_token() error: {e}") + + +if __name__ == "__main__": + get_position_by_token() diff --git a/clients/w3w_prediction/examples/rest_api/Position/query_pn_l.py b/clients/w3w_prediction/examples/rest_api/Position/query_pn_l.py new file mode 100644 index 00000000..803470f2 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Position/query_pn_l.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_pn_l(): + try: + response = client.rest_api.query_pn_l( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + ) + + rate_limits = response.rate_limits + logging.info(f"query_pn_l() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_pn_l() response: {data}") + except Exception as e: + logging.error(f"query_pn_l() error: {e}") + + +if __name__ == "__main__": + query_pn_l() diff --git a/clients/w3w_prediction/examples/rest_api/Position/query_positions.py b/clients/w3w_prediction/examples/rest_api/Position/query_positions.py new file mode 100644 index 00000000..b34e9235 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Position/query_positions.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_positions(): + try: + response = client.rest_api.query_positions( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + ) + + rate_limits = response.rate_limits + logging.info(f"query_positions() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_positions() response: {data}") + except Exception as e: + logging.error(f"query_positions() error: {e}") + + +if __name__ == "__main__": + query_positions() diff --git a/clients/w3w_prediction/examples/rest_api/Position/query_positions_by_filter.py b/clients/w3w_prediction/examples/rest_api/Position/query_positions_by_filter.py new file mode 100644 index 00000000..b0ba748c --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Position/query_positions_by_filter.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_positions_by_filter(): + try: + response = client.rest_api.query_positions_by_filter() + + rate_limits = response.rate_limits + logging.info(f"query_positions_by_filter() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_positions_by_filter() response: {data}") + except Exception as e: + logging.error(f"query_positions_by_filter() error: {e}") + + +if __name__ == "__main__": + query_positions_by_filter() diff --git a/clients/w3w_prediction/examples/rest_api/Position/query_settled_position_history.py b/clients/w3w_prediction/examples/rest_api/Position/query_settled_position_history.py new file mode 100644 index 00000000..95abece5 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Position/query_settled_position_history.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_settled_position_history(): + try: + response = client.rest_api.query_settled_position_history( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + ) + + rate_limits = response.rate_limits + logging.info(f"query_settled_position_history() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_settled_position_history() response: {data}") + except Exception as e: + logging.error(f"query_settled_position_history() error: {e}") + + +if __name__ == "__main__": + query_settled_position_history() diff --git a/clients/w3w_prediction/examples/rest_api/Redeem/batch_redeem.py b/clients/w3w_prediction/examples/rest_api/Redeem/batch_redeem.py new file mode 100644 index 00000000..c6098e70 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Redeem/batch_redeem.py @@ -0,0 +1,42 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def batch_redeem(): + try: + response = client.rest_api.batch_redeem( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + wallet_id="5b5c1ec3be4e4416a5872b21c1ca5d20", + token_ids=["112233"], + ) + + rate_limits = response.rate_limits + logging.info(f"batch_redeem() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"batch_redeem() response: {data}") + except Exception as e: + logging.error(f"batch_redeem() error: {e}") + + +if __name__ == "__main__": + batch_redeem() diff --git a/clients/w3w_prediction/examples/rest_api/Redeem/get_redeem_status.py b/clients/w3w_prediction/examples/rest_api/Redeem/get_redeem_status.py new file mode 100644 index 00000000..26b32290 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Redeem/get_redeem_status.py @@ -0,0 +1,41 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def get_redeem_status(): + try: + response = client.rest_api.get_redeem_status( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + tx_hash="0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + ) + + rate_limits = response.rate_limits + logging.info(f"get_redeem_status() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"get_redeem_status() response: {data}") + except Exception as e: + logging.error(f"get_redeem_status() error: {e}") + + +if __name__ == "__main__": + get_redeem_status() diff --git a/clients/w3w_prediction/examples/rest_api/Trade/batch_cancel_orders.py b/clients/w3w_prediction/examples/rest_api/Trade/batch_cancel_orders.py new file mode 100644 index 00000000..33cfb0ec --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Trade/batch_cancel_orders.py @@ -0,0 +1,41 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def batch_cancel_orders(): + try: + response = client.rest_api.batch_cancel_orders( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + wallet_id="5b5c1ec3be4e4416a5872b21c1ca5d20", + ) + + rate_limits = response.rate_limits + logging.info(f"batch_cancel_orders() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"batch_cancel_orders() response: {data}") + except Exception as e: + logging.error(f"batch_cancel_orders() error: {e}") + + +if __name__ == "__main__": + batch_cancel_orders() diff --git a/clients/w3w_prediction/examples/rest_api/Trade/get_quote.py b/clients/w3w_prediction/examples/rest_api/Trade/get_quote.py new file mode 100644 index 00000000..9ca890e0 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Trade/get_quote.py @@ -0,0 +1,47 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) +from binance_sdk_w3w_prediction.rest_api.models import GetQuoteSideEnum +from binance_sdk_w3w_prediction.rest_api.models import GetQuoteOrderTypeEnum + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def get_quote(): + try: + response = client.rest_api.get_quote( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + token_id="112233", + side=GetQuoteSideEnum["BUY"].value, + amount_in="1000000000000000000", + order_type=GetQuoteOrderTypeEnum["MARKET"].value, + slippage_bps=1200, + ) + + rate_limits = response.rate_limits + logging.info(f"get_quote() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"get_quote() response: {data}") + except Exception as e: + logging.error(f"get_quote() error: {e}") + + +if __name__ == "__main__": + get_quote() diff --git a/clients/w3w_prediction/examples/rest_api/Trade/place_order.py b/clients/w3w_prediction/examples/rest_api/Trade/place_order.py new file mode 100644 index 00000000..f494edf9 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Trade/place_order.py @@ -0,0 +1,48 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) +from binance_sdk_w3w_prediction.rest_api.models import PlaceOrderAccountTypeEnum +from binance_sdk_w3w_prediction.rest_api.models import PlaceOrderOrderTypeEnum + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def place_order(): + try: + response = client.rest_api.place_order( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + wallet_id="5b5c1ec3be4e4416a5872b21c1ca5d20", + quote_id="q_20260525_abc123xyz", + time_in_force="FOK", + account_type=PlaceOrderAccountTypeEnum["SPOT"].value, + order_type=PlaceOrderOrderTypeEnum["MARKET"].value, + slippage_bps=1200, + ) + + rate_limits = response.rate_limits + logging.info(f"place_order() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"place_order() response: {data}") + except Exception as e: + logging.error(f"place_order() error: {e}") + + +if __name__ == "__main__": + place_order() diff --git a/clients/w3w_prediction/examples/rest_api/Trade/query_active_orders.py b/clients/w3w_prediction/examples/rest_api/Trade/query_active_orders.py new file mode 100644 index 00000000..6b2f0a68 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Trade/query_active_orders.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_active_orders(): + try: + response = client.rest_api.query_active_orders( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + ) + + rate_limits = response.rate_limits + logging.info(f"query_active_orders() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_active_orders() response: {data}") + except Exception as e: + logging.error(f"query_active_orders() error: {e}") + + +if __name__ == "__main__": + query_active_orders() diff --git a/clients/w3w_prediction/examples/rest_api/Trade/query_order_history.py b/clients/w3w_prediction/examples/rest_api/Trade/query_order_history.py new file mode 100644 index 00000000..f4242c96 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Trade/query_order_history.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_order_history(): + try: + response = client.rest_api.query_order_history( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + ) + + rate_limits = response.rate_limits + logging.info(f"query_order_history() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_order_history() response: {data}") + except Exception as e: + logging.error(f"query_order_history() error: {e}") + + +if __name__ == "__main__": + query_order_history() diff --git a/clients/w3w_prediction/examples/rest_api/Transfer/create_inbound_transfer.py b/clients/w3w_prediction/examples/rest_api/Transfer/create_inbound_transfer.py new file mode 100644 index 00000000..e7ffb4fa --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Transfer/create_inbound_transfer.py @@ -0,0 +1,46 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) +from binance_sdk_w3w_prediction.rest_api.models import ( + CreateInboundTransferAccountTypeEnum, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def create_inbound_transfer(): + try: + response = client.rest_api.create_inbound_transfer( + wallet_id="5b5c1ec3be4e4416a5872b21c1ca5d20", + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + from_token_amount="1000000000000000000", + account_type=CreateInboundTransferAccountTypeEnum["SPOT"].value, + ) + + rate_limits = response.rate_limits + logging.info(f"create_inbound_transfer() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"create_inbound_transfer() response: {data}") + except Exception as e: + logging.error(f"create_inbound_transfer() error: {e}") + + +if __name__ == "__main__": + create_inbound_transfer() diff --git a/clients/w3w_prediction/examples/rest_api/Transfer/create_outbound_transfer.py b/clients/w3w_prediction/examples/rest_api/Transfer/create_outbound_transfer.py new file mode 100644 index 00000000..39aec0e0 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Transfer/create_outbound_transfer.py @@ -0,0 +1,50 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) +from binance_sdk_w3w_prediction.rest_api.models import ( + CreateOutboundTransferAccountTypeEnum, +) +from binance_sdk_w3w_prediction.rest_api.models import ( + CreateOutboundTransferSourceBizEnum, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def create_outbound_transfer(): + try: + response = client.rest_api.create_outbound_transfer( + wallet_id="5b5c1ec3be4e4416a5872b21c1ca5d20", + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + from_token_amount="1000000000000000000", + account_type=CreateOutboundTransferAccountTypeEnum["SPOT"].value, + source_biz=CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + ) + + rate_limits = response.rate_limits + logging.info(f"create_outbound_transfer() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"create_outbound_transfer() response: {data}") + except Exception as e: + logging.error(f"create_outbound_transfer() error: {e}") + + +if __name__ == "__main__": + create_outbound_transfer() diff --git a/clients/w3w_prediction/examples/rest_api/Transfer/query_transfer_list.py b/clients/w3w_prediction/examples/rest_api/Transfer/query_transfer_list.py new file mode 100644 index 00000000..2874f02d --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Transfer/query_transfer_list.py @@ -0,0 +1,42 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_transfer_list(): + try: + response = client.rest_api.query_transfer_list( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + start_date="2026-05-01", + end_date="2026-05-25", + ) + + rate_limits = response.rate_limits + logging.info(f"query_transfer_list() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_transfer_list() response: {data}") + except Exception as e: + logging.error(f"query_transfer_list() error: {e}") + + +if __name__ == "__main__": + query_transfer_list() diff --git a/clients/w3w_prediction/examples/rest_api/Transfer/query_transfer_status.py b/clients/w3w_prediction/examples/rest_api/Transfer/query_transfer_status.py new file mode 100644 index 00000000..66300e50 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Transfer/query_transfer_status.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_transfer_status(): + try: + response = client.rest_api.query_transfer_status( + transfer_id="tf_20260525_out_001", + ) + + rate_limits = response.rate_limits + logging.info(f"query_transfer_status() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_transfer_status() response: {data}") + except Exception as e: + logging.error(f"query_transfer_status() error: {e}") + + +if __name__ == "__main__": + query_transfer_status() diff --git a/clients/w3w_prediction/examples/rest_api/Wallet/get_portfolio.py b/clients/w3w_prediction/examples/rest_api/Wallet/get_portfolio.py new file mode 100644 index 00000000..b34cc4f2 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Wallet/get_portfolio.py @@ -0,0 +1,40 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def get_portfolio(): + try: + response = client.rest_api.get_portfolio( + wallet_address="0x12e32db8817e292508c34111cbc4b23340df542c", + ) + + rate_limits = response.rate_limits + logging.info(f"get_portfolio() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"get_portfolio() response: {data}") + except Exception as e: + logging.error(f"get_portfolio() error: {e}") + + +if __name__ == "__main__": + get_portfolio() diff --git a/clients/w3w_prediction/examples/rest_api/Wallet/get_quota_status.py b/clients/w3w_prediction/examples/rest_api/Wallet/get_quota_status.py new file mode 100644 index 00000000..e9aa6422 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Wallet/get_quota_status.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def get_quota_status(): + try: + response = client.rest_api.get_quota_status() + + rate_limits = response.rate_limits + logging.info(f"get_quota_status() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"get_quota_status() response: {data}") + except Exception as e: + logging.error(f"get_quota_status() error: {e}") + + +if __name__ == "__main__": + get_quota_status() diff --git a/clients/w3w_prediction/examples/rest_api/Wallet/list_prediction_wallets.py b/clients/w3w_prediction/examples/rest_api/Wallet/list_prediction_wallets.py new file mode 100644 index 00000000..dbac6c16 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Wallet/list_prediction_wallets.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def list_prediction_wallets(): + try: + response = client.rest_api.list_prediction_wallets() + + rate_limits = response.rate_limits + logging.info(f"list_prediction_wallets() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"list_prediction_wallets() response: {data}") + except Exception as e: + logging.error(f"list_prediction_wallets() error: {e}") + + +if __name__ == "__main__": + list_prediction_wallets() diff --git a/clients/w3w_prediction/examples/rest_api/Wallet/query_payment_option_balances.py b/clients/w3w_prediction/examples/rest_api/Wallet/query_payment_option_balances.py new file mode 100644 index 00000000..d82e4305 --- /dev/null +++ b/clients/w3w_prediction/examples/rest_api/Wallet/query_payment_option_balances.py @@ -0,0 +1,38 @@ +import os +import logging + +from binance_sdk_w3w_prediction.w3w_prediction import ( + W3wPrediction, + ConfigurationRestAPI, + W3W_PREDICTION_REST_API_PROD_URL, +) + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Create configuration for the REST API +configuration_rest_api = ConfigurationRestAPI( + api_key=os.getenv("API_KEY", ""), + api_secret=os.getenv("API_SECRET", ""), + base_path=os.getenv("BASE_PATH", W3W_PREDICTION_REST_API_PROD_URL), +) + +# Initialize W3wPrediction client +client = W3wPrediction(config_rest_api=configuration_rest_api) + + +def query_payment_option_balances(): + try: + response = client.rest_api.query_payment_option_balances() + + rate_limits = response.rate_limits + logging.info(f"query_payment_option_balances() rate limits: {rate_limits}") + + data = response.data() + logging.info(f"query_payment_option_balances() response: {data}") + except Exception as e: + logging.error(f"query_payment_option_balances() error: {e}") + + +if __name__ == "__main__": + query_payment_option_balances() diff --git a/clients/w3w_prediction/pyproject.toml b/clients/w3w_prediction/pyproject.toml new file mode 100644 index 00000000..a270946f --- /dev/null +++ b/clients/w3w_prediction/pyproject.toml @@ -0,0 +1,39 @@ +[tool.poetry] +name = "binance-sdk-w3w-prediction" +version = "1.0.0" +description = "Official Binance W3wPrediction Connector - A lightweight library that provides a convenient interface to Binance's W3wPrediction REST API" +authors = ["Binance"] +license = "MIT" +include = ["CHANGELOG.md", "LICENSE"] +packages = [ + { include = "binance_sdk_w3w_prediction", from = "src" } +] + +[tool.poetry.dependencies] +python = ">=3.10,<3.15" +requests = ">=2.34.2" +urllib3 = ">=2.7.0" +pydantic = ">=2.10.0" +websockets = "^15.0.1" +websocket-client = ">=1.6.3" +pycryptodome = "^3.17" +aiohttp = "^3.14.0" +binance-common = "4.0.2" + +[tool.poetry.extras] +dev = ["pytest"] + +[tool.poetry.group.dev.dependencies] +tox = "^4.27.0" +pytest-asyncio = "^1.0.0" +black = "^25.1.0" +ruff = "^0.12.0" +pytest = ">=8.4.1" + +[tool.ruff] +exclude = [".git", ".tox", "build", "dist"] +lint.ignore = ["E741"] + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/__init__.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/__init__.py new file mode 100644 index 00000000..98887220 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/__init__.py @@ -0,0 +1,31 @@ +from binance_sdk_w3w_prediction.w3w_prediction import W3wPrediction +from binance_common.errors import ( + ClientError, + RequiredError, + UnauthorizedError, + ForbiddenError, + TooManyRequestsError, + RateLimitBanError, + ServerError, + NetworkError, + NotFoundError, + BadRequestError, +) +from binance_common.constants import ( + W3W_PREDICTION_REST_API_PROD_URL, +) + +__all__ = [ + "W3wPrediction", + "W3W_PREDICTION_REST_API_PROD_URL", + "ClientError", + "RequiredError", + "UnauthorizedError", + "ForbiddenError", + "TooManyRequestsError", + "RateLimitBanError", + "ServerError", + "NetworkError", + "NotFoundError", + "BadRequestError", +] diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/metadata.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/metadata.py new file mode 100644 index 00000000..5b20fbfb --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/metadata.py @@ -0,0 +1 @@ +NAME = "binance-sdk-w3w-prediction" diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/py.typed b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/__init__.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/__init__.py new file mode 100644 index 00000000..3db26d68 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/__init__.py @@ -0,0 +1,13 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from .rest_api import W3wPredictionRestAPI + +__all__ = ["W3wPredictionRestAPI"] diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/__init__.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/__init__.py new file mode 100644 index 00000000..263317a7 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/__init__.py @@ -0,0 +1,16 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from .market_data_api import MarketDataApi as MarketDataApi +from .position_api import PositionApi as PositionApi +from .redeem_api import RedeemApi as RedeemApi +from .trade_api import TradeApi as TradeApi +from .transfer_api import TransferApi as TransferApi +from .wallet_api import WalletApi as WalletApi diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/market_data_api.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/market_data_api.py new file mode 100644 index 00000000..ae41740d --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/market_data_api.py @@ -0,0 +1,334 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from typing import Optional, Union +from requests import Session +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.models import ApiResponse +from binance_common.signature import Signers +from binance_common.utils import send_request + +from ..models import GetMarketDetailResponse +from ..models import ListPredictionCategoriesResponse +from ..models import ListPredictionMarketsResponse +from ..models import MarketSearchResponse +from ..models import QueryLastTradePriceResponse +from ..models import QueryOrderBookResponse + + +from ..models import ListPredictionMarketsSortByEnum +from ..models import ListPredictionMarketsOrderByEnum + + +class MarketDataApi: + """API Client for MarketDataApi endpoints.""" + + def __init__( + self, + configuration: ConfigurationRestAPI = None, + session: Session = None, + signer: Signers = None, + ) -> None: + self._configuration = configuration + self._session = session + self._signer = signer + + def get_market_detail( + self, + market_topic_id: Union[int, None], + ) -> ApiResponse[GetMarketDetailResponse]: + """ + Get Market Detail + GET /sapi/v1/w3w/wallet/prediction/market/detail + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/market-data#get-market-detail + + Get full details for a specific prediction market topic, including variant data and timeline. + + Weight(IP): 200 + + Args: + market_topic_id (Union[int, None]): Market topic ID. Must be > 0 + + Returns: + ApiResponse[GetMarketDetailResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if market_topic_id is None: + raise RequiredError( + field="market_topic_id", + error_message="Missing required parameter 'market_topic_id'", + ) + + body = {} + payload = {"market_topic_id": market_topic_id} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/market/detail", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=GetMarketDetailResponse, + is_signed=True, + signer=self._signer, + ) + + def list_prediction_categories( + self, + ) -> ApiResponse[ListPredictionCategoriesResponse]: + """ + List Prediction Categories + GET /sapi/v1/w3w/wallet/prediction/category/list + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/market-data#list-prediction-categories + + Get all available prediction market categories (L1 and L2). + + Weight(IP): 200 + + Args: + + Returns: + ApiResponse[ListPredictionCategoriesResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + body = None + payload = None + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/category/list", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=ListPredictionCategoriesResponse, + is_signed=True, + signer=self._signer, + ) + + def list_prediction_markets( + self, + l1_category: Optional[str] = None, + l2_category: Optional[str] = None, + sort_by: Optional[ListPredictionMarketsSortByEnum] = None, + order_by: Optional[ListPredictionMarketsOrderByEnum] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + ) -> ApiResponse[ListPredictionMarketsResponse]: + """ + List Prediction Markets + GET /sapi/v1/w3w/wallet/prediction/market/list + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/market-data#list-prediction-markets + + Get a paginated list of prediction market topics, with optional category and sort filters. + + Weight(IP): 200 + + Args: + l1_category (Optional[str] = None): Level-1 category filter + l2_category (Optional[str] = None): Level-2 category filter + sort_by (Optional[ListPredictionMarketsSortByEnum] = None): Sort field. Enum: `RECOMMENDED`, `VOLUME`, `PARTICIPANTS`, `CREATED_TIME`, `END_DATE` + order_by (Optional[ListPredictionMarketsOrderByEnum] = None): Sort direction. Enum: `ASC`, `DESC` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + + Returns: + ApiResponse[ListPredictionMarketsResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + body = {} + payload = { + "l1_category": l1_category, + "l2_category": l2_category, + "sort_by": sort_by, + "order_by": order_by, + "offset": offset, + "limit": limit, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/market/list", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=ListPredictionMarketsResponse, + is_signed=True, + signer=self._signer, + ) + + def market_search( + self, + query: Union[str, None], + top_k: Optional[int] = None, + ) -> ApiResponse[MarketSearchResponse]: + """ + Market Search + GET /sapi/v1/w3w/wallet/prediction/market/search + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/market-data#market-search + + Semantic search for prediction market topics by keyword. + + Weight(IP): 200 + + Args: + query (Union[str, None]): Search keyword. Not blank + top_k (Optional[int] = None): Max number of results to return. Default `20`, range 1–50 + + Returns: + ApiResponse[MarketSearchResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if query is None: + raise RequiredError( + field="query", error_message="Missing required parameter 'query'" + ) + + body = {} + payload = {"query": query, "top_k": top_k} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/market/search", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=MarketSearchResponse, + is_signed=True, + signer=self._signer, + ) + + def query_last_trade_price( + self, + market_id: Union[int, None], + ) -> ApiResponse[QueryLastTradePriceResponse]: + """ + Query Last Trade Price + GET /sapi/v1/w3w/wallet/prediction/order-book/last-trade-price + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/market-data#query-last-trade-price + + Get the most recent trade price for a prediction market. + + Weight(IP): 200 + + Args: + market_id (Union[int, None]): Market ID. Must be > 0 + + Returns: + ApiResponse[QueryLastTradePriceResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if market_id is None: + raise RequiredError( + field="market_id", + error_message="Missing required parameter 'market_id'", + ) + + body = {} + payload = {"market_id": market_id} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/order-book/last-trade-price", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryLastTradePriceResponse, + is_signed=True, + signer=self._signer, + ) + + def query_order_book( + self, + vendor: Union[str, None], + market_id: Union[int, None], + token_id: Union[str, None], + ) -> ApiResponse[QueryOrderBookResponse]: + """ + Query Order Book + GET /sapi/v1/w3w/wallet/prediction/order-book + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/market-data#query-order-book + + Get the current order book (bids and asks) for a specific prediction market outcome token. + + Weight(IP): 200 + + Args: + vendor (Union[str, None]): Vendor identifier (e.g. `predict_fun`) + market_id (Union[int, None]): Market ID. Must be > 0 + token_id (Union[str, None]): Prediction outcome token ID + + Returns: + ApiResponse[QueryOrderBookResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if vendor is None: + raise RequiredError( + field="vendor", error_message="Missing required parameter 'vendor'" + ) + if market_id is None: + raise RequiredError( + field="market_id", + error_message="Missing required parameter 'market_id'", + ) + if token_id is None: + raise RequiredError( + field="token_id", error_message="Missing required parameter 'token_id'" + ) + + body = {} + payload = {"vendor": vendor, "market_id": market_id, "token_id": token_id} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/order-book", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryOrderBookResponse, + is_signed=True, + signer=self._signer, + ) diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/position_api.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/position_api.py new file mode 100644 index 00000000..5b95f20a --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/position_api.py @@ -0,0 +1,345 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from typing import Optional, Union +from requests import Session +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.models import ApiResponse +from binance_common.signature import Signers +from binance_common.utils import send_request + +from ..models import GetPositionByTokenResponse +from ..models import QueryPnLResponse +from ..models import QueryPositionsResponse +from ..models import QueryPositionsByFilterResponse +from ..models import QuerySettledPositionHistoryResponse + + +class PositionApi: + """API Client for PositionApi endpoints.""" + + def __init__( + self, + configuration: ConfigurationRestAPI = None, + session: Session = None, + signer: Signers = None, + ) -> None: + self._configuration = configuration + self._session = session + self._signer = signer + + def get_position_by_token( + self, + wallet_address: Union[str, None], + token_id: Union[str, None], + recv_window: Optional[int] = None, + ) -> ApiResponse[GetPositionByTokenResponse]: + """ + Get Position by Token + GET /sapi/v1/w3w/wallet/prediction/position/token + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/position#get-position-by-token + + Get the authenticated user's position detail for a specific prediction token. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Union[str, None]): Prediction outcome token ID + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetPositionByTokenResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if token_id is None: + raise RequiredError( + field="token_id", error_message="Missing required parameter 'token_id'" + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "token_id": token_id, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/position/token", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=GetPositionByTokenResponse, + is_signed=True, + signer=self._signer, + ) + + def query_pn_l( + self, + wallet_address: Union[str, None], + token_id: Optional[str] = None, + market_id: Optional[int] = None, + market_topic_id: Optional[int] = None, + active_only: Optional[bool] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPnLResponse]: + """ + Query PnL + GET /sapi/v1/w3w/wallet/prediction/pnl/query + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/position#query-pn-l + + Query profit and loss records for the authenticated user's prediction positions. When `tokenId` is provided, returns a single record in `pnl`; otherwise returns a list in `pnlList`. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Optional[str] = None): Filter by prediction token ID + market_id (Optional[int] = None): Filter by market ID. Must be > 0 + market_topic_id (Optional[int] = None): Filter by market topic ID. Must be > 0 + active_only (Optional[bool] = None): If `true`, return only active (unresolved) positions + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPnLResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "token_id": token_id, + "market_id": market_id, + "market_topic_id": market_topic_id, + "active_only": active_only, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/pnl/query", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryPnLResponse, + is_signed=True, + signer=self._signer, + ) + + def query_positions( + self, + wallet_address: Union[str, None], + tab: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPositionsResponse]: + """ + Query Positions + GET /sapi/v1/w3w/wallet/prediction/position/list + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/position#query-positions + + Get the authenticated user's prediction token positions with portfolio summary and tab-based filtering. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + tab (Optional[str] = None): Position status tab. Values from `PositionQueryType`. Default `ONGOING` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPositionsResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "tab": tab, + "offset": offset, + "limit": limit, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/position/list", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryPositionsResponse, + is_signed=True, + signer=self._signer, + ) + + def query_positions_by_filter( + self, + wallet_address: Optional[str] = None, + market_topic_id: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPositionsByFilterResponse]: + """ + Query Positions by Filter + GET /sapi/v1/w3w/wallet/prediction/position/filter + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/position#query-positions-by-filter + + Get prediction positions filtered by wallet address and/or market topic ID. Both parameters are optional. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Optional[str] = None): User's prediction wallet address + market_topic_id (Optional[int] = None): Filter by market topic ID + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPositionsByFilterResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + body = {} + payload = { + "wallet_address": wallet_address, + "market_topic_id": market_topic_id, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/position/filter", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryPositionsByFilterResponse, + is_signed=True, + signer=self._signer, + ) + + def query_settled_position_history( + self, + wallet_address: Union[str, None], + l1_category: Optional[str] = None, + result: Optional[int] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QuerySettledPositionHistoryResponse]: + """ + Query Settled Position History + GET /sapi/v1/w3w/wallet/prediction/position/settled-history + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/position#query-settled-position-history + + Get the authenticated user's settled (resolved) prediction position history with optional filters. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + l1_category (Optional[str] = None): Filter by level-1 category + result (Optional[int] = None): Settlement result filter + start_date (Optional[str] = None): Start date. Format: `yyyy-MM-dd`. Must be ≤ `endDate` + end_date (Optional[str] = None): End date. Format: `yyyy-MM-dd`. Must be ≥ `startDate` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QuerySettledPositionHistoryResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "l1_category": l1_category, + "result": result, + "start_date": start_date, + "end_date": end_date, + "offset": offset, + "limit": limit, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/position/settled-history", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QuerySettledPositionHistoryResponse, + is_signed=True, + signer=self._signer, + ) diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/redeem_api.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/redeem_api.py new file mode 100644 index 00000000..b8d12439 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/redeem_api.py @@ -0,0 +1,173 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from typing import List, Optional, Union +from requests import Session +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.models import ApiResponse +from binance_common.signature import Signers +from binance_common.utils import send_request + +from ..models import BatchRedeemResponse +from ..models import GetRedeemStatusResponse + + +class RedeemApi: + """API Client for RedeemApi endpoints.""" + + def __init__( + self, + configuration: ConfigurationRestAPI = None, + session: Session = None, + signer: Signers = None, + ) -> None: + self._configuration = configuration + self._session = session + self._signer = signer + + def batch_redeem( + self, + wallet_address: Union[str, None], + wallet_id: Union[str, None], + token_ids: Union[List[str], None], + chain_id: Optional[str] = None, + ) -> ApiResponse[BatchRedeemResponse]: + """ + Batch Redeem + POST /sapi/v1/w3w/wallet/prediction/batch-redeem + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/redeem#batch-redeem + + Redeem one or more settled prediction tokens on-chain to claim winnings. Requires SAS authorization. + + Weight(IP): 200 + + Security Type: TRADE + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + wallet_id (Union[str, None]): Wallet ID + token_ids (Union[List[str], None]): List of prediction token IDs to redeem. Not empty. Example: `tokenIds=112233&tokenIds=112234` + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + + Returns: + ApiResponse[BatchRedeemResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if wallet_id is None: + raise RequiredError( + field="wallet_id", + error_message="Missing required parameter 'wallet_id'", + ) + if token_ids is None: + raise RequiredError( + field="token_ids", + error_message="Missing required parameter 'token_ids'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "wallet_id": wallet_id, + "token_ids": token_ids, + "chain_id": chain_id, + } + + return send_request( + self._session, + self._configuration, + method="POST", + path="/sapi/v1/w3w/wallet/prediction/batch-redeem", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=BatchRedeemResponse, + is_signed=True, + signer=self._signer, + ) + + def get_redeem_status( + self, + wallet_address: Union[str, None], + tx_hash: Union[str, None], + recv_window: Optional[int] = None, + ) -> ApiResponse[GetRedeemStatusResponse]: + """ + Get Redeem Status + GET /sapi/v1/w3w/wallet/prediction/redeem/status + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/redeem#get-redeem-status + + Query the on-chain transaction status of a previously submitted redeem request. + + Weight(IP): 200 + + Security Type: USER_DATA + + Response Notes: + - Status values: + + | Value | Description | + | ----------- | -------------------------------------------- | + | `PENDING` | Transaction submitted, awaiting confirmation | + | `CONFIRMED` | Transaction confirmed on-chain | + | `FAILED` | Transaction failed | + | `NOT_FOUND` | Transaction hash not found | + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + tx_hash (Union[str, None]): Redeem transaction hash + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetRedeemStatusResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if tx_hash is None: + raise RequiredError( + field="tx_hash", error_message="Missing required parameter 'tx_hash'" + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "tx_hash": tx_hash, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/redeem/status", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=GetRedeemStatusResponse, + is_signed=True, + signer=self._signer, + ) diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/trade_api.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/trade_api.py new file mode 100644 index 00000000..84aed3e7 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/trade_api.py @@ -0,0 +1,488 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from typing import List, Optional, Union +from requests import Session +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.models import ApiResponse +from binance_common.signature import Signers +from binance_common.utils import send_request + +from ..models import BatchCancelOrdersResponse +from ..models import GetQuoteResponse +from ..models import PlaceOrderResponse +from ..models import QueryActiveOrdersResponse +from ..models import QueryOrderHistoryResponse + + +from ..models import BatchCancelOrdersCancelInfoListParameterInner + + +from ..models import GetQuoteSideEnum +from ..models import GetQuoteOrderTypeEnum +from ..models import GetQuoteFundingSourceEnum +from ..models import PlaceOrderAccountTypeEnum +from ..models import PlaceOrderOrderTypeEnum +from ..models import PlaceOrderFundingSourceEnum +from ..models import QueryActiveOrdersTradeSideEnum +from ..models import QueryOrderHistoryOrderTypeEnum + + +class TradeApi: + """API Client for TradeApi endpoints.""" + + def __init__( + self, + configuration: ConfigurationRestAPI = None, + session: Session = None, + signer: Signers = None, + ) -> None: + self._configuration = configuration + self._session = session + self._signer = signer + + def batch_cancel_orders( + self, + wallet_address: Union[str, None], + wallet_id: Union[str, None], + cancel_info_list: Optional[ + List[BatchCancelOrdersCancelInfoListParameterInner] + ] = None, + ) -> ApiResponse[BatchCancelOrdersResponse]: + """ + Batch Cancel Orders + POST /sapi/v1/w3w/wallet/prediction/trade/batch-cancel + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/trade#batch-cancel-orders + + Cancel one or more active prediction orders in a single request. Requires SAS authorization. + + **Known Issue — Bracket Encoding Incompatibility:** + This endpoint uses indexed bracket notation (`cancelInfoList[0].orderId`). Binance SAPI signature verification runs over the **raw, unencoded** canonical string. However, mainstream HTTP libraries (Python `requests`, Java `HttpURLConnection`/`URI`, Go `net/url`, Node.js `url`) automatically percent-encode `[` → `%5B` and `]` → `%5D`, producing a signature mismatch with error `-1022 Signature for this request is not valid`. Postman is unaffected because it does not encode keys. + + **Workarounds** (use low-level HTTP APIs that do not normalize URLs): + - **Python:** use `http.client` (stdlib) and hand-build the body string. + - **Java:** use `HttpURLConnection` and write the raw body bytes directly. + - **Go:** use `strings.NewReader` with a hand-built body instead of `url.Values.Encode()`. + + Weight(IP): 200 + + Security Type: TRADE + + Notes: + - Use dot notation for nested list fields: `cancelInfoList[0].orderId`, `cancelInfoList[1].orderId`, etc. + - `vendor` does not need to be supplied. The server automatically sets the correct vendor (`predict_fun`) for every item in the batch. + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + wallet_id (Union[str, None]): Wallet ID + cancel_info_list (Optional[List[BatchCancelOrdersCancelInfoListParameterInner]] = None): List of orders to cancel (index `i` starts from 0) + + Returns: + ApiResponse[BatchCancelOrdersResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if wallet_id is None: + raise RequiredError( + field="wallet_id", + error_message="Missing required parameter 'wallet_id'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "wallet_id": wallet_id, + "cancel_info_list": cancel_info_list, + } + + return send_request( + self._session, + self._configuration, + method="POST", + path="/sapi/v1/w3w/wallet/prediction/trade/batch-cancel", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=BatchCancelOrdersResponse, + is_signed=True, + signer=self._signer, + ) + + def get_quote( + self, + wallet_address: Union[str, None], + token_id: Union[str, None], + side: Union[GetQuoteSideEnum, None], + amount_in: Union[str, None], + order_type: Union[GetQuoteOrderTypeEnum, None], + slippage_bps: Union[int, None], + price_limit: Optional[str] = None, + chain_id: Optional[str] = None, + fee_rate_bps: Optional[int] = None, + funding_source: Optional[GetQuoteFundingSourceEnum] = None, + fund_transfer_amount: Optional[str] = None, + ) -> ApiResponse[GetQuoteResponse]: + """ + Get Quote + POST /sapi/v1/w3w/wallet/prediction/trade/get-quote + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/trade#get-quote + + Get a price quote for a prediction order. The returned `quoteId` must be used in the subsequent Place Order request. + + Weight(IP): 200 + + Security Type: TRADE + + Response Notes: + - `feeAmount` is a string because it is denominated in wei (18 decimals) and may exceed JavaScript's safe integer range. `feeDiscountBps` is also a string to allow fractional basis-point values in the future. `feeRateBps` and `slippageBps` are integers and will never exceed safe integer bounds. + - **MARKET order minimum amount:** For `MARKET` orders, `amountIn` must be at least approximately **1.5 USDT** (in wei: `1500000000000000000`). The exact minimum varies by market liquidity. If the amount is too small, the server returns `-9000 Your order amount is too small`. This limit does **not** apply to `LIMIT` orders. + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Union[str, None]): Prediction outcome token ID + side (Union[GetQuoteSideEnum, None]): Trade direction. Enum: `BUY`, `SELL` + amount_in (Union[str, None]): Input amount in wei (18 decimals). Must be > 0. For `MARKET` orders, minimum is approximately 1.5 USDT (varies by market depth). Example: `1000000000000000000` = 1 USDT + order_type (Union[GetQuoteOrderTypeEnum, None]): Order type. Enum: `MARKET`, `LIMIT` + slippage_bps (Union[int, None]): Slippage tolerance in basis points. Range 1–10000 + price_limit (Optional[str] = None): Limit price. Required when `orderType=LIMIT`. Must be > 0 + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + fee_rate_bps (Optional[int] = None): Fee rate in basis points. Default `200`, range 1–10000 + funding_source (Optional[GetQuoteFundingSourceEnum] = None): Funding source. Enum: `MPC`, `CEX`. Default `MPC` + fund_transfer_amount (Optional[str] = None): Auto-transfer amount before order (wei). Must be > 0 if provided + + Returns: + ApiResponse[GetQuoteResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if token_id is None: + raise RequiredError( + field="token_id", error_message="Missing required parameter 'token_id'" + ) + if side is None: + raise RequiredError( + field="side", error_message="Missing required parameter 'side'" + ) + if amount_in is None: + raise RequiredError( + field="amount_in", + error_message="Missing required parameter 'amount_in'", + ) + if order_type is None: + raise RequiredError( + field="order_type", + error_message="Missing required parameter 'order_type'", + ) + if slippage_bps is None: + raise RequiredError( + field="slippage_bps", + error_message="Missing required parameter 'slippage_bps'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "token_id": token_id, + "side": side, + "amount_in": amount_in, + "order_type": order_type, + "slippage_bps": slippage_bps, + "price_limit": price_limit, + "chain_id": chain_id, + "fee_rate_bps": fee_rate_bps, + "funding_source": funding_source, + "fund_transfer_amount": fund_transfer_amount, + } + + return send_request( + self._session, + self._configuration, + method="POST", + path="/sapi/v1/w3w/wallet/prediction/trade/get-quote", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=GetQuoteResponse, + is_signed=True, + signer=self._signer, + ) + + def place_order( + self, + wallet_address: Union[str, None], + wallet_id: Union[str, None], + quote_id: Union[str, None], + time_in_force: Union[str, None], + account_type: Union[PlaceOrderAccountTypeEnum, None], + order_type: Union[PlaceOrderOrderTypeEnum, None], + slippage_bps: Union[int, None], + price_limit: Optional[str] = None, + funding_source: Optional[PlaceOrderFundingSourceEnum] = None, + fund_transfer_amount: Optional[str] = None, + ) -> ApiResponse[PlaceOrderResponse]: + """ + Place Order + POST /sapi/v1/w3w/wallet/prediction/trade/place-order-bundle + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/trade#place-order + + Place a prediction order using a previously obtained quote. Requires SAS authorization. + + Weight(IP): 200 + + Security Type: TRADE + + Notes: + - Validation rules: + + | orderType | timeInForce | priceLimit | + | --------- | ------------- | --------------------- | + | `MARKET` | Must be `FOK` | Not required | + | `LIMIT` | Must be `GTC` | Required, must be > 0 | + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + wallet_id (Union[str, None]): Wallet ID + quote_id (Union[str, None]): Quote ID obtained from `Get Quote` + time_in_force (Union[str, None]): Must match `orderType`: `FOK` for `MARKET`, `GTC` for `LIMIT` + account_type (Union[PlaceOrderAccountTypeEnum, None]): Payment account type. Enum: `SPOT`, `FUNDING` + order_type (Union[PlaceOrderOrderTypeEnum, None]): Order type. Enum: `MARKET`, `LIMIT` + slippage_bps (Union[int, None]): Slippage tolerance in basis points. Range 1–10000 + price_limit (Optional[str] = None): Limit price. Required when `orderType=LIMIT`. Must be > 0 + funding_source (Optional[PlaceOrderFundingSourceEnum] = None): Funding source. Enum: `MPC`, `CEX`. Default `MPC` + fund_transfer_amount (Optional[str] = None): Auto-transfer amount before order (wei). Must be > 0 if provided + + Returns: + ApiResponse[PlaceOrderResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if wallet_id is None: + raise RequiredError( + field="wallet_id", + error_message="Missing required parameter 'wallet_id'", + ) + if quote_id is None: + raise RequiredError( + field="quote_id", error_message="Missing required parameter 'quote_id'" + ) + if time_in_force is None: + raise RequiredError( + field="time_in_force", + error_message="Missing required parameter 'time_in_force'", + ) + if account_type is None: + raise RequiredError( + field="account_type", + error_message="Missing required parameter 'account_type'", + ) + if order_type is None: + raise RequiredError( + field="order_type", + error_message="Missing required parameter 'order_type'", + ) + if slippage_bps is None: + raise RequiredError( + field="slippage_bps", + error_message="Missing required parameter 'slippage_bps'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "wallet_id": wallet_id, + "quote_id": quote_id, + "time_in_force": time_in_force, + "account_type": account_type, + "order_type": order_type, + "slippage_bps": slippage_bps, + "price_limit": price_limit, + "funding_source": funding_source, + "fund_transfer_amount": fund_transfer_amount, + } + + return send_request( + self._session, + self._configuration, + method="POST", + path="/sapi/v1/w3w/wallet/prediction/trade/place-order-bundle", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=PlaceOrderResponse, + is_signed=True, + signer=self._signer, + ) + + def query_active_orders( + self, + wallet_address: Union[str, None], + trade_side: Optional[QueryActiveOrdersTradeSideEnum] = None, + l1_category: Optional[str] = None, + market_id: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryActiveOrdersResponse]: + """ + Query Active Orders + GET /sapi/v1/w3w/wallet/prediction/order/list + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/trade#query-active-orders + + Get active (open) prediction orders for the authenticated user. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + trade_side (Optional[QueryActiveOrdersTradeSideEnum] = None): Filter by trade side. Enum: `BUY`, `SELL` + l1_category (Optional[str] = None): Filter by level-1 category + market_id (Optional[int] = None): Filter by market ID + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryActiveOrdersResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "trade_side": trade_side, + "l1_category": l1_category, + "market_id": market_id, + "offset": offset, + "limit": limit, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/order/list", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryActiveOrdersResponse, + is_signed=True, + signer=self._signer, + ) + + def query_order_history( + self, + wallet_address: Union[str, None], + l1_category: Optional[str] = None, + order_type: Optional[QueryOrderHistoryOrderTypeEnum] = None, + status: Optional[str] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryOrderHistoryResponse]: + """ + Query Order History + GET /sapi/v1/w3w/wallet/prediction/order/history + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/trade#query-order-history + + Get historical prediction orders (all statuses) for the authenticated user, with optional filters. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + l1_category (Optional[str] = None): Filter by level-1 category + order_type (Optional[QueryOrderHistoryOrderTypeEnum] = None): Filter by order type. Enum: `MARKET`, `LIMIT` + status (Optional[str] = None): Filter by order status + start_date (Optional[str] = None): Start date. Format: `yyyy-MM-dd`. Must be ≤ `endDate` + end_date (Optional[str] = None): End date. Format: `yyyy-MM-dd`. Must be ≥ `startDate` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryOrderHistoryResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "l1_category": l1_category, + "order_type": order_type, + "status": status, + "start_date": start_date, + "end_date": end_date, + "offset": offset, + "limit": limit, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/order/history", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryOrderHistoryResponse, + is_signed=True, + signer=self._signer, + ) diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/transfer_api.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/transfer_api.py new file mode 100644 index 00000000..631aafc5 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/transfer_api.py @@ -0,0 +1,350 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from typing import Optional, Union +from requests import Session +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.models import ApiResponse +from binance_common.signature import Signers +from binance_common.utils import send_request + +from ..models import CreateInboundTransferResponse +from ..models import CreateOutboundTransferResponse +from ..models import QueryTransferListResponse +from ..models import QueryTransferStatusResponse + + +from ..models import CreateInboundTransferAccountTypeEnum +from ..models import CreateOutboundTransferAccountTypeEnum +from ..models import CreateOutboundTransferSourceBizEnum +from ..models import QueryTransferListDirectionEnum + + +class TransferApi: + """API Client for TransferApi endpoints.""" + + def __init__( + self, + configuration: ConfigurationRestAPI = None, + session: Session = None, + signer: Signers = None, + ) -> None: + self._configuration = configuration + self._session = session + self._signer = signer + + def create_inbound_transfer( + self, + wallet_id: Union[str, None], + wallet_address: Union[str, None], + from_token_amount: Union[str, None], + account_type: Union[CreateInboundTransferAccountTypeEnum, None], + from_token: Optional[str] = None, + to_token: Optional[str] = None, + chain_id: Optional[str] = None, + ) -> ApiResponse[CreateInboundTransferResponse]: + """ + Create Inbound Transfer + POST /sapi/v1/w3w/wallet/prediction/transfer/inbound + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/transfer#create-inbound-transfer + + Transfer funds from the prediction wallet back to the user's CEX account (SPOT or FUNDING). Requires SAS authorization. + + ⚠️ **SAS Authorization Required:** This endpoint enforces SAS (Self-Authorization Service) authorization. If SAS is not enabled for the wallet, the request will be rejected with `-31003 SAS authorization required`. Enable SAS for your wallet before calling this endpoint. + + Weight(IP): 200 + + Security Type: TRADE + + Args: + wallet_id (Union[str, None]): Wallet ID + wallet_address (Union[str, None]): User's prediction wallet address + from_token_amount (Union[str, None]): Transfer amount in wei (18 decimals). Must be > 0. Example: `1000000000000000000` = 1 USDT + account_type (Union[CreateInboundTransferAccountTypeEnum, None]): Destination CEX account. Enum: `SPOT`, `FUNDING` + from_token (Optional[str] = None): Source token symbol. Default `USDT` + to_token (Optional[str] = None): Destination token symbol. Default `USDT` + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + + Returns: + ApiResponse[CreateInboundTransferResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_id is None: + raise RequiredError( + field="wallet_id", + error_message="Missing required parameter 'wallet_id'", + ) + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if from_token_amount is None: + raise RequiredError( + field="from_token_amount", + error_message="Missing required parameter 'from_token_amount'", + ) + if account_type is None: + raise RequiredError( + field="account_type", + error_message="Missing required parameter 'account_type'", + ) + + body = {} + payload = { + "wallet_id": wallet_id, + "wallet_address": wallet_address, + "from_token_amount": from_token_amount, + "account_type": account_type, + "from_token": from_token, + "to_token": to_token, + "chain_id": chain_id, + } + + return send_request( + self._session, + self._configuration, + method="POST", + path="/sapi/v1/w3w/wallet/prediction/transfer/inbound", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=CreateInboundTransferResponse, + is_signed=True, + signer=self._signer, + ) + + def create_outbound_transfer( + self, + wallet_id: Union[str, None], + wallet_address: Union[str, None], + from_token_amount: Union[str, None], + account_type: Union[CreateOutboundTransferAccountTypeEnum, None], + source_biz: Union[CreateOutboundTransferSourceBizEnum, None], + from_token: Optional[str] = None, + to_token: Optional[str] = None, + chain_id: Optional[str] = None, + ) -> ApiResponse[CreateOutboundTransferResponse]: + """ + Create Outbound Transfer + POST /sapi/v1/w3w/wallet/prediction/transfer/outbound + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/transfer#create-outbound-transfer + + Transfer funds from the user's CEX account (SPOT or FUNDING) into the prediction wallet. Requires SAS authorization. + + Weight(IP): 200 + + Security Type: TRADE + + Args: + wallet_id (Union[str, None]): Wallet ID + wallet_address (Union[str, None]): User's prediction wallet address + from_token_amount (Union[str, None]): Transfer amount in wei (18 decimals). Must be > 0. Example: `1000000000000000000` = 1 USDT + account_type (Union[CreateOutboundTransferAccountTypeEnum, None]): Source CEX account. Enum: `SPOT`, `FUNDING` + source_biz (Union[CreateOutboundTransferSourceBizEnum, None]): Business source. Enum: `USER_TRANSFER`, `PREDICTION_BUY` + from_token (Optional[str] = None): Source token symbol. Default `USDT` + to_token (Optional[str] = None): Destination token symbol. Default `USDT` + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + + Returns: + ApiResponse[CreateOutboundTransferResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_id is None: + raise RequiredError( + field="wallet_id", + error_message="Missing required parameter 'wallet_id'", + ) + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if from_token_amount is None: + raise RequiredError( + field="from_token_amount", + error_message="Missing required parameter 'from_token_amount'", + ) + if account_type is None: + raise RequiredError( + field="account_type", + error_message="Missing required parameter 'account_type'", + ) + if source_biz is None: + raise RequiredError( + field="source_biz", + error_message="Missing required parameter 'source_biz'", + ) + + body = {} + payload = { + "wallet_id": wallet_id, + "wallet_address": wallet_address, + "from_token_amount": from_token_amount, + "account_type": account_type, + "source_biz": source_biz, + "from_token": from_token, + "to_token": to_token, + "chain_id": chain_id, + } + + return send_request( + self._session, + self._configuration, + method="POST", + path="/sapi/v1/w3w/wallet/prediction/transfer/outbound", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=CreateOutboundTransferResponse, + is_signed=True, + signer=self._signer, + ) + + def query_transfer_list( + self, + wallet_address: Union[str, None], + start_date: Union[str, None], + end_date: Union[str, None], + token_symbol: Optional[str] = None, + direction: Optional[QueryTransferListDirectionEnum] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryTransferListResponse]: + """ + Query Transfer List + GET /sapi/v1/w3w/wallet/prediction/transfer/list + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/transfer#query-transfer-list + + Get the authenticated user's prediction wallet transfer history within a date range. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + start_date (Union[str, None]): Start date. Format: `yyyy-MM-dd`. Must be ≤ `endDate` + end_date (Union[str, None]): End date. Format: `yyyy-MM-dd`. Must be ≥ `startDate` + token_symbol (Optional[str] = None): Filter by token symbol (e.g. `USDT`) + direction (Optional[QueryTransferListDirectionEnum] = None): Filter by direction. Enum: `INBOUND`, `OUTBOUND` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryTransferListResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + if start_date is None: + raise RequiredError( + field="start_date", + error_message="Missing required parameter 'start_date'", + ) + if end_date is None: + raise RequiredError( + field="end_date", error_message="Missing required parameter 'end_date'" + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "start_date": start_date, + "end_date": end_date, + "token_symbol": token_symbol, + "direction": direction, + "offset": offset, + "limit": limit, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/transfer/list", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryTransferListResponse, + is_signed=True, + signer=self._signer, + ) + + def query_transfer_status( + self, + transfer_id: Union[str, None], + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryTransferStatusResponse]: + """ + Query Transfer Status + GET /sapi/v1/w3w/wallet/prediction/transfer/status + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/transfer#query-transfer-status + + Query the current status of a prediction wallet transfer by transfer ID. + + **`status` values:** Terminal states are `COMPLETED` and `FAILED`. Intermediate states are `PROCESSING` and `PENDING`. **Do not** poll for `SUCCESS` — it is not a valid terminal state. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + transfer_id (Union[str, None]): Transfer ID returned from outbound/inbound transfer + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryTransferStatusResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if transfer_id is None: + raise RequiredError( + field="transfer_id", + error_message="Missing required parameter 'transfer_id'", + ) + + body = {} + payload = {"transfer_id": transfer_id, "recv_window": recv_window} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/transfer/status", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryTransferStatusResponse, + is_signed=True, + signer=self._signer, + ) diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/wallet_api.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/wallet_api.py new file mode 100644 index 00000000..f4c49834 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/api/wallet_api.py @@ -0,0 +1,227 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from typing import Optional, Union +from requests import Session +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.models import ApiResponse +from binance_common.signature import Signers +from binance_common.utils import send_request + +from ..models import GetPortfolioResponse +from ..models import GetQuotaStatusResponse +from ..models import ListPredictionWalletsResponse +from ..models import QueryPaymentOptionBalancesResponse + + +class WalletApi: + """API Client for WalletApi endpoints.""" + + def __init__( + self, + configuration: ConfigurationRestAPI = None, + session: Session = None, + signer: Signers = None, + ) -> None: + self._configuration = configuration + self._session = session + self._signer = signer + + def get_portfolio( + self, + wallet_address: Union[str, None], + token_id: Optional[str] = None, + market_id: Optional[int] = None, + market_topic_id: Optional[int] = None, + active_only: Optional[bool] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[GetPortfolioResponse]: + """ + Get Portfolio + GET /sapi/v1/w3w/wallet/prediction/pnl/portfolio + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/wallet#get-portfolio + + Get the authenticated user's prediction portfolio overview including active positions count, aggregated PnL, and full position list. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Optional[str] = None): Filter by prediction token ID + market_id (Optional[int] = None): Filter by market ID. Must be > 0 + market_topic_id (Optional[int] = None): Filter by market topic ID. Must be > 0 + active_only (Optional[bool] = None): If `true`, return only active (unresolved) positions + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetPortfolioResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + if wallet_address is None: + raise RequiredError( + field="wallet_address", + error_message="Missing required parameter 'wallet_address'", + ) + + body = {} + payload = { + "wallet_address": wallet_address, + "token_id": token_id, + "market_id": market_id, + "market_topic_id": market_topic_id, + "active_only": active_only, + "recv_window": recv_window, + } + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/pnl/portfolio", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=GetPortfolioResponse, + is_signed=True, + signer=self._signer, + ) + + def get_quota_status( + self, + recv_window: Optional[int] = None, + ) -> ApiResponse[GetQuotaStatusResponse]: + """ + Get Quota Status + GET /sapi/v1/w3w/wallet/prediction/quota/limit/status + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/wallet#get-quota-status + + Query the current user's daily trading quota limit and remaining allowance for prediction markets. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetQuotaStatusResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + body = {} + payload = {"recv_window": recv_window} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/quota/limit/status", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=GetQuotaStatusResponse, + is_signed=True, + signer=self._signer, + ) + + def list_prediction_wallets( + self, + recv_window: Optional[int] = None, + ) -> ApiResponse[ListPredictionWalletsResponse]: + """ + List Prediction Wallets + GET /sapi/v1/w3w/wallet/prediction/wallet/list + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/wallet#list-prediction-wallets + + Get all prediction wallets registered for the authenticated user. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[ListPredictionWalletsResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + body = {} + payload = {"recv_window": recv_window} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/wallet/list", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=ListPredictionWalletsResponse, + is_signed=True, + signer=self._signer, + ) + + def query_payment_option_balances( + self, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPaymentOptionBalancesResponse]: + """ + Query Payment Option Balances + GET /sapi/v1/w3w/wallet/prediction/balance/payment-options + https://developers.binance.com/en/dev-docs/catalog/web3-wallet-prediction-trading/api/rest-api/wallet#query-payment-option-balances + + Get available balances for each payment option that can be used for prediction trading. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPaymentOptionBalancesResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + body = {} + payload = {"recv_window": recv_window} + + return send_request( + self._session, + self._configuration, + method="GET", + path="/sapi/v1/w3w/wallet/prediction/balance/payment-options", + payload=payload, + body=body, + time_unit=self._configuration.time_unit, + response_model=QueryPaymentOptionBalancesResponse, + is_signed=True, + signer=self._signer, + ) diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/__init__.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/__init__.py new file mode 100644 index 00000000..d42d4691 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/__init__.py @@ -0,0 +1,167 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from .batch_cancel_orders_cancel_info_list_parameter_inner import ( + BatchCancelOrdersCancelInfoListParameterInner as BatchCancelOrdersCancelInfoListParameterInner, +) +from .batch_cancel_orders_response import ( + BatchCancelOrdersResponse as BatchCancelOrdersResponse, +) +from .batch_cancel_orders_response_failed_inner import ( + BatchCancelOrdersResponseFailedInner as BatchCancelOrdersResponseFailedInner, +) +from .batch_redeem_response import BatchRedeemResponse as BatchRedeemResponse +from .batch_redeem_response_results_inner import ( + BatchRedeemResponseResultsInner as BatchRedeemResponseResultsInner, +) +from .create_inbound_transfer_response import ( + CreateInboundTransferResponse as CreateInboundTransferResponse, +) +from .create_outbound_transfer_response import ( + CreateOutboundTransferResponse as CreateOutboundTransferResponse, +) +from .get_market_detail_response import ( + GetMarketDetailResponse as GetMarketDetailResponse, +) +from .get_market_detail_response_markets_inner import ( + GetMarketDetailResponseMarketsInner as GetMarketDetailResponseMarketsInner, +) +from .get_market_detail_response_markets_inner_outcomes_inner import ( + GetMarketDetailResponseMarketsInnerOutcomesInner as GetMarketDetailResponseMarketsInnerOutcomesInner, +) +from .get_market_detail_response_timeline_inner import ( + GetMarketDetailResponseTimelineInner as GetMarketDetailResponseTimelineInner, +) +from .get_market_detail_response_variant_data import ( + GetMarketDetailResponseVariantData as GetMarketDetailResponseVariantData, +) +from .get_portfolio_response import GetPortfolioResponse as GetPortfolioResponse +from .get_portfolio_response_positions_inner import ( + GetPortfolioResponsePositionsInner as GetPortfolioResponsePositionsInner, +) +from .get_position_by_token_response import ( + GetPositionByTokenResponse as GetPositionByTokenResponse, +) +from .get_position_by_token_response_position import ( + GetPositionByTokenResponsePosition as GetPositionByTokenResponsePosition, +) +from .get_quota_status_response import GetQuotaStatusResponse as GetQuotaStatusResponse +from .get_quote_response import GetQuoteResponse as GetQuoteResponse +from .get_redeem_status_response import ( + GetRedeemStatusResponse as GetRedeemStatusResponse, +) +from .list_prediction_categories_response import ( + ListPredictionCategoriesResponse as ListPredictionCategoriesResponse, +) +from .list_prediction_categories_response_categories_inner import ( + ListPredictionCategoriesResponseCategoriesInner as ListPredictionCategoriesResponseCategoriesInner, +) +from .list_prediction_categories_response_categories_inner_subcategories_inner import ( + ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner as ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner, +) +from .list_prediction_markets_response import ( + ListPredictionMarketsResponse as ListPredictionMarketsResponse, +) +from .list_prediction_markets_response_market_topics_inner import ( + ListPredictionMarketsResponseMarketTopicsInner as ListPredictionMarketsResponseMarketTopicsInner, +) +from .list_prediction_wallets_response import ( + ListPredictionWalletsResponse as ListPredictionWalletsResponse, +) +from .list_prediction_wallets_response_wallets_inner import ( + ListPredictionWalletsResponseWalletsInner as ListPredictionWalletsResponseWalletsInner, +) +from .market_search_response import MarketSearchResponse as MarketSearchResponse +from .market_search_response_inner import ( + MarketSearchResponseInner as MarketSearchResponseInner, +) +from .place_order_response import PlaceOrderResponse as PlaceOrderResponse +from .query_active_orders_response import ( + QueryActiveOrdersResponse as QueryActiveOrdersResponse, +) +from .query_active_orders_response_orders_inner import ( + QueryActiveOrdersResponseOrdersInner as QueryActiveOrdersResponseOrdersInner, +) +from .query_last_trade_price_response import ( + QueryLastTradePriceResponse as QueryLastTradePriceResponse, +) +from .query_order_book_response import QueryOrderBookResponse as QueryOrderBookResponse +from .query_order_book_response_asks_inner import ( + QueryOrderBookResponseAsksInner as QueryOrderBookResponseAsksInner, +) +from .query_order_book_response_bids_inner import ( + QueryOrderBookResponseBidsInner as QueryOrderBookResponseBidsInner, +) +from .query_order_history_response import ( + QueryOrderHistoryResponse as QueryOrderHistoryResponse, +) +from .query_order_history_response_orders_inner import ( + QueryOrderHistoryResponseOrdersInner as QueryOrderHistoryResponseOrdersInner, +) +from .query_payment_option_balances_response import ( + QueryPaymentOptionBalancesResponse as QueryPaymentOptionBalancesResponse, +) +from .query_payment_option_balances_response_items_inner import ( + QueryPaymentOptionBalancesResponseItemsInner as QueryPaymentOptionBalancesResponseItemsInner, +) +from .query_pn_l_response import QueryPnLResponse as QueryPnLResponse +from .query_positions_by_filter_response import ( + QueryPositionsByFilterResponse as QueryPositionsByFilterResponse, +) +from .query_positions_by_filter_response_positions_inner import ( + QueryPositionsByFilterResponsePositionsInner as QueryPositionsByFilterResponsePositionsInner, +) +from .query_positions_response import QueryPositionsResponse as QueryPositionsResponse +from .query_positions_response_counts import ( + QueryPositionsResponseCounts as QueryPositionsResponseCounts, +) +from .query_positions_response_positions_inner import ( + QueryPositionsResponsePositionsInner as QueryPositionsResponsePositionsInner, +) +from .query_positions_response_summary import ( + QueryPositionsResponseSummary as QueryPositionsResponseSummary, +) +from .query_settled_position_history_response import ( + QuerySettledPositionHistoryResponse as QuerySettledPositionHistoryResponse, +) +from .query_settled_position_history_response_positions_inner import ( + QuerySettledPositionHistoryResponsePositionsInner as QuerySettledPositionHistoryResponsePositionsInner, +) +from .query_transfer_list_response import ( + QueryTransferListResponse as QueryTransferListResponse, +) +from .query_transfer_list_response_transfers_inner import ( + QueryTransferListResponseTransfersInner as QueryTransferListResponseTransfersInner, +) +from .query_transfer_status_response import ( + QueryTransferStatusResponse as QueryTransferStatusResponse, +) + + +from .enums import ListPredictionMarketsSortByEnum as ListPredictionMarketsSortByEnum +from .enums import ListPredictionMarketsOrderByEnum as ListPredictionMarketsOrderByEnum +from .enums import GetQuoteSideEnum as GetQuoteSideEnum +from .enums import GetQuoteOrderTypeEnum as GetQuoteOrderTypeEnum +from .enums import GetQuoteFundingSourceEnum as GetQuoteFundingSourceEnum +from .enums import PlaceOrderAccountTypeEnum as PlaceOrderAccountTypeEnum +from .enums import PlaceOrderOrderTypeEnum as PlaceOrderOrderTypeEnum +from .enums import PlaceOrderFundingSourceEnum as PlaceOrderFundingSourceEnum +from .enums import QueryActiveOrdersTradeSideEnum as QueryActiveOrdersTradeSideEnum +from .enums import QueryOrderHistoryOrderTypeEnum as QueryOrderHistoryOrderTypeEnum +from .enums import ( + CreateInboundTransferAccountTypeEnum as CreateInboundTransferAccountTypeEnum, +) +from .enums import ( + CreateOutboundTransferAccountTypeEnum as CreateOutboundTransferAccountTypeEnum, +) +from .enums import ( + CreateOutboundTransferSourceBizEnum as CreateOutboundTransferSourceBizEnum, +) +from .enums import QueryTransferListDirectionEnum as QueryTransferListDirectionEnum diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_cancel_info_list_parameter_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_cancel_info_list_parameter_inner.py new file mode 100644 index 00000000..bced94c8 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_cancel_info_list_parameter_inner.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + + +class BatchCancelOrdersCancelInfoListParameterInner(BaseModel): + """ + BatchCancelOrdersCancelInfoListParameterInner + """ # noqa: E501 + + order_id: StrictStr = Field( + description="Internal order ID to cancel", alias="orderId" + ) + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["orderId"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BatchCancelOrdersCancelInfoListParameterInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BatchCancelOrdersCancelInfoListParameterInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"orderId": obj.get("orderId")}) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_response.py new file mode 100644 index 00000000..a9fa9393 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_response.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.batch_cancel_orders_response_failed_inner import ( + BatchCancelOrdersResponseFailedInner, +) +from typing import Set +from typing_extensions import Self + + +class BatchCancelOrdersResponse(BaseModel): + """ + BatchCancelOrdersResponse + """ # noqa: E501 + + canceled: Optional[List[StrictStr]] = None + failed: Optional[List[BatchCancelOrdersResponseFailedInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["canceled", "failed"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BatchCancelOrdersResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in failed (list) + _items = [] + if self.failed: + for _item_failed in self.failed: + if _item_failed: + _items.append(_item_failed.to_dict()) + _dict["failed"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BatchCancelOrdersResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "canceled": obj.get("canceled"), + "failed": ( + [ + BatchCancelOrdersResponseFailedInner.from_dict(_item) + for _item in obj["failed"] + ] + if obj.get("failed") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_response_failed_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_response_failed_inner.py new file mode 100644 index 00000000..15342619 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_cancel_orders_response_failed_inner.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class BatchCancelOrdersResponseFailedInner(BaseModel): + """ + BatchCancelOrdersResponseFailedInner + """ # noqa: E501 + + order_id: Optional[StrictStr] = Field(default=None, alias="orderId") + reason: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["orderId", "reason"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BatchCancelOrdersResponseFailedInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BatchCancelOrdersResponseFailedInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + {"orderId": obj.get("orderId"), "reason": obj.get("reason")} + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_redeem_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_redeem_response.py new file mode 100644 index 00000000..d137c6f7 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_redeem_response.py @@ -0,0 +1,124 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.batch_redeem_response_results_inner import ( + BatchRedeemResponseResultsInner, +) +from typing import Set +from typing_extensions import Self + + +class BatchRedeemResponse(BaseModel): + """ + BatchRedeemResponse + """ # noqa: E501 + + batch_id: Optional[StrictStr] = Field(default=None, alias="batchId") + results: Optional[List[BatchRedeemResponseResultsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["batchId", "results"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BatchRedeemResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item_results in self.results: + if _item_results: + _items.append(_item_results.to_dict()) + _dict["results"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BatchRedeemResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "batchId": obj.get("batchId"), + "results": ( + [ + BatchRedeemResponseResultsInner.from_dict(_item) + for _item in obj["results"] + ] + if obj.get("results") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_redeem_response_results_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_redeem_response_results_inner.py new file mode 100644 index 00000000..a1604eab --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/batch_redeem_response_results_inner.py @@ -0,0 +1,116 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class BatchRedeemResponseResultsInner(BaseModel): + """ + BatchRedeemResponseResultsInner + """ # noqa: E501 + + request_id: Optional[StrictStr] = Field(default=None, alias="requestId") + tx_hash: Optional[StrictStr] = Field(default=None, alias="txHash") + status: Optional[StrictStr] = None + error: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["requestId", "txHash", "status", "error"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of BatchRedeemResponseResultsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if error (nullable) is None + # and model_fields_set contains the field + if self.error is None and "error" in self.model_fields_set: + _dict["error"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of BatchRedeemResponseResultsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "requestId": obj.get("requestId"), + "txHash": obj.get("txHash"), + "status": obj.get("status"), + "error": obj.get("error"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/create_inbound_transfer_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/create_inbound_transfer_response.py new file mode 100644 index 00000000..e3c80481 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/create_inbound_transfer_response.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class CreateInboundTransferResponse(BaseModel): + """ + CreateInboundTransferResponse + """ # noqa: E501 + + transfer_id: Optional[StrictStr] = Field(default=None, alias="transferId") + status: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["transferId", "status"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateInboundTransferResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateInboundTransferResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + {"transferId": obj.get("transferId"), "status": obj.get("status")} + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/create_outbound_transfer_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/create_outbound_transfer_response.py new file mode 100644 index 00000000..d40d8129 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/create_outbound_transfer_response.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class CreateOutboundTransferResponse(BaseModel): + """ + CreateOutboundTransferResponse + """ # noqa: E501 + + transfer_id: Optional[StrictStr] = Field(default=None, alias="transferId") + status: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["transferId", "status"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CreateOutboundTransferResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CreateOutboundTransferResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + {"transferId": obj.get("transferId"), "status": obj.get("status")} + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/enums.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/enums.py new file mode 100644 index 00000000..cfb0fe9e --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/enums.py @@ -0,0 +1,84 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from enum import Enum + + +class ListPredictionMarketsSortByEnum(Enum): + RECOMMENDED = "RECOMMENDED" + VOLUME = "VOLUME" + PARTICIPANTS = "PARTICIPANTS" + CREATED_TIME = "CREATED_TIME" + END_DATE = "END_DATE" + + +class ListPredictionMarketsOrderByEnum(Enum): + ASC = "ASC" + DESC = "DESC" + + +class GetQuoteSideEnum(Enum): + BUY = "BUY" + SELL = "SELL" + + +class GetQuoteOrderTypeEnum(Enum): + MARKET = "MARKET" + LIMIT = "LIMIT" + + +class GetQuoteFundingSourceEnum(Enum): + MPC = "MPC" + CEX = "CEX" + + +class PlaceOrderAccountTypeEnum(Enum): + SPOT = "SPOT" + FUNDING = "FUNDING" + + +class PlaceOrderOrderTypeEnum(Enum): + MARKET = "MARKET" + LIMIT = "LIMIT" + + +class PlaceOrderFundingSourceEnum(Enum): + MPC = "MPC" + CEX = "CEX" + + +class QueryActiveOrdersTradeSideEnum(Enum): + BUY = "BUY" + SELL = "SELL" + + +class QueryOrderHistoryOrderTypeEnum(Enum): + MARKET = "MARKET" + LIMIT = "LIMIT" + + +class CreateInboundTransferAccountTypeEnum(Enum): + SPOT = "SPOT" + FUNDING = "FUNDING" + + +class CreateOutboundTransferAccountTypeEnum(Enum): + SPOT = "SPOT" + FUNDING = "FUNDING" + + +class CreateOutboundTransferSourceBizEnum(Enum): + USER_TRANSFER = "USER_TRANSFER" + PREDICTION_BUY = "PREDICTION_BUY" + + +class QueryTransferListDirectionEnum(Enum): + INBOUND = "INBOUND" + OUTBOUND = "OUTBOUND" diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response.py new file mode 100644 index 00000000..91cc1844 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response.py @@ -0,0 +1,227 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.get_market_detail_response_markets_inner import ( + GetMarketDetailResponseMarketsInner, +) +from binance_sdk_w3w_prediction.rest_api.models.get_market_detail_response_timeline_inner import ( + GetMarketDetailResponseTimelineInner, +) +from binance_sdk_w3w_prediction.rest_api.models.get_market_detail_response_variant_data import ( + GetMarketDetailResponseVariantData, +) +from typing import Set +from typing_extensions import Self + + +class GetMarketDetailResponse(BaseModel): + """ + GetMarketDetailResponse + """ # noqa: E501 + + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + vendor: Optional[StrictStr] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + slug: Optional[StrictStr] = None + title: Optional[StrictStr] = None + question: Optional[StrictStr] = None + description: Optional[StrictStr] = None + image_url: Optional[StrictStr] = Field(default=None, alias="imageUrl") + topic_type: Optional[StrictStr] = Field(default=None, alias="topicType") + chart_type: Optional[StrictStr] = Field(default=None, alias="chartType") + symbol: Optional[StrictStr] = None + variant_data: Optional[GetMarketDetailResponseVariantData] = Field( + default=None, alias="variantData" + ) + participant_count: Optional[StrictInt] = Field( + default=None, alias="participantCount" + ) + collateral: Optional[StrictStr] = None + fee_rate_bps: Optional[StrictInt] = Field(default=None, alias="feeRateBps") + slippage_bps: Optional[StrictInt] = Field(default=None, alias="slippageBps") + is_yield_bearing: Optional[StrictBool] = Field(default=None, alias="isYieldBearing") + trade_volume: Optional[StrictStr] = Field(default=None, alias="tradeVolume") + liquidity: Optional[StrictStr] = None + published_at: Optional[StrictInt] = Field(default=None, alias="publishedAt") + start_date: Optional[StrictInt] = Field(default=None, alias="startDate") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + status: Optional[StrictStr] = None + timeline: Optional[List[GetMarketDetailResponseTimelineInner]] = None + markets: Optional[List[GetMarketDetailResponseMarketsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "marketTopicId", + "vendor", + "chainId", + "slug", + "title", + "question", + "description", + "imageUrl", + "topicType", + "chartType", + "symbol", + "variantData", + "participantCount", + "collateral", + "feeRateBps", + "slippageBps", + "isYieldBearing", + "tradeVolume", + "liquidity", + "publishedAt", + "startDate", + "endDate", + "status", + "timeline", + "markets", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetMarketDetailResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of variant_data + if self.variant_data: + _dict["variantData"] = self.variant_data.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in timeline (list) + _items = [] + if self.timeline: + for _item_timeline in self.timeline: + if _item_timeline: + _items.append(_item_timeline.to_dict()) + _dict["timeline"] = _items + # override the default output from pydantic by calling `to_dict()` of each item in markets (list) + _items = [] + if self.markets: + for _item_markets in self.markets: + if _item_markets: + _items.append(_item_markets.to_dict()) + _dict["markets"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetMarketDetailResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "marketTopicId": obj.get("marketTopicId"), + "vendor": obj.get("vendor"), + "chainId": obj.get("chainId"), + "slug": obj.get("slug"), + "title": obj.get("title"), + "question": obj.get("question"), + "description": obj.get("description"), + "imageUrl": obj.get("imageUrl"), + "topicType": obj.get("topicType"), + "chartType": obj.get("chartType"), + "symbol": obj.get("symbol"), + "variantData": ( + GetMarketDetailResponseVariantData.from_dict(obj["variantData"]) + if obj.get("variantData") is not None + else None + ), + "participantCount": obj.get("participantCount"), + "collateral": obj.get("collateral"), + "feeRateBps": obj.get("feeRateBps"), + "slippageBps": obj.get("slippageBps"), + "isYieldBearing": obj.get("isYieldBearing"), + "tradeVolume": obj.get("tradeVolume"), + "liquidity": obj.get("liquidity"), + "publishedAt": obj.get("publishedAt"), + "startDate": obj.get("startDate"), + "endDate": obj.get("endDate"), + "status": obj.get("status"), + "timeline": ( + [ + GetMarketDetailResponseTimelineInner.from_dict(_item) + for _item in obj["timeline"] + ] + if obj.get("timeline") is not None + else None + ), + "markets": ( + [ + GetMarketDetailResponseMarketsInner.from_dict(_item) + for _item in obj["markets"] + ] + if obj.get("markets") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_markets_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_markets_inner.py new file mode 100644 index 00000000..218fd86f --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_markets_inner.py @@ -0,0 +1,161 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.get_market_detail_response_markets_inner_outcomes_inner import ( + GetMarketDetailResponseMarketsInnerOutcomesInner, +) +from typing import Set +from typing_extensions import Self + + +class GetMarketDetailResponseMarketsInner(BaseModel): + """ + GetMarketDetailResponseMarketsInner + """ # noqa: E501 + + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + external_id: Optional[StrictStr] = Field(default=None, alias="externalId") + title: Optional[StrictStr] = None + question: Optional[StrictStr] = None + description: Optional[StrictStr] = None + condition_id: Optional[StrictStr] = Field(default=None, alias="conditionId") + status: Optional[StrictStr] = None + trading_status: Optional[StrictStr] = Field(default=None, alias="tradingStatus") + trade_volume: Optional[StrictStr] = Field(default=None, alias="tradeVolume") + liquidity: Optional[StrictStr] = None + decimal_precision: Optional[StrictInt] = Field( + default=None, alias="decimalPrecision" + ) + outcomes: Optional[List[GetMarketDetailResponseMarketsInnerOutcomesInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "marketId", + "externalId", + "title", + "question", + "description", + "conditionId", + "status", + "tradingStatus", + "tradeVolume", + "liquidity", + "decimalPrecision", + "outcomes", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseMarketsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in outcomes (list) + _items = [] + if self.outcomes: + for _item_outcomes in self.outcomes: + if _item_outcomes: + _items.append(_item_outcomes.to_dict()) + _dict["outcomes"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseMarketsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "marketId": obj.get("marketId"), + "externalId": obj.get("externalId"), + "title": obj.get("title"), + "question": obj.get("question"), + "description": obj.get("description"), + "conditionId": obj.get("conditionId"), + "status": obj.get("status"), + "tradingStatus": obj.get("tradingStatus"), + "tradeVolume": obj.get("tradeVolume"), + "liquidity": obj.get("liquidity"), + "decimalPrecision": obj.get("decimalPrecision"), + "outcomes": ( + [ + GetMarketDetailResponseMarketsInnerOutcomesInner.from_dict( + _item + ) + for _item in obj["outcomes"] + ] + if obj.get("outcomes") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_markets_inner_outcomes_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_markets_inner_outcomes_inner.py new file mode 100644 index 00000000..41e14899 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_markets_inner_outcomes_inner.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class GetMarketDetailResponseMarketsInnerOutcomesInner(BaseModel): + """ + GetMarketDetailResponseMarketsInnerOutcomesInner + """ # noqa: E501 + + name: Optional[StrictStr] = None + price: Optional[StrictStr] = None + chance: Optional[StrictStr] = None + index: Optional[StrictInt] = None + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["name", "price", "chance", "index", "tokenId"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseMarketsInnerOutcomesInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseMarketsInnerOutcomesInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "name": obj.get("name"), + "price": obj.get("price"), + "chance": obj.get("chance"), + "index": obj.get("index"), + "tokenId": obj.get("tokenId"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_timeline_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_timeline_inner.py new file mode 100644 index 00000000..f990031b --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_timeline_inner.py @@ -0,0 +1,109 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class GetMarketDetailResponseTimelineInner(BaseModel): + """ + GetMarketDetailResponseTimelineInner + """ # noqa: E501 + + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + start_date: Optional[StrictInt] = Field(default=None, alias="startDate") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["marketTopicId", "startDate", "endDate"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseTimelineInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseTimelineInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "marketTopicId": obj.get("marketTopicId"), + "startDate": obj.get("startDate"), + "endDate": obj.get("endDate"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_variant_data.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_variant_data.py new file mode 100644 index 00000000..9b779036 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_market_detail_response_variant_data.py @@ -0,0 +1,131 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class GetMarketDetailResponseVariantData(BaseModel): + """ + GetMarketDetailResponseVariantData + """ # noqa: E501 + + type: Optional[StrictStr] = None + start_price: Optional[StrictStr] = Field(default=None, alias="startPrice") + end_price: Optional[StrictStr] = Field(default=None, alias="endPrice") + price_feed_id: Optional[StrictStr] = Field(default=None, alias="priceFeedId") + price_feed_provider: Optional[StrictStr] = Field( + default=None, alias="priceFeedProvider" + ) + price_feed_symbol: Optional[StrictStr] = Field( + default=None, alias="priceFeedSymbol" + ) + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "type", + "startPrice", + "endPrice", + "priceFeedId", + "priceFeedProvider", + "priceFeedSymbol", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseVariantData from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if end_price (nullable) is None + # and model_fields_set contains the field + if self.end_price is None and "end_price" in self.model_fields_set: + _dict["endPrice"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetMarketDetailResponseVariantData from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "type": obj.get("type"), + "startPrice": obj.get("startPrice"), + "endPrice": obj.get("endPrice"), + "priceFeedId": obj.get("priceFeedId"), + "priceFeedProvider": obj.get("priceFeedProvider"), + "priceFeedSymbol": obj.get("priceFeedSymbol"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_portfolio_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_portfolio_response.py new file mode 100644 index 00000000..5cac2510 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_portfolio_response.py @@ -0,0 +1,156 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.get_portfolio_response_positions_inner import ( + GetPortfolioResponsePositionsInner, +) +from typing import Set +from typing_extensions import Self + + +class GetPortfolioResponse(BaseModel): + """ + GetPortfolioResponse + """ # noqa: E501 + + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + wallet_address: Optional[StrictStr] = Field(default=None, alias="walletAddress") + active_positions_count: Optional[StrictInt] = Field( + default=None, alias="activePositionsCount" + ) + total_realized_pnl: Optional[StrictStr] = Field( + default=None, alias="totalRealizedPnl" + ) + total_unrealized_pnl: Optional[StrictStr] = Field( + default=None, alias="totalUnrealizedPnl" + ) + total_pnl: Optional[StrictStr] = Field(default=None, alias="totalPnl") + total_cost_basis: Optional[StrictStr] = Field(default=None, alias="totalCostBasis") + total_current_value: Optional[StrictStr] = Field( + default=None, alias="totalCurrentValue" + ) + positions: Optional[List[GetPortfolioResponsePositionsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "chainId", + "walletAddress", + "activePositionsCount", + "totalRealizedPnl", + "totalUnrealizedPnl", + "totalPnl", + "totalCostBasis", + "totalCurrentValue", + "positions", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetPortfolioResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in positions (list) + _items = [] + if self.positions: + for _item_positions in self.positions: + if _item_positions: + _items.append(_item_positions.to_dict()) + _dict["positions"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetPortfolioResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "chainId": obj.get("chainId"), + "walletAddress": obj.get("walletAddress"), + "activePositionsCount": obj.get("activePositionsCount"), + "totalRealizedPnl": obj.get("totalRealizedPnl"), + "totalUnrealizedPnl": obj.get("totalUnrealizedPnl"), + "totalPnl": obj.get("totalPnl"), + "totalCostBasis": obj.get("totalCostBasis"), + "totalCurrentValue": obj.get("totalCurrentValue"), + "positions": ( + [ + GetPortfolioResponsePositionsInner.from_dict(_item) + for _item in obj["positions"] + ] + if obj.get("positions") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_portfolio_response_positions_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_portfolio_response_positions_inner.py new file mode 100644 index 00000000..b00a94b5 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_portfolio_response_positions_inner.py @@ -0,0 +1,146 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class GetPortfolioResponsePositionsInner(BaseModel): + """ + GetPortfolioResponsePositionsInner + """ # noqa: E501 + + id: Optional[StrictInt] = None + wallet_address: Optional[StrictStr] = Field(default=None, alias="walletAddress") + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + vendor: Optional[StrictStr] = None + current_shares: Optional[StrictStr] = Field(default=None, alias="currentShares") + avg_price: Optional[StrictStr] = Field(default=None, alias="avgPrice") + current_price: Optional[StrictStr] = Field(default=None, alias="currentPrice") + realized_pnl: Optional[StrictStr] = Field(default=None, alias="realizedPnl") + unrealized_pnl: Optional[StrictStr] = Field(default=None, alias="unrealizedPnl") + total_pnl: Optional[StrictStr] = Field(default=None, alias="totalPnl") + pnl_percentage: Optional[StrictStr] = Field(default=None, alias="pnlPercentage") + is_resolved: Optional[StrictBool] = Field(default=None, alias="isResolved") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "id", + "walletAddress", + "marketTopicId", + "marketId", + "tokenId", + "vendor", + "currentShares", + "avgPrice", + "currentPrice", + "realizedPnl", + "unrealizedPnl", + "totalPnl", + "pnlPercentage", + "isResolved", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetPortfolioResponsePositionsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetPortfolioResponsePositionsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "id": obj.get("id"), + "walletAddress": obj.get("walletAddress"), + "marketTopicId": obj.get("marketTopicId"), + "marketId": obj.get("marketId"), + "tokenId": obj.get("tokenId"), + "vendor": obj.get("vendor"), + "currentShares": obj.get("currentShares"), + "avgPrice": obj.get("avgPrice"), + "currentPrice": obj.get("currentPrice"), + "realizedPnl": obj.get("realizedPnl"), + "unrealizedPnl": obj.get("unrealizedPnl"), + "totalPnl": obj.get("totalPnl"), + "pnlPercentage": obj.get("pnlPercentage"), + "isResolved": obj.get("isResolved"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_position_by_token_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_position_by_token_response.py new file mode 100644 index 00000000..9025c2e6 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_position_by_token_response.py @@ -0,0 +1,115 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.get_position_by_token_response_position import ( + GetPositionByTokenResponsePosition, +) +from typing import Set +from typing_extensions import Self + + +class GetPositionByTokenResponse(BaseModel): + """ + GetPositionByTokenResponse + """ # noqa: E501 + + position: Optional[GetPositionByTokenResponsePosition] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["position"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetPositionByTokenResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of position + if self.position: + _dict["position"] = self.position.to_dict() + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetPositionByTokenResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "position": ( + GetPositionByTokenResponsePosition.from_dict(obj["position"]) + if obj.get("position") is not None + else None + ) + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_position_by_token_response_position.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_position_by_token_response_position.py new file mode 100644 index 00000000..553f0200 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_position_by_token_response_position.py @@ -0,0 +1,180 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class GetPositionByTokenResponsePosition(BaseModel): + """ + GetPositionByTokenResponsePosition + """ # noqa: E501 + + position_id: Optional[StrictInt] = Field(default=None, alias="positionId") + vendor: Optional[StrictStr] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + collateral_symbol: Optional[StrictStr] = Field( + default=None, alias="collateralSymbol" + ) + topic_type: Optional[StrictStr] = Field(default=None, alias="topicType") + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + market_topic_title: Optional[StrictStr] = Field( + default=None, alias="marketTopicTitle" + ) + market_title: Optional[StrictStr] = Field(default=None, alias="marketTitle") + outcome_name: Optional[StrictStr] = Field(default=None, alias="outcomeName") + outcome_index: Optional[StrictInt] = Field(default=None, alias="outcomeIndex") + shares: Optional[StrictStr] = None + avg_price: Optional[StrictStr] = Field(default=None, alias="avgPrice") + total_cost: Optional[StrictStr] = Field(default=None, alias="totalCost") + value: Optional[StrictStr] = None + current_price: Optional[StrictStr] = Field(default=None, alias="currentPrice") + position_status: Optional[StrictStr] = Field(default=None, alias="positionStatus") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + unrealized_pnl: Optional[StrictStr] = Field(default=None, alias="unrealizedPnl") + realized_pnl: Optional[StrictStr] = Field(default=None, alias="realizedPnl") + pnl: Optional[StrictStr] = None + created_time: Optional[StrictInt] = Field(default=None, alias="createdTime") + updated_time: Optional[StrictInt] = Field(default=None, alias="updatedTime") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "positionId", + "vendor", + "chainId", + "tokenId", + "collateralSymbol", + "topicType", + "marketTopicId", + "marketId", + "marketTopicTitle", + "marketTitle", + "outcomeName", + "outcomeIndex", + "shares", + "avgPrice", + "totalCost", + "value", + "currentPrice", + "positionStatus", + "endDate", + "unrealizedPnl", + "realizedPnl", + "pnl", + "createdTime", + "updatedTime", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetPositionByTokenResponsePosition from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetPositionByTokenResponsePosition from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "positionId": obj.get("positionId"), + "vendor": obj.get("vendor"), + "chainId": obj.get("chainId"), + "tokenId": obj.get("tokenId"), + "collateralSymbol": obj.get("collateralSymbol"), + "topicType": obj.get("topicType"), + "marketTopicId": obj.get("marketTopicId"), + "marketId": obj.get("marketId"), + "marketTopicTitle": obj.get("marketTopicTitle"), + "marketTitle": obj.get("marketTitle"), + "outcomeName": obj.get("outcomeName"), + "outcomeIndex": obj.get("outcomeIndex"), + "shares": obj.get("shares"), + "avgPrice": obj.get("avgPrice"), + "totalCost": obj.get("totalCost"), + "value": obj.get("value"), + "currentPrice": obj.get("currentPrice"), + "positionStatus": obj.get("positionStatus"), + "endDate": obj.get("endDate"), + "unrealizedPnl": obj.get("unrealizedPnl"), + "realizedPnl": obj.get("realizedPnl"), + "pnl": obj.get("pnl"), + "createdTime": obj.get("createdTime"), + "updatedTime": obj.get("updatedTime"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_quota_status_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_quota_status_response.py new file mode 100644 index 00000000..3f28917d --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_quota_status_response.py @@ -0,0 +1,109 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class GetQuotaStatusResponse(BaseModel): + """ + GetQuotaStatusResponse + """ # noqa: E501 + + daily_limit: Optional[StrictStr] = Field(default=None, alias="dailyLimit") + remaining_daily_limit: Optional[StrictStr] = Field( + default=None, alias="remainingDailyLimit" + ) + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["dailyLimit", "remainingDailyLimit"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetQuotaStatusResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetQuotaStatusResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "dailyLimit": obj.get("dailyLimit"), + "remainingDailyLimit": obj.get("remainingDailyLimit"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_quote_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_quote_response.py new file mode 100644 index 00000000..c41c359c --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_quote_response.py @@ -0,0 +1,200 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import ( + BaseModel, + ConfigDict, + Field, + StrictBool, + StrictFloat, + StrictInt, + StrictStr, +) +from typing import Any, ClassVar, Dict, List, Optional, Union +from typing import Set +from typing_extensions import Self + + +class GetQuoteResponse(BaseModel): + """ + GetQuoteResponse + """ # noqa: E501 + + quote_id: Optional[StrictStr] = Field(default=None, alias="quoteId") + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + chance: Optional[StrictStr] = None + vendor: Optional[StrictStr] = None + market_title: Optional[StrictStr] = Field(default=None, alias="marketTitle") + market_ext_id: Optional[StrictStr] = Field(default=None, alias="marketExtId") + side: Optional[StrictStr] = None + amount_in: Optional[StrictStr] = Field(default=None, alias="amountIn") + amount_out: Optional[StrictStr] = Field(default=None, alias="amountOut") + is_min_amount_out: Optional[StrictBool] = Field( + default=None, alias="isMinAmountOut" + ) + fee_amount: Optional[StrictStr] = Field(default=None, alias="feeAmount") + fee_discount_bps: Optional[StrictStr] = Field(default=None, alias="feeDiscountBps") + average_price: Optional[Union[StrictFloat, StrictInt]] = Field( + default=None, alias="averagePrice" + ) + last_price: Optional[Union[StrictFloat, StrictInt]] = Field( + default=None, alias="lastPrice" + ) + price_impact: Optional[Union[StrictFloat, StrictInt]] = Field( + default=None, alias="priceImpact" + ) + timestamp: Optional[StrictInt] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + user_id: Optional[StrictInt] = Field(default=None, alias="userId") + wallet_address: Optional[StrictStr] = Field(default=None, alias="walletAddress") + order_type: Optional[StrictStr] = Field(default=None, alias="orderType") + slippage_bps: Optional[StrictInt] = Field(default=None, alias="slippageBps") + fee_rate_bps: Optional[StrictInt] = Field(default=None, alias="feeRateBps") + min_receive: Optional[StrictStr] = Field(default=None, alias="minReceive") + expire_at: Optional[StrictInt] = Field(default=None, alias="expireAt") + price_limit: Optional[StrictStr] = Field(default=None, alias="priceLimit") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "quoteId", + "tokenId", + "chance", + "vendor", + "marketTitle", + "marketExtId", + "side", + "amountIn", + "amountOut", + "isMinAmountOut", + "feeAmount", + "feeDiscountBps", + "averagePrice", + "lastPrice", + "priceImpact", + "timestamp", + "chainId", + "userId", + "walletAddress", + "orderType", + "slippageBps", + "feeRateBps", + "minReceive", + "expireAt", + "priceLimit", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetQuoteResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if price_limit (nullable) is None + # and model_fields_set contains the field + if self.price_limit is None and "price_limit" in self.model_fields_set: + _dict["priceLimit"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetQuoteResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "quoteId": obj.get("quoteId"), + "tokenId": obj.get("tokenId"), + "chance": obj.get("chance"), + "vendor": obj.get("vendor"), + "marketTitle": obj.get("marketTitle"), + "marketExtId": obj.get("marketExtId"), + "side": obj.get("side"), + "amountIn": obj.get("amountIn"), + "amountOut": obj.get("amountOut"), + "isMinAmountOut": obj.get("isMinAmountOut"), + "feeAmount": obj.get("feeAmount"), + "feeDiscountBps": obj.get("feeDiscountBps"), + "averagePrice": obj.get("averagePrice"), + "lastPrice": obj.get("lastPrice"), + "priceImpact": obj.get("priceImpact"), + "timestamp": obj.get("timestamp"), + "chainId": obj.get("chainId"), + "userId": obj.get("userId"), + "walletAddress": obj.get("walletAddress"), + "orderType": obj.get("orderType"), + "slippageBps": obj.get("slippageBps"), + "feeRateBps": obj.get("feeRateBps"), + "minReceive": obj.get("minReceive"), + "expireAt": obj.get("expireAt"), + "priceLimit": obj.get("priceLimit"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_redeem_status_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_redeem_status_response.py new file mode 100644 index 00000000..e66f1db0 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/get_redeem_status_response.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class GetRedeemStatusResponse(BaseModel): + """ + GetRedeemStatusResponse + """ # noqa: E501 + + tx_hash: Optional[StrictStr] = Field(default=None, alias="txHash") + status: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["txHash", "status"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetRedeemStatusResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetRedeemStatusResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + {"txHash": obj.get("txHash"), "status": obj.get("status")} + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response.py new file mode 100644 index 00000000..aa79cb2c --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.list_prediction_categories_response_categories_inner import ( + ListPredictionCategoriesResponseCategoriesInner, +) +from typing import Set +from typing_extensions import Self + + +class ListPredictionCategoriesResponse(BaseModel): + """ + ListPredictionCategoriesResponse + """ # noqa: E501 + + categories: Optional[List[ListPredictionCategoriesResponseCategoriesInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["categories"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ListPredictionCategoriesResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in categories (list) + _items = [] + if self.categories: + for _item_categories in self.categories: + if _item_categories: + _items.append(_item_categories.to_dict()) + _dict["categories"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ListPredictionCategoriesResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "categories": ( + [ + ListPredictionCategoriesResponseCategoriesInner.from_dict(_item) + for _item in obj["categories"] + ] + if obj.get("categories") is not None + else None + ) + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response_categories_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response_categories_inner.py new file mode 100644 index 00000000..47be0578 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response_categories_inner.py @@ -0,0 +1,134 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.list_prediction_categories_response_categories_inner_subcategories_inner import ( + ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner, +) +from typing import Set +from typing_extensions import Self + + +class ListPredictionCategoriesResponseCategoriesInner(BaseModel): + """ + ListPredictionCategoriesResponseCategoriesInner + """ # noqa: E501 + + id: Optional[StrictStr] = None + name: Optional[StrictStr] = None + icon: Optional[StrictStr] = None + order: Optional[StrictInt] = None + subcategories: Optional[ + List[ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner] + ] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "name", "icon", "order", "subcategories"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ListPredictionCategoriesResponseCategoriesInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in subcategories (list) + _items = [] + if self.subcategories: + for _item_subcategories in self.subcategories: + if _item_subcategories: + _items.append(_item_subcategories.to_dict()) + _dict["subcategories"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ListPredictionCategoriesResponseCategoriesInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "id": obj.get("id"), + "name": obj.get("name"), + "icon": obj.get("icon"), + "order": obj.get("order"), + "subcategories": ( + [ + ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner.from_dict( + _item + ) + for _item in obj["subcategories"] + ] + if obj.get("subcategories") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response_categories_inner_subcategories_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response_categories_inner_subcategories_inner.py new file mode 100644 index 00000000..a8b5fef3 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_categories_response_categories_inner_subcategories_inner.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner(BaseModel): + """ + ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner + """ # noqa: E501 + + id: Optional[StrictStr] = None + name: Optional[StrictStr] = None + icon: Optional[StrictStr] = None + order: Optional[StrictInt] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["id", "name", "icon", "order"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ListPredictionCategoriesResponseCategoriesInnerSubcategoriesInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "id": obj.get("id"), + "name": obj.get("name"), + "icon": obj.get("icon"), + "order": obj.get("order"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_markets_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_markets_response.py new file mode 100644 index 00000000..65d274ae --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_markets_response.py @@ -0,0 +1,138 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.list_prediction_markets_response_market_topics_inner import ( + ListPredictionMarketsResponseMarketTopicsInner, +) +from typing import Set +from typing_extensions import Self + + +class ListPredictionMarketsResponse(BaseModel): + """ + ListPredictionMarketsResponse + """ # noqa: E501 + + market_topics: Optional[List[ListPredictionMarketsResponseMarketTopicsInner]] = ( + Field(default=None, alias="marketTopics") + ) + total: Optional[StrictInt] = None + offset: Optional[StrictInt] = None + limit: Optional[StrictInt] = None + has_more: Optional[StrictBool] = Field(default=None, alias="hasMore") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "marketTopics", + "total", + "offset", + "limit", + "hasMore", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ListPredictionMarketsResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in market_topics (list) + _items = [] + if self.market_topics: + for _item_market_topics in self.market_topics: + if _item_market_topics: + _items.append(_item_market_topics.to_dict()) + _dict["marketTopics"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ListPredictionMarketsResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "marketTopics": ( + [ + ListPredictionMarketsResponseMarketTopicsInner.from_dict(_item) + for _item in obj["marketTopics"] + ] + if obj.get("marketTopics") is not None + else None + ), + "total": obj.get("total"), + "offset": obj.get("offset"), + "limit": obj.get("limit"), + "hasMore": obj.get("hasMore"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_markets_response_market_topics_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_markets_response_market_topics_inner.py new file mode 100644 index 00000000..4fca2766 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_markets_response_market_topics_inner.py @@ -0,0 +1,175 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class ListPredictionMarketsResponseMarketTopicsInner(BaseModel): + """ + ListPredictionMarketsResponseMarketTopicsInner + """ # noqa: E501 + + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + vendor: Optional[StrictStr] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + slug: Optional[StrictStr] = None + title: Optional[StrictStr] = None + question: Optional[StrictStr] = None + description: Optional[StrictStr] = None + image_url: Optional[StrictStr] = Field(default=None, alias="imageUrl") + topic_type: Optional[StrictStr] = Field(default=None, alias="topicType") + chart_type: Optional[StrictStr] = Field(default=None, alias="chartType") + symbol: Optional[StrictStr] = None + participant_count: Optional[StrictInt] = Field( + default=None, alias="participantCount" + ) + collateral: Optional[StrictStr] = None + fee_rate_bps: Optional[StrictInt] = Field(default=None, alias="feeRateBps") + slippage_bps: Optional[StrictInt] = Field(default=None, alias="slippageBps") + is_yield_bearing: Optional[StrictBool] = Field(default=None, alias="isYieldBearing") + trade_volume: Optional[StrictStr] = Field(default=None, alias="tradeVolume") + liquidity: Optional[StrictStr] = None + published_at: Optional[StrictInt] = Field(default=None, alias="publishedAt") + start_date: Optional[StrictInt] = Field(default=None, alias="startDate") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + status: Optional[StrictStr] = None + markets: Optional[List[Dict[str, Any]]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "marketTopicId", + "vendor", + "chainId", + "slug", + "title", + "question", + "description", + "imageUrl", + "topicType", + "chartType", + "symbol", + "participantCount", + "collateral", + "feeRateBps", + "slippageBps", + "isYieldBearing", + "tradeVolume", + "liquidity", + "publishedAt", + "startDate", + "endDate", + "status", + "markets", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ListPredictionMarketsResponseMarketTopicsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ListPredictionMarketsResponseMarketTopicsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "marketTopicId": obj.get("marketTopicId"), + "vendor": obj.get("vendor"), + "chainId": obj.get("chainId"), + "slug": obj.get("slug"), + "title": obj.get("title"), + "question": obj.get("question"), + "description": obj.get("description"), + "imageUrl": obj.get("imageUrl"), + "topicType": obj.get("topicType"), + "chartType": obj.get("chartType"), + "symbol": obj.get("symbol"), + "participantCount": obj.get("participantCount"), + "collateral": obj.get("collateral"), + "feeRateBps": obj.get("feeRateBps"), + "slippageBps": obj.get("slippageBps"), + "isYieldBearing": obj.get("isYieldBearing"), + "tradeVolume": obj.get("tradeVolume"), + "liquidity": obj.get("liquidity"), + "publishedAt": obj.get("publishedAt"), + "startDate": obj.get("startDate"), + "endDate": obj.get("endDate"), + "status": obj.get("status"), + "markets": obj.get("markets"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_wallets_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_wallets_response.py new file mode 100644 index 00000000..6c221753 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_wallets_response.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.list_prediction_wallets_response_wallets_inner import ( + ListPredictionWalletsResponseWalletsInner, +) +from typing import Set +from typing_extensions import Self + + +class ListPredictionWalletsResponse(BaseModel): + """ + ListPredictionWalletsResponse + """ # noqa: E501 + + wallets: Optional[List[ListPredictionWalletsResponseWalletsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["wallets"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ListPredictionWalletsResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in wallets (list) + _items = [] + if self.wallets: + for _item_wallets in self.wallets: + if _item_wallets: + _items.append(_item_wallets.to_dict()) + _dict["wallets"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ListPredictionWalletsResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "wallets": ( + [ + ListPredictionWalletsResponseWalletsInner.from_dict(_item) + for _item in obj["wallets"] + ] + if obj.get("wallets") is not None + else None + ) + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_wallets_response_wallets_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_wallets_response_wallets_inner.py new file mode 100644 index 00000000..6440a186 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/list_prediction_wallets_response_wallets_inner.py @@ -0,0 +1,109 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class ListPredictionWalletsResponseWalletsInner(BaseModel): + """ + ListPredictionWalletsResponseWalletsInner + """ # noqa: E501 + + wallet_address: Optional[StrictStr] = Field(default=None, alias="walletAddress") + wallet_id: Optional[StrictStr] = Field(default=None, alias="walletId") + registered_time: Optional[StrictInt] = Field(default=None, alias="registeredTime") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["walletAddress", "walletId", "registeredTime"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ListPredictionWalletsResponseWalletsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ListPredictionWalletsResponseWalletsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "walletAddress": obj.get("walletAddress"), + "walletId": obj.get("walletId"), + "registeredTime": obj.get("registeredTime"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/kline_candlestick_data_response_item.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/market_search_response.py similarity index 81% rename from clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/kline_candlestick_data_response_item.py rename to clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/market_search_response.py index d607f7a7..8417d408 100644 --- a/clients/derivatives_trading_coin_futures/src/binance_sdk_derivatives_trading_coin_futures/rest_api/models/kline_candlestick_data_response_item.py +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/market_search_response.py @@ -1,30 +1,32 @@ # coding: utf-8 """ -Binance Derivatives Trading COIN Futures REST API +Prediction Trading REST API -OpenAPI Specification for the Binance Derivatives Trading COIN Futures REST API +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. The version of the OpenAPI document: 1.0.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. """ - from __future__ import annotations import pprint import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict +from pydantic import ConfigDict from typing import Any, ClassVar, Dict +from binance_sdk_w3w_prediction.rest_api.models.market_search_response_inner import ( + MarketSearchResponseInner, +) from typing import Optional, Set, List from typing_extensions import Self -class KlineCandlestickDataResponseItem(BaseModel): +class MarketSearchResponse(MarketSearchResponseInner): """ - KlineCandlestickDataResponseItem + MarketSearchResponse """ # noqa: E501 __properties: ClassVar[List[str]] = [] @@ -50,7 +52,7 @@ def is_array(cls) -> bool: @classmethod def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of KlineCandlestickDataResponseItem from a JSON string""" + """Create an instance of MarketSearchResponse from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/market_search_response_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/market_search_response_inner.py new file mode 100644 index 00000000..b8bedd19 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/market_search_response_inner.py @@ -0,0 +1,160 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class MarketSearchResponseInner(BaseModel): + """ + MarketSearchResponseInner + """ # noqa: E501 + + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + vendor: Optional[StrictStr] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + slug: Optional[StrictStr] = None + title: Optional[StrictStr] = None + question: Optional[StrictStr] = None + description: Optional[StrictStr] = None + topic_type: Optional[StrictStr] = Field(default=None, alias="topicType") + chart_type: Optional[StrictStr] = Field(default=None, alias="chartType") + symbol: Optional[StrictStr] = None + participant_count: Optional[StrictInt] = Field( + default=None, alias="participantCount" + ) + collateral: Optional[StrictStr] = None + trade_volume: Optional[StrictStr] = Field(default=None, alias="tradeVolume") + liquidity: Optional[StrictStr] = None + start_date: Optional[StrictInt] = Field(default=None, alias="startDate") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + status: Optional[StrictStr] = None + markets: Optional[List[Dict[str, Any]]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "marketTopicId", + "vendor", + "chainId", + "slug", + "title", + "question", + "description", + "topicType", + "chartType", + "symbol", + "participantCount", + "collateral", + "tradeVolume", + "liquidity", + "startDate", + "endDate", + "status", + "markets", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of MarketSearchResponseInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of MarketSearchResponseInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "marketTopicId": obj.get("marketTopicId"), + "vendor": obj.get("vendor"), + "chainId": obj.get("chainId"), + "slug": obj.get("slug"), + "title": obj.get("title"), + "question": obj.get("question"), + "description": obj.get("description"), + "topicType": obj.get("topicType"), + "chartType": obj.get("chartType"), + "symbol": obj.get("symbol"), + "participantCount": obj.get("participantCount"), + "collateral": obj.get("collateral"), + "tradeVolume": obj.get("tradeVolume"), + "liquidity": obj.get("liquidity"), + "startDate": obj.get("startDate"), + "endDate": obj.get("endDate"), + "status": obj.get("status"), + "markets": obj.get("markets"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/place_order_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/place_order_response.py new file mode 100644 index 00000000..8a27972b --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/place_order_response.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class PlaceOrderResponse(BaseModel): + """ + PlaceOrderResponse + """ # noqa: E501 + + order_id: Optional[StrictStr] = Field(default=None, alias="orderId") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["orderId"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of PlaceOrderResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of PlaceOrderResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"orderId": obj.get("orderId")}) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_active_orders_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_active_orders_response.py new file mode 100644 index 00000000..af5e3ad1 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_active_orders_response.py @@ -0,0 +1,128 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_active_orders_response_orders_inner import ( + QueryActiveOrdersResponseOrdersInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryActiveOrdersResponse(BaseModel): + """ + QueryActiveOrdersResponse + """ # noqa: E501 + + total: Optional[StrictInt] = None + offset: Optional[StrictInt] = None + limit: Optional[StrictInt] = None + orders: Optional[List[QueryActiveOrdersResponseOrdersInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["total", "offset", "limit", "orders"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryActiveOrdersResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in orders (list) + _items = [] + if self.orders: + for _item_orders in self.orders: + if _item_orders: + _items.append(_item_orders.to_dict()) + _dict["orders"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryActiveOrdersResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "total": obj.get("total"), + "offset": obj.get("offset"), + "limit": obj.get("limit"), + "orders": ( + [ + QueryActiveOrdersResponseOrdersInner.from_dict(_item) + for _item in obj["orders"] + ] + if obj.get("orders") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_active_orders_response_orders_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_active_orders_response_orders_inner.py new file mode 100644 index 00000000..94faa5fe --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_active_orders_response_orders_inner.py @@ -0,0 +1,181 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryActiveOrdersResponseOrdersInner(BaseModel): + """ + QueryActiveOrdersResponseOrdersInner + """ # noqa: E501 + + order_id: Optional[StrictStr] = Field(default=None, alias="orderId") + vendor_order_id: Optional[StrictStr] = Field(default=None, alias="vendorOrderId") + vendor: Optional[StrictStr] = None + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + slug: Optional[StrictStr] = None + market_topic_title: Optional[StrictStr] = Field( + default=None, alias="marketTopicTitle" + ) + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + market_title: Optional[StrictStr] = Field(default=None, alias="marketTitle") + outcome: Optional[StrictStr] = None + outcome_index: Optional[StrictInt] = Field(default=None, alias="outcomeIndex") + status: Optional[StrictStr] = None + side: Optional[StrictStr] = None + order_type: Optional[StrictStr] = Field(default=None, alias="orderType") + create_time: Optional[StrictInt] = Field(default=None, alias="createTime") + modify_time: Optional[StrictInt] = Field(default=None, alias="modifyTime") + maker_usdt_amount: Optional[StrictStr] = Field( + default=None, alias="makerUsdtAmount" + ) + maker_share_qty: Optional[StrictStr] = Field(default=None, alias="makerShareQty") + filled_usdt_amount: Optional[StrictStr] = Field( + default=None, alias="filledUsdtAmount" + ) + filled_share_qty: Optional[StrictStr] = Field(default=None, alias="filledShareQty") + fill_percentage: Optional[StrictStr] = Field(default=None, alias="fillPercentage") + price: Optional[StrictStr] = None + market_provider_fee: Optional[StrictStr] = Field( + default=None, alias="marketProviderFee" + ) + network_fee: Optional[StrictStr] = Field(default=None, alias="networkFee") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "orderId", + "vendorOrderId", + "vendor", + "marketTopicId", + "slug", + "marketTopicTitle", + "marketId", + "marketTitle", + "outcome", + "outcomeIndex", + "status", + "side", + "orderType", + "createTime", + "modifyTime", + "makerUsdtAmount", + "makerShareQty", + "filledUsdtAmount", + "filledShareQty", + "fillPercentage", + "price", + "marketProviderFee", + "networkFee", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryActiveOrdersResponseOrdersInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryActiveOrdersResponseOrdersInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "orderId": obj.get("orderId"), + "vendorOrderId": obj.get("vendorOrderId"), + "vendor": obj.get("vendor"), + "marketTopicId": obj.get("marketTopicId"), + "slug": obj.get("slug"), + "marketTopicTitle": obj.get("marketTopicTitle"), + "marketId": obj.get("marketId"), + "marketTitle": obj.get("marketTitle"), + "outcome": obj.get("outcome"), + "outcomeIndex": obj.get("outcomeIndex"), + "status": obj.get("status"), + "side": obj.get("side"), + "orderType": obj.get("orderType"), + "createTime": obj.get("createTime"), + "modifyTime": obj.get("modifyTime"), + "makerUsdtAmount": obj.get("makerUsdtAmount"), + "makerShareQty": obj.get("makerShareQty"), + "filledUsdtAmount": obj.get("filledUsdtAmount"), + "filledShareQty": obj.get("filledShareQty"), + "fillPercentage": obj.get("fillPercentage"), + "price": obj.get("price"), + "marketProviderFee": obj.get("marketProviderFee"), + "networkFee": obj.get("networkFee"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_last_trade_price_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_last_trade_price_response.py new file mode 100644 index 00000000..9f3ef5a8 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_last_trade_price_response.py @@ -0,0 +1,107 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryLastTradePriceResponse(BaseModel): + """ + QueryLastTradePriceResponse + """ # noqa: E501 + + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + last_trade_price: Optional[StrictStr] = Field(default=None, alias="lastTradePrice") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["marketId", "lastTradePrice"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryLastTradePriceResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryLastTradePriceResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "marketId": obj.get("marketId"), + "lastTradePrice": obj.get("lastTradePrice"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response.py new file mode 100644 index 00000000..c7fec770 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response.py @@ -0,0 +1,153 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_order_book_response_asks_inner import ( + QueryOrderBookResponseAsksInner, +) +from binance_sdk_w3w_prediction.rest_api.models.query_order_book_response_bids_inner import ( + QueryOrderBookResponseBidsInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryOrderBookResponse(BaseModel): + """ + QueryOrderBookResponse + """ # noqa: E501 + + outcome: Optional[StrictStr] = None + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + timestamp: Optional[StrictInt] = None + bids: Optional[List[QueryOrderBookResponseBidsInner]] = None + asks: Optional[List[QueryOrderBookResponseAsksInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "outcome", + "tokenId", + "timestamp", + "bids", + "asks", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryOrderBookResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in bids (list) + _items = [] + if self.bids: + for _item_bids in self.bids: + if _item_bids: + _items.append(_item_bids.to_dict()) + _dict["bids"] = _items + # override the default output from pydantic by calling `to_dict()` of each item in asks (list) + _items = [] + if self.asks: + for _item_asks in self.asks: + if _item_asks: + _items.append(_item_asks.to_dict()) + _dict["asks"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryOrderBookResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "outcome": obj.get("outcome"), + "tokenId": obj.get("tokenId"), + "timestamp": obj.get("timestamp"), + "bids": ( + [ + QueryOrderBookResponseBidsInner.from_dict(_item) + for _item in obj["bids"] + ] + if obj.get("bids") is not None + else None + ), + "asks": ( + [ + QueryOrderBookResponseAsksInner.from_dict(_item) + for _item in obj["asks"] + ] + if obj.get("asks") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response_asks_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response_asks_inner.py new file mode 100644 index 00000000..5e7cc67f --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response_asks_inner.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryOrderBookResponseAsksInner(BaseModel): + """ + QueryOrderBookResponseAsksInner + """ # noqa: E501 + + price: Optional[StrictStr] = None + size: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["price", "size"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryOrderBookResponseAsksInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryOrderBookResponseAsksInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"price": obj.get("price"), "size": obj.get("size")}) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response_bids_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response_bids_inner.py new file mode 100644 index 00000000..23fe5f54 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_book_response_bids_inner.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryOrderBookResponseBidsInner(BaseModel): + """ + QueryOrderBookResponseBidsInner + """ # noqa: E501 + + price: Optional[StrictStr] = None + size: Optional[StrictStr] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["price", "size"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryOrderBookResponseBidsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryOrderBookResponseBidsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"price": obj.get("price"), "size": obj.get("size")}) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_history_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_history_response.py new file mode 100644 index 00000000..63274f8b --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_history_response.py @@ -0,0 +1,128 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_order_history_response_orders_inner import ( + QueryOrderHistoryResponseOrdersInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryOrderHistoryResponse(BaseModel): + """ + QueryOrderHistoryResponse + """ # noqa: E501 + + total: Optional[StrictInt] = None + offset: Optional[StrictInt] = None + limit: Optional[StrictInt] = None + orders: Optional[List[QueryOrderHistoryResponseOrdersInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["total", "offset", "limit", "orders"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryOrderHistoryResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in orders (list) + _items = [] + if self.orders: + for _item_orders in self.orders: + if _item_orders: + _items.append(_item_orders.to_dict()) + _dict["orders"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryOrderHistoryResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "total": obj.get("total"), + "offset": obj.get("offset"), + "limit": obj.get("limit"), + "orders": ( + [ + QueryOrderHistoryResponseOrdersInner.from_dict(_item) + for _item in obj["orders"] + ] + if obj.get("orders") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_history_response_orders_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_history_response_orders_inner.py new file mode 100644 index 00000000..f8d192e4 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_order_history_response_orders_inner.py @@ -0,0 +1,184 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryOrderHistoryResponseOrdersInner(BaseModel): + """ + QueryOrderHistoryResponseOrdersInner + """ # noqa: E501 + + order_id: Optional[StrictStr] = Field(default=None, alias="orderId") + vendor_order_id: Optional[StrictStr] = Field(default=None, alias="vendorOrderId") + vendor: Optional[StrictStr] = None + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + slug: Optional[StrictStr] = None + market_topic_title: Optional[StrictStr] = Field( + default=None, alias="marketTopicTitle" + ) + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + market_title: Optional[StrictStr] = Field(default=None, alias="marketTitle") + outcome: Optional[StrictStr] = None + outcome_index: Optional[StrictInt] = Field(default=None, alias="outcomeIndex") + status: Optional[StrictStr] = None + side: Optional[StrictStr] = None + order_type: Optional[StrictStr] = Field(default=None, alias="orderType") + create_time: Optional[StrictInt] = Field(default=None, alias="createTime") + modify_time: Optional[StrictInt] = Field(default=None, alias="modifyTime") + terminal_time: Optional[StrictInt] = Field(default=None, alias="terminalTime") + maker_usdt_amount: Optional[StrictStr] = Field( + default=None, alias="makerUsdtAmount" + ) + maker_share_qty: Optional[StrictStr] = Field(default=None, alias="makerShareQty") + filled_usdt_amount: Optional[StrictStr] = Field( + default=None, alias="filledUsdtAmount" + ) + filled_share_qty: Optional[StrictStr] = Field(default=None, alias="filledShareQty") + fill_percentage: Optional[StrictStr] = Field(default=None, alias="fillPercentage") + price: Optional[StrictStr] = None + market_provider_fee: Optional[StrictStr] = Field( + default=None, alias="marketProviderFee" + ) + network_fee: Optional[StrictStr] = Field(default=None, alias="networkFee") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "orderId", + "vendorOrderId", + "vendor", + "marketTopicId", + "slug", + "marketTopicTitle", + "marketId", + "marketTitle", + "outcome", + "outcomeIndex", + "status", + "side", + "orderType", + "createTime", + "modifyTime", + "terminalTime", + "makerUsdtAmount", + "makerShareQty", + "filledUsdtAmount", + "filledShareQty", + "fillPercentage", + "price", + "marketProviderFee", + "networkFee", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryOrderHistoryResponseOrdersInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryOrderHistoryResponseOrdersInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "orderId": obj.get("orderId"), + "vendorOrderId": obj.get("vendorOrderId"), + "vendor": obj.get("vendor"), + "marketTopicId": obj.get("marketTopicId"), + "slug": obj.get("slug"), + "marketTopicTitle": obj.get("marketTopicTitle"), + "marketId": obj.get("marketId"), + "marketTitle": obj.get("marketTitle"), + "outcome": obj.get("outcome"), + "outcomeIndex": obj.get("outcomeIndex"), + "status": obj.get("status"), + "side": obj.get("side"), + "orderType": obj.get("orderType"), + "createTime": obj.get("createTime"), + "modifyTime": obj.get("modifyTime"), + "terminalTime": obj.get("terminalTime"), + "makerUsdtAmount": obj.get("makerUsdtAmount"), + "makerShareQty": obj.get("makerShareQty"), + "filledUsdtAmount": obj.get("filledUsdtAmount"), + "filledShareQty": obj.get("filledShareQty"), + "fillPercentage": obj.get("fillPercentage"), + "price": obj.get("price"), + "marketProviderFee": obj.get("marketProviderFee"), + "networkFee": obj.get("networkFee"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_payment_option_balances_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_payment_option_balances_response.py new file mode 100644 index 00000000..21622178 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_payment_option_balances_response.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_payment_option_balances_response_items_inner import ( + QueryPaymentOptionBalancesResponseItemsInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryPaymentOptionBalancesResponse(BaseModel): + """ + QueryPaymentOptionBalancesResponse + """ # noqa: E501 + + items: Optional[List[QueryPaymentOptionBalancesResponseItemsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["items"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPaymentOptionBalancesResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in items (list) + _items = [] + if self.items: + for _item_items in self.items: + if _item_items: + _items.append(_item_items.to_dict()) + _dict["items"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPaymentOptionBalancesResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "items": ( + [ + QueryPaymentOptionBalancesResponseItemsInner.from_dict(_item) + for _item in obj["items"] + ] + if obj.get("items") is not None + else None + ) + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_payment_option_balances_response_items_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_payment_option_balances_response_items_inner.py new file mode 100644 index 00000000..fded4713 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_payment_option_balances_response_items_inner.py @@ -0,0 +1,115 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryPaymentOptionBalancesResponseItemsInner(BaseModel): + """ + QueryPaymentOptionBalancesResponseItemsInner + """ # noqa: E501 + + account_type: Optional[StrictStr] = Field(default=None, alias="accountType") + available_balance_display: Optional[StrictStr] = Field( + default=None, alias="availableBalanceDisplay" + ) + enabled: Optional[StrictBool] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "accountType", + "availableBalanceDisplay", + "enabled", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPaymentOptionBalancesResponseItemsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPaymentOptionBalancesResponseItemsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "accountType": obj.get("accountType"), + "availableBalanceDisplay": obj.get("availableBalanceDisplay"), + "enabled": obj.get("enabled"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_pn_l_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_pn_l_response.py new file mode 100644 index 00000000..c0e5140a --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_pn_l_response.py @@ -0,0 +1,156 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.get_portfolio_response_positions_inner import ( + GetPortfolioResponsePositionsInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryPnLResponse(BaseModel): + """ + QueryPnLResponse + """ # noqa: E501 + + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + wallet_address: Optional[StrictStr] = Field(default=None, alias="walletAddress") + pnl: Optional[StrictStr] = None + pnl_list: Optional[List[GetPortfolioResponsePositionsInner]] = Field( + default=None, alias="pnlList" + ) + total_count: Optional[StrictInt] = Field(default=None, alias="totalCount") + total_realized_pnl: Optional[StrictStr] = Field( + default=None, alias="totalRealizedPnl" + ) + total_unrealized_pnl: Optional[StrictStr] = Field( + default=None, alias="totalUnrealizedPnl" + ) + total_pnl: Optional[StrictStr] = Field(default=None, alias="totalPnl") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "chainId", + "walletAddress", + "pnl", + "pnlList", + "totalCount", + "totalRealizedPnl", + "totalUnrealizedPnl", + "totalPnl", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPnLResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in pnl_list (list) + _items = [] + if self.pnl_list: + for _item_pnl_list in self.pnl_list: + if _item_pnl_list: + _items.append(_item_pnl_list.to_dict()) + _dict["pnlList"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if pnl (nullable) is None + # and model_fields_set contains the field + if self.pnl is None and "pnl" in self.model_fields_set: + _dict["pnl"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPnLResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "chainId": obj.get("chainId"), + "walletAddress": obj.get("walletAddress"), + "pnl": obj.get("pnl"), + "pnlList": ( + [ + GetPortfolioResponsePositionsInner.from_dict(_item) + for _item in obj["pnlList"] + ] + if obj.get("pnlList") is not None + else None + ), + "totalCount": obj.get("totalCount"), + "totalRealizedPnl": obj.get("totalRealizedPnl"), + "totalUnrealizedPnl": obj.get("totalUnrealizedPnl"), + "totalPnl": obj.get("totalPnl"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_by_filter_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_by_filter_response.py new file mode 100644 index 00000000..e17aaeca --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_by_filter_response.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_positions_by_filter_response_positions_inner import ( + QueryPositionsByFilterResponsePositionsInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryPositionsByFilterResponse(BaseModel): + """ + QueryPositionsByFilterResponse + """ # noqa: E501 + + positions: Optional[List[QueryPositionsByFilterResponsePositionsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["positions"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPositionsByFilterResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in positions (list) + _items = [] + if self.positions: + for _item_positions in self.positions: + if _item_positions: + _items.append(_item_positions.to_dict()) + _dict["positions"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPositionsByFilterResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "positions": ( + [ + QueryPositionsByFilterResponsePositionsInner.from_dict(_item) + for _item in obj["positions"] + ] + if obj.get("positions") is not None + else None + ) + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_by_filter_response_positions_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_by_filter_response_positions_inner.py new file mode 100644 index 00000000..4a692a72 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_by_filter_response_positions_inner.py @@ -0,0 +1,180 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryPositionsByFilterResponsePositionsInner(BaseModel): + """ + QueryPositionsByFilterResponsePositionsInner + """ # noqa: E501 + + position_id: Optional[StrictInt] = Field(default=None, alias="positionId") + vendor: Optional[StrictStr] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + collateral_symbol: Optional[StrictStr] = Field( + default=None, alias="collateralSymbol" + ) + topic_type: Optional[StrictStr] = Field(default=None, alias="topicType") + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + market_topic_title: Optional[StrictStr] = Field( + default=None, alias="marketTopicTitle" + ) + market_title: Optional[StrictStr] = Field(default=None, alias="marketTitle") + outcome_name: Optional[StrictStr] = Field(default=None, alias="outcomeName") + outcome_index: Optional[StrictInt] = Field(default=None, alias="outcomeIndex") + shares: Optional[StrictStr] = None + avg_price: Optional[StrictStr] = Field(default=None, alias="avgPrice") + total_cost: Optional[StrictStr] = Field(default=None, alias="totalCost") + value: Optional[StrictStr] = None + current_price: Optional[StrictStr] = Field(default=None, alias="currentPrice") + position_status: Optional[StrictStr] = Field(default=None, alias="positionStatus") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + unrealized_pnl: Optional[StrictStr] = Field(default=None, alias="unrealizedPnl") + realized_pnl: Optional[StrictStr] = Field(default=None, alias="realizedPnl") + pnl: Optional[StrictStr] = None + created_time: Optional[StrictInt] = Field(default=None, alias="createdTime") + updated_time: Optional[StrictInt] = Field(default=None, alias="updatedTime") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "positionId", + "vendor", + "chainId", + "tokenId", + "collateralSymbol", + "topicType", + "marketTopicId", + "marketId", + "marketTopicTitle", + "marketTitle", + "outcomeName", + "outcomeIndex", + "shares", + "avgPrice", + "totalCost", + "value", + "currentPrice", + "positionStatus", + "endDate", + "unrealizedPnl", + "realizedPnl", + "pnl", + "createdTime", + "updatedTime", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPositionsByFilterResponsePositionsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPositionsByFilterResponsePositionsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "positionId": obj.get("positionId"), + "vendor": obj.get("vendor"), + "chainId": obj.get("chainId"), + "tokenId": obj.get("tokenId"), + "collateralSymbol": obj.get("collateralSymbol"), + "topicType": obj.get("topicType"), + "marketTopicId": obj.get("marketTopicId"), + "marketId": obj.get("marketId"), + "marketTopicTitle": obj.get("marketTopicTitle"), + "marketTitle": obj.get("marketTitle"), + "outcomeName": obj.get("outcomeName"), + "outcomeIndex": obj.get("outcomeIndex"), + "shares": obj.get("shares"), + "avgPrice": obj.get("avgPrice"), + "totalCost": obj.get("totalCost"), + "value": obj.get("value"), + "currentPrice": obj.get("currentPrice"), + "positionStatus": obj.get("positionStatus"), + "endDate": obj.get("endDate"), + "unrealizedPnl": obj.get("unrealizedPnl"), + "realizedPnl": obj.get("realizedPnl"), + "pnl": obj.get("pnl"), + "createdTime": obj.get("createdTime"), + "updatedTime": obj.get("updatedTime"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response.py new file mode 100644 index 00000000..b96cd89b --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response.py @@ -0,0 +1,146 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_positions_response_counts import ( + QueryPositionsResponseCounts, +) +from binance_sdk_w3w_prediction.rest_api.models.query_positions_response_positions_inner import ( + QueryPositionsResponsePositionsInner, +) +from binance_sdk_w3w_prediction.rest_api.models.query_positions_response_summary import ( + QueryPositionsResponseSummary, +) +from typing import Set +from typing_extensions import Self + + +class QueryPositionsResponse(BaseModel): + """ + QueryPositionsResponse + """ # noqa: E501 + + summary: Optional[QueryPositionsResponseSummary] = None + counts: Optional[QueryPositionsResponseCounts] = None + positions: Optional[List[QueryPositionsResponsePositionsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["summary", "counts", "positions"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPositionsResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of summary + if self.summary: + _dict["summary"] = self.summary.to_dict() + # override the default output from pydantic by calling `to_dict()` of counts + if self.counts: + _dict["counts"] = self.counts.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in positions (list) + _items = [] + if self.positions: + for _item_positions in self.positions: + if _item_positions: + _items.append(_item_positions.to_dict()) + _dict["positions"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPositionsResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "summary": ( + QueryPositionsResponseSummary.from_dict(obj["summary"]) + if obj.get("summary") is not None + else None + ), + "counts": ( + QueryPositionsResponseCounts.from_dict(obj["counts"]) + if obj.get("counts") is not None + else None + ), + "positions": ( + [ + QueryPositionsResponsePositionsInner.from_dict(_item) + for _item in obj["positions"] + ] + if obj.get("positions") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_counts.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_counts.py new file mode 100644 index 00000000..bf3913e5 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_counts.py @@ -0,0 +1,115 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryPositionsResponseCounts(BaseModel): + """ + QueryPositionsResponseCounts + """ # noqa: E501 + + ongoing_count: Optional[StrictInt] = Field(default=None, alias="ongoingCount") + ended_count: Optional[StrictInt] = Field(default=None, alias="endedCount") + pending_claim_count: Optional[StrictInt] = Field( + default=None, alias="pendingClaimCount" + ) + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "ongoingCount", + "endedCount", + "pendingClaimCount", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPositionsResponseCounts from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPositionsResponseCounts from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "ongoingCount": obj.get("ongoingCount"), + "endedCount": obj.get("endedCount"), + "pendingClaimCount": obj.get("pendingClaimCount"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_positions_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_positions_inner.py new file mode 100644 index 00000000..8dc472af --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_positions_inner.py @@ -0,0 +1,191 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryPositionsResponsePositionsInner(BaseModel): + """ + QueryPositionsResponsePositionsInner + """ # noqa: E501 + + position_id: Optional[StrictInt] = Field(default=None, alias="positionId") + vendor: Optional[StrictStr] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + collateral_symbol: Optional[StrictStr] = Field( + default=None, alias="collateralSymbol" + ) + topic_type: Optional[StrictStr] = Field(default=None, alias="topicType") + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + market_topic_title: Optional[StrictStr] = Field( + default=None, alias="marketTopicTitle" + ) + market_title: Optional[StrictStr] = Field(default=None, alias="marketTitle") + outcome_name: Optional[StrictStr] = Field(default=None, alias="outcomeName") + outcome_index: Optional[StrictInt] = Field(default=None, alias="outcomeIndex") + shares: Optional[StrictStr] = None + avg_price: Optional[StrictStr] = Field(default=None, alias="avgPrice") + total_cost: Optional[StrictStr] = Field(default=None, alias="totalCost") + value: Optional[StrictStr] = None + current_price: Optional[StrictStr] = Field(default=None, alias="currentPrice") + to_win: Optional[StrictStr] = Field(default=None, alias="toWin") + position_status: Optional[StrictStr] = Field(default=None, alias="positionStatus") + can_claim: Optional[StrictBool] = Field(default=None, alias="canClaim") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + unrealized_pnl: Optional[StrictStr] = Field(default=None, alias="unrealizedPnl") + unrealized_pnl_percent: Optional[StrictStr] = Field( + default=None, alias="unrealizedPnlPercent" + ) + realized_pnl: Optional[StrictStr] = Field(default=None, alias="realizedPnl") + pnl: Optional[StrictStr] = None + created_time: Optional[StrictInt] = Field(default=None, alias="createdTime") + updated_time: Optional[StrictInt] = Field(default=None, alias="updatedTime") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "positionId", + "vendor", + "chainId", + "tokenId", + "collateralSymbol", + "topicType", + "marketTopicId", + "marketId", + "marketTopicTitle", + "marketTitle", + "outcomeName", + "outcomeIndex", + "shares", + "avgPrice", + "totalCost", + "value", + "currentPrice", + "toWin", + "positionStatus", + "canClaim", + "endDate", + "unrealizedPnl", + "unrealizedPnlPercent", + "realizedPnl", + "pnl", + "createdTime", + "updatedTime", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPositionsResponsePositionsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPositionsResponsePositionsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "positionId": obj.get("positionId"), + "vendor": obj.get("vendor"), + "chainId": obj.get("chainId"), + "tokenId": obj.get("tokenId"), + "collateralSymbol": obj.get("collateralSymbol"), + "topicType": obj.get("topicType"), + "marketTopicId": obj.get("marketTopicId"), + "marketId": obj.get("marketId"), + "marketTopicTitle": obj.get("marketTopicTitle"), + "marketTitle": obj.get("marketTitle"), + "outcomeName": obj.get("outcomeName"), + "outcomeIndex": obj.get("outcomeIndex"), + "shares": obj.get("shares"), + "avgPrice": obj.get("avgPrice"), + "totalCost": obj.get("totalCost"), + "value": obj.get("value"), + "currentPrice": obj.get("currentPrice"), + "toWin": obj.get("toWin"), + "positionStatus": obj.get("positionStatus"), + "canClaim": obj.get("canClaim"), + "endDate": obj.get("endDate"), + "unrealizedPnl": obj.get("unrealizedPnl"), + "unrealizedPnlPercent": obj.get("unrealizedPnlPercent"), + "realizedPnl": obj.get("realizedPnl"), + "pnl": obj.get("pnl"), + "createdTime": obj.get("createdTime"), + "updatedTime": obj.get("updatedTime"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_summary.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_summary.py new file mode 100644 index 00000000..19b1f6d6 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_positions_response_summary.py @@ -0,0 +1,131 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryPositionsResponseSummary(BaseModel): + """ + QueryPositionsResponseSummary + """ # noqa: E501 + + total_value: Optional[StrictStr] = Field(default=None, alias="totalValue") + position_value: Optional[StrictStr] = Field(default=None, alias="positionValue") + wallet_balance: Optional[StrictStr] = Field(default=None, alias="walletBalance") + total_claimable_amount: Optional[StrictStr] = Field( + default=None, alias="totalClaimableAmount" + ) + today_realized_pnl: Optional[StrictStr] = Field( + default=None, alias="todayRealizedPnl" + ) + today_realized_pnl_percent: Optional[StrictStr] = Field( + default=None, alias="todayRealizedPnlPercent" + ) + today_total_cost: Optional[StrictStr] = Field(default=None, alias="todayTotalCost") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "totalValue", + "positionValue", + "walletBalance", + "totalClaimableAmount", + "todayRealizedPnl", + "todayRealizedPnlPercent", + "todayTotalCost", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryPositionsResponseSummary from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryPositionsResponseSummary from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "totalValue": obj.get("totalValue"), + "positionValue": obj.get("positionValue"), + "walletBalance": obj.get("walletBalance"), + "totalClaimableAmount": obj.get("totalClaimableAmount"), + "todayRealizedPnl": obj.get("todayRealizedPnl"), + "todayRealizedPnlPercent": obj.get("todayRealizedPnlPercent"), + "todayTotalCost": obj.get("todayTotalCost"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_settled_position_history_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_settled_position_history_response.py new file mode 100644 index 00000000..c4df3724 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_settled_position_history_response.py @@ -0,0 +1,126 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_settled_position_history_response_positions_inner import ( + QuerySettledPositionHistoryResponsePositionsInner, +) +from typing import Set +from typing_extensions import Self + + +class QuerySettledPositionHistoryResponse(BaseModel): + """ + QuerySettledPositionHistoryResponse + """ # noqa: E501 + + total_count: Optional[StrictInt] = Field(default=None, alias="totalCount") + positions: Optional[List[QuerySettledPositionHistoryResponsePositionsInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["totalCount", "positions"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QuerySettledPositionHistoryResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in positions (list) + _items = [] + if self.positions: + for _item_positions in self.positions: + if _item_positions: + _items.append(_item_positions.to_dict()) + _dict["positions"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QuerySettledPositionHistoryResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "totalCount": obj.get("totalCount"), + "positions": ( + [ + QuerySettledPositionHistoryResponsePositionsInner.from_dict( + _item + ) + for _item in obj["positions"] + ] + if obj.get("positions") is not None + else None + ), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_settled_position_history_response_positions_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_settled_position_history_response_positions_inner.py new file mode 100644 index 00000000..cfee334f --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_settled_position_history_response_positions_inner.py @@ -0,0 +1,195 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QuerySettledPositionHistoryResponsePositionsInner(BaseModel): + """ + QuerySettledPositionHistoryResponsePositionsInner + """ # noqa: E501 + + position_id: Optional[StrictInt] = Field(default=None, alias="positionId") + vendor: Optional[StrictStr] = None + chain_id: Optional[StrictStr] = Field(default=None, alias="chainId") + token_id: Optional[StrictStr] = Field(default=None, alias="tokenId") + collateral_symbol: Optional[StrictStr] = Field( + default=None, alias="collateralSymbol" + ) + topic_type: Optional[StrictStr] = Field(default=None, alias="topicType") + market_topic_id: Optional[StrictInt] = Field(default=None, alias="marketTopicId") + market_id: Optional[StrictInt] = Field(default=None, alias="marketId") + market_topic_title: Optional[StrictStr] = Field( + default=None, alias="marketTopicTitle" + ) + market_title: Optional[StrictStr] = Field(default=None, alias="marketTitle") + outcome_name: Optional[StrictStr] = Field(default=None, alias="outcomeName") + outcome_index: Optional[StrictInt] = Field(default=None, alias="outcomeIndex") + shares: Optional[StrictStr] = None + avg_price: Optional[StrictStr] = Field(default=None, alias="avgPrice") + total_cost: Optional[StrictStr] = Field(default=None, alias="totalCost") + value: Optional[StrictStr] = None + current_price: Optional[StrictStr] = Field(default=None, alias="currentPrice") + to_win: Optional[StrictStr] = Field(default=None, alias="toWin") + position_status: Optional[StrictStr] = Field(default=None, alias="positionStatus") + is_winner: Optional[StrictBool] = Field(default=None, alias="isWinner") + redeem_status: Optional[StrictStr] = Field(default=None, alias="redeemStatus") + end_date: Optional[StrictInt] = Field(default=None, alias="endDate") + final_outcome: Optional[StrictStr] = Field(default=None, alias="finalOutcome") + realized_pnl: Optional[StrictStr] = Field(default=None, alias="realizedPnl") + pnl: Optional[StrictStr] = None + claim_amount: Optional[StrictStr] = Field(default=None, alias="claimAmount") + settled_date: Optional[StrictInt] = Field(default=None, alias="settledDate") + created_time: Optional[StrictInt] = Field(default=None, alias="createdTime") + updated_time: Optional[StrictInt] = Field(default=None, alias="updatedTime") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "positionId", + "vendor", + "chainId", + "tokenId", + "collateralSymbol", + "topicType", + "marketTopicId", + "marketId", + "marketTopicTitle", + "marketTitle", + "outcomeName", + "outcomeIndex", + "shares", + "avgPrice", + "totalCost", + "value", + "currentPrice", + "toWin", + "positionStatus", + "isWinner", + "redeemStatus", + "endDate", + "finalOutcome", + "realizedPnl", + "pnl", + "claimAmount", + "settledDate", + "createdTime", + "updatedTime", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QuerySettledPositionHistoryResponsePositionsInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QuerySettledPositionHistoryResponsePositionsInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "positionId": obj.get("positionId"), + "vendor": obj.get("vendor"), + "chainId": obj.get("chainId"), + "tokenId": obj.get("tokenId"), + "collateralSymbol": obj.get("collateralSymbol"), + "topicType": obj.get("topicType"), + "marketTopicId": obj.get("marketTopicId"), + "marketId": obj.get("marketId"), + "marketTopicTitle": obj.get("marketTopicTitle"), + "marketTitle": obj.get("marketTitle"), + "outcomeName": obj.get("outcomeName"), + "outcomeIndex": obj.get("outcomeIndex"), + "shares": obj.get("shares"), + "avgPrice": obj.get("avgPrice"), + "totalCost": obj.get("totalCost"), + "value": obj.get("value"), + "currentPrice": obj.get("currentPrice"), + "toWin": obj.get("toWin"), + "positionStatus": obj.get("positionStatus"), + "isWinner": obj.get("isWinner"), + "redeemStatus": obj.get("redeemStatus"), + "endDate": obj.get("endDate"), + "finalOutcome": obj.get("finalOutcome"), + "realizedPnl": obj.get("realizedPnl"), + "pnl": obj.get("pnl"), + "claimAmount": obj.get("claimAmount"), + "settledDate": obj.get("settledDate"), + "createdTime": obj.get("createdTime"), + "updatedTime": obj.get("updatedTime"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_list_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_list_response.py new file mode 100644 index 00000000..d7af6703 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_list_response.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from binance_sdk_w3w_prediction.rest_api.models.query_transfer_list_response_transfers_inner import ( + QueryTransferListResponseTransfersInner, +) +from typing import Set +from typing_extensions import Self + + +class QueryTransferListResponse(BaseModel): + """ + QueryTransferListResponse + """ # noqa: E501 + + transfers: Optional[List[QueryTransferListResponseTransfersInner]] = None + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["transfers"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryTransferListResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in transfers (list) + _items = [] + if self.transfers: + for _item_transfers in self.transfers: + if _item_transfers: + _items.append(_item_transfers.to_dict()) + _dict["transfers"] = _items + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryTransferListResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "transfers": ( + [ + QueryTransferListResponseTransfersInner.from_dict(_item) + for _item in obj["transfers"] + ] + if obj.get("transfers") is not None + else None + ) + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_list_response_transfers_inner.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_list_response_transfers_inner.py new file mode 100644 index 00000000..963c11f9 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_list_response_transfers_inner.py @@ -0,0 +1,155 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryTransferListResponseTransfersInner(BaseModel): + """ + QueryTransferListResponseTransfersInner + """ # noqa: E501 + + transfer_id: Optional[StrictStr] = Field(default=None, alias="transferId") + direction: Optional[StrictStr] = None + status: Optional[StrictStr] = None + wallet_address: Optional[StrictStr] = Field(default=None, alias="walletAddress") + from_token: Optional[StrictStr] = Field(default=None, alias="fromToken") + from_token_amount: Optional[StrictStr] = Field( + default=None, alias="fromTokenAmount" + ) + to_token: Optional[StrictStr] = Field(default=None, alias="toToken") + to_token_amount: Optional[StrictStr] = Field(default=None, alias="toTokenAmount") + error_code: Optional[StrictStr] = Field(default=None, alias="errorCode") + error_message: Optional[StrictStr] = Field(default=None, alias="errorMessage") + create_time: Optional[StrictStr] = Field(default=None, alias="createTime") + update_time: Optional[StrictStr] = Field(default=None, alias="updateTime") + complete_at: Optional[StrictStr] = Field(default=None, alias="completeAt") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "transferId", + "direction", + "status", + "walletAddress", + "fromToken", + "fromTokenAmount", + "toToken", + "toTokenAmount", + "errorCode", + "errorMessage", + "createTime", + "updateTime", + "completeAt", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryTransferListResponseTransfersInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if error_code (nullable) is None + # and model_fields_set contains the field + if self.error_code is None and "error_code" in self.model_fields_set: + _dict["errorCode"] = None + + # set to None if error_message (nullable) is None + # and model_fields_set contains the field + if self.error_message is None and "error_message" in self.model_fields_set: + _dict["errorMessage"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryTransferListResponseTransfersInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "transferId": obj.get("transferId"), + "direction": obj.get("direction"), + "status": obj.get("status"), + "walletAddress": obj.get("walletAddress"), + "fromToken": obj.get("fromToken"), + "fromTokenAmount": obj.get("fromTokenAmount"), + "toToken": obj.get("toToken"), + "toTokenAmount": obj.get("toTokenAmount"), + "errorCode": obj.get("errorCode"), + "errorMessage": obj.get("errorMessage"), + "createTime": obj.get("createTime"), + "updateTime": obj.get("updateTime"), + "completeAt": obj.get("completeAt"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_status_response.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_status_response.py new file mode 100644 index 00000000..764e6ea8 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/models/query_transfer_status_response.py @@ -0,0 +1,149 @@ +# coding: utf-8 + +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Set +from typing_extensions import Self + + +class QueryTransferStatusResponse(BaseModel): + """ + QueryTransferStatusResponse + """ # noqa: E501 + + transfer_id: Optional[StrictStr] = Field(default=None, alias="transferId") + direction: Optional[StrictStr] = None + status: Optional[StrictStr] = None + from_token: Optional[StrictStr] = Field(default=None, alias="fromToken") + from_token_amount: Optional[StrictStr] = Field( + default=None, alias="fromTokenAmount" + ) + to_token: Optional[StrictStr] = Field(default=None, alias="toToken") + to_token_amount: Optional[StrictStr] = Field(default=None, alias="toTokenAmount") + error_code: Optional[StrictStr] = Field(default=None, alias="errorCode") + error_message: Optional[StrictStr] = Field(default=None, alias="errorMessage") + create_time: Optional[StrictStr] = Field(default=None, alias="createTime") + update_time: Optional[StrictStr] = Field(default=None, alias="updateTime") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = [ + "transferId", + "direction", + "status", + "fromToken", + "fromTokenAmount", + "toToken", + "toTokenAmount", + "errorCode", + "errorMessage", + "createTime", + "updateTime", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def is_array(cls) -> bool: + return False + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of QueryTransferStatusResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set( + [ + "additional_properties", + ] + ) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if error_code (nullable) is None + # and model_fields_set contains the field + if self.error_code is None and "error_code" in self.model_fields_set: + _dict["errorCode"] = None + + # set to None if error_message (nullable) is None + # and model_fields_set contains the field + if self.error_message is None and "error_message" in self.model_fields_set: + _dict["errorMessage"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of QueryTransferStatusResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "transferId": obj.get("transferId"), + "direction": obj.get("direction"), + "status": obj.get("status"), + "fromToken": obj.get("fromToken"), + "fromTokenAmount": obj.get("fromTokenAmount"), + "toToken": obj.get("toToken"), + "toTokenAmount": obj.get("toTokenAmount"), + "errorCode": obj.get("errorCode"), + "errorMessage": obj.get("errorMessage"), + "createTime": obj.get("createTime"), + "updateTime": obj.get("updateTime"), + } + ) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/rest_api.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/rest_api.py new file mode 100644 index 00000000..4e54bdfa --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/rest_api/rest_api.py @@ -0,0 +1,1153 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +import requests +from typing import Optional, List, TypeVar, Union +from binance_common.configuration import ConfigurationRestAPI +from binance_common.models import ApiResponse +from binance_common.signature import Signers +from binance_common.utils import send_request +from .api.market_data_api import MarketDataApi +from .api.position_api import PositionApi +from .api.redeem_api import RedeemApi +from .api.trade_api import TradeApi +from .api.transfer_api import TransferApi +from .api.wallet_api import WalletApi + +from .models import GetMarketDetailResponse +from .models import ListPredictionCategoriesResponse +from .models import ListPredictionMarketsResponse +from .models import MarketSearchResponse +from .models import QueryLastTradePriceResponse +from .models import QueryOrderBookResponse + + +from .models import ListPredictionMarketsSortByEnum +from .models import ListPredictionMarketsOrderByEnum +from .models import GetPositionByTokenResponse +from .models import QueryPnLResponse +from .models import QueryPositionsResponse +from .models import QueryPositionsByFilterResponse +from .models import QuerySettledPositionHistoryResponse + + +from .models import BatchRedeemResponse +from .models import GetRedeemStatusResponse + + +from .models import BatchCancelOrdersResponse +from .models import GetQuoteResponse +from .models import PlaceOrderResponse +from .models import QueryActiveOrdersResponse +from .models import QueryOrderHistoryResponse + + +from .models import BatchCancelOrdersCancelInfoListParameterInner + + +from .models import GetQuoteSideEnum +from .models import GetQuoteOrderTypeEnum +from .models import GetQuoteFundingSourceEnum +from .models import PlaceOrderAccountTypeEnum +from .models import PlaceOrderOrderTypeEnum +from .models import PlaceOrderFundingSourceEnum +from .models import QueryActiveOrdersTradeSideEnum +from .models import QueryOrderHistoryOrderTypeEnum +from .models import CreateInboundTransferResponse +from .models import CreateOutboundTransferResponse +from .models import QueryTransferListResponse +from .models import QueryTransferStatusResponse + + +from .models import CreateInboundTransferAccountTypeEnum +from .models import CreateOutboundTransferAccountTypeEnum +from .models import CreateOutboundTransferSourceBizEnum +from .models import QueryTransferListDirectionEnum +from .models import GetPortfolioResponse +from .models import GetQuotaStatusResponse +from .models import ListPredictionWalletsResponse +from .models import QueryPaymentOptionBalancesResponse + +T = TypeVar("T") + + +class W3wPredictionRestAPI: + def __init__( + self, + configuration: ConfigurationRestAPI, + ) -> None: + self.configuration = configuration + self._session = requests.Session() + self._signer = ( + Signers.get_signer( + configuration.private_key, configuration.private_key_passphrase + ) + if configuration.private_key is not None + else None + ) + + self._marketDataApi = MarketDataApi( + self.configuration, self._session, self._signer + ) + self._positionApi = PositionApi(self.configuration, self._session, self._signer) + self._redeemApi = RedeemApi(self.configuration, self._session, self._signer) + self._tradeApi = TradeApi(self.configuration, self._session, self._signer) + self._transferApi = TransferApi(self.configuration, self._session, self._signer) + self._walletApi = WalletApi(self.configuration, self._session, self._signer) + + def send_request( + self, + endpoint: str, + method: str, + query_params: Optional[dict] = None, + body_params: Optional[dict] = None, + ) -> ApiResponse[T]: + """ + Sends an request to the Binance REST API. + + Args: + endpoint (str): The API endpoint path to send the request to. + method (str): The HTTP method to use for the request (e.g. "GET", "POST", "PUT", "DELETE"). + query_params (Optional[dict]): The request payload as a dictionary, or None if no payload is required. + body_params (Optional[dict]): The request body as a dictionary, or None if no body is required. + + Returns: + ApiResponse[T]: The API response, where T is the expected response type. + """ + return send_request[T]( + self._session, + self.configuration, + method, + endpoint, + query_params, + body_params, + ) + + def send_signed_request( + self, + endpoint: str, + method: str, + query_params: Optional[dict] = None, + body_params: Optional[dict] = None, + ) -> ApiResponse[T]: + """ + Sends a signed request to the Binance REST API. + + Args: + endpoint (str): The API endpoint path to send the request to. + method (str): The HTTP method to use for the request (e.g. "GET", "POST", "PUT", "DELETE"). + query_params (Optional[dict]): The request payload as a dictionary, or None if no payload is required. + body_params (Optional[dict]): The request body as a dictionary, or None if no body is required. + + Returns: + ApiResponse[T]: The API response, where T is the expected response type. + """ + return send_request[T]( + self._session, + self.configuration, + method, + endpoint, + query_params, + body_params, + is_signed=True, + signer=self._signer, + ) + + def get_market_detail( + self, + market_topic_id: Union[int, None], + ) -> ApiResponse[GetMarketDetailResponse]: + """ + Get Market Detail + + Get full details for a specific prediction market topic, including variant data and timeline. + + Weight(IP): 200 + + Args: + market_topic_id (Union[int, None]): Market topic ID. Must be > 0 + + Returns: + ApiResponse[GetMarketDetailResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.get_market_detail(market_topic_id) + + def list_prediction_categories( + self, + ) -> ApiResponse[ListPredictionCategoriesResponse]: + """ + List Prediction Categories + + Get all available prediction market categories (L1 and L2). + + Weight(IP): 200 + + Args: + + Returns: + ApiResponse[ListPredictionCategoriesResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.list_prediction_categories() + + def list_prediction_markets( + self, + l1_category: Optional[str] = None, + l2_category: Optional[str] = None, + sort_by: Optional[ListPredictionMarketsSortByEnum] = None, + order_by: Optional[ListPredictionMarketsOrderByEnum] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + ) -> ApiResponse[ListPredictionMarketsResponse]: + """ + List Prediction Markets + + Get a paginated list of prediction market topics, with optional category and sort filters. + + Weight(IP): 200 + + Args: + l1_category (Optional[str] = None): Level-1 category filter + l2_category (Optional[str] = None): Level-2 category filter + sort_by (Optional[ListPredictionMarketsSortByEnum] = None): Sort field. Enum: `RECOMMENDED`, `VOLUME`, `PARTICIPANTS`, `CREATED_TIME`, `END_DATE` + order_by (Optional[ListPredictionMarketsOrderByEnum] = None): Sort direction. Enum: `ASC`, `DESC` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + + Returns: + ApiResponse[ListPredictionMarketsResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.list_prediction_markets( + l1_category, l2_category, sort_by, order_by, offset, limit + ) + + def market_search( + self, + query: Union[str, None], + top_k: Optional[int] = None, + ) -> ApiResponse[MarketSearchResponse]: + """ + Market Search + + Semantic search for prediction market topics by keyword. + + Weight(IP): 200 + + Args: + query (Union[str, None]): Search keyword. Not blank + top_k (Optional[int] = None): Max number of results to return. Default `20`, range 1–50 + + Returns: + ApiResponse[MarketSearchResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.market_search(query, top_k) + + def query_last_trade_price( + self, + market_id: Union[int, None], + ) -> ApiResponse[QueryLastTradePriceResponse]: + """ + Query Last Trade Price + + Get the most recent trade price for a prediction market. + + Weight(IP): 200 + + Args: + market_id (Union[int, None]): Market ID. Must be > 0 + + Returns: + ApiResponse[QueryLastTradePriceResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.query_last_trade_price(market_id) + + def query_order_book( + self, + vendor: Union[str, None], + market_id: Union[int, None], + token_id: Union[str, None], + ) -> ApiResponse[QueryOrderBookResponse]: + """ + Query Order Book + + Get the current order book (bids and asks) for a specific prediction market outcome token. + + Weight(IP): 200 + + Args: + vendor (Union[str, None]): Vendor identifier (e.g. `predict_fun`) + market_id (Union[int, None]): Market ID. Must be > 0 + token_id (Union[str, None]): Prediction outcome token ID + + Returns: + ApiResponse[QueryOrderBookResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._marketDataApi.query_order_book(vendor, market_id, token_id) + + def get_position_by_token( + self, + wallet_address: Union[str, None], + token_id: Union[str, None], + recv_window: Optional[int] = None, + ) -> ApiResponse[GetPositionByTokenResponse]: + """ + Get Position by Token + + Get the authenticated user's position detail for a specific prediction token. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Union[str, None]): Prediction outcome token ID + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetPositionByTokenResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._positionApi.get_position_by_token( + wallet_address, token_id, recv_window + ) + + def query_pn_l( + self, + wallet_address: Union[str, None], + token_id: Optional[str] = None, + market_id: Optional[int] = None, + market_topic_id: Optional[int] = None, + active_only: Optional[bool] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPnLResponse]: + """ + Query PnL + + Query profit and loss records for the authenticated user's prediction positions. When `tokenId` is provided, returns a single record in `pnl`; otherwise returns a list in `pnlList`. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Optional[str] = None): Filter by prediction token ID + market_id (Optional[int] = None): Filter by market ID. Must be > 0 + market_topic_id (Optional[int] = None): Filter by market topic ID. Must be > 0 + active_only (Optional[bool] = None): If `true`, return only active (unresolved) positions + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPnLResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._positionApi.query_pn_l( + wallet_address, + token_id, + market_id, + market_topic_id, + active_only, + recv_window, + ) + + def query_positions( + self, + wallet_address: Union[str, None], + tab: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPositionsResponse]: + """ + Query Positions + + Get the authenticated user's prediction token positions with portfolio summary and tab-based filtering. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + tab (Optional[str] = None): Position status tab. Values from `PositionQueryType`. Default `ONGOING` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPositionsResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._positionApi.query_positions( + wallet_address, tab, offset, limit, recv_window + ) + + def query_positions_by_filter( + self, + wallet_address: Optional[str] = None, + market_topic_id: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPositionsByFilterResponse]: + """ + Query Positions by Filter + + Get prediction positions filtered by wallet address and/or market topic ID. Both parameters are optional. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Optional[str] = None): User's prediction wallet address + market_topic_id (Optional[int] = None): Filter by market topic ID + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPositionsByFilterResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._positionApi.query_positions_by_filter( + wallet_address, market_topic_id, recv_window + ) + + def query_settled_position_history( + self, + wallet_address: Union[str, None], + l1_category: Optional[str] = None, + result: Optional[int] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QuerySettledPositionHistoryResponse]: + """ + Query Settled Position History + + Get the authenticated user's settled (resolved) prediction position history with optional filters. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + l1_category (Optional[str] = None): Filter by level-1 category + result (Optional[int] = None): Settlement result filter + start_date (Optional[str] = None): Start date. Format: `yyyy-MM-dd`. Must be ≤ `endDate` + end_date (Optional[str] = None): End date. Format: `yyyy-MM-dd`. Must be ≥ `startDate` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QuerySettledPositionHistoryResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._positionApi.query_settled_position_history( + wallet_address, + l1_category, + result, + start_date, + end_date, + offset, + limit, + recv_window, + ) + + def batch_redeem( + self, + wallet_address: Union[str, None], + wallet_id: Union[str, None], + token_ids: Union[List[str], None], + chain_id: Optional[str] = None, + ) -> ApiResponse[BatchRedeemResponse]: + """ + Batch Redeem + + Redeem one or more settled prediction tokens on-chain to claim winnings. Requires SAS authorization. + + Weight(IP): 200 + + Security Type: TRADE + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + wallet_id (Union[str, None]): Wallet ID + token_ids (Union[List[str], None]): List of prediction token IDs to redeem. Not empty. Example: `tokenIds=112233&tokenIds=112234` + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + + Returns: + ApiResponse[BatchRedeemResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._redeemApi.batch_redeem( + wallet_address, wallet_id, token_ids, chain_id + ) + + def get_redeem_status( + self, + wallet_address: Union[str, None], + tx_hash: Union[str, None], + recv_window: Optional[int] = None, + ) -> ApiResponse[GetRedeemStatusResponse]: + """ + Get Redeem Status + + Query the on-chain transaction status of a previously submitted redeem request. + + Weight(IP): 200 + + Security Type: USER_DATA + + Response Notes: + - Status values: + + | Value | Description | + | ----------- | -------------------------------------------- | + | `PENDING` | Transaction submitted, awaiting confirmation | + | `CONFIRMED` | Transaction confirmed on-chain | + | `FAILED` | Transaction failed | + | `NOT_FOUND` | Transaction hash not found | + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + tx_hash (Union[str, None]): Redeem transaction hash + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetRedeemStatusResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._redeemApi.get_redeem_status(wallet_address, tx_hash, recv_window) + + def batch_cancel_orders( + self, + wallet_address: Union[str, None], + wallet_id: Union[str, None], + cancel_info_list: Optional[ + List[BatchCancelOrdersCancelInfoListParameterInner] + ] = None, + ) -> ApiResponse[BatchCancelOrdersResponse]: + """ + Batch Cancel Orders + + Cancel one or more active prediction orders in a single request. Requires SAS authorization. + + **Known Issue — Bracket Encoding Incompatibility:** + This endpoint uses indexed bracket notation (`cancelInfoList[0].orderId`). Binance SAPI signature verification runs over the **raw, unencoded** canonical string. However, mainstream HTTP libraries (Python `requests`, Java `HttpURLConnection`/`URI`, Go `net/url`, Node.js `url`) automatically percent-encode `[` → `%5B` and `]` → `%5D`, producing a signature mismatch with error `-1022 Signature for this request is not valid`. Postman is unaffected because it does not encode keys. + + **Workarounds** (use low-level HTTP APIs that do not normalize URLs): + - **Python:** use `http.client` (stdlib) and hand-build the body string. + - **Java:** use `HttpURLConnection` and write the raw body bytes directly. + - **Go:** use `strings.NewReader` with a hand-built body instead of `url.Values.Encode()`. + + Weight(IP): 200 + + Security Type: TRADE + + Notes: + - Use dot notation for nested list fields: `cancelInfoList[0].orderId`, `cancelInfoList[1].orderId`, etc. + - `vendor` does not need to be supplied. The server automatically sets the correct vendor (`predict_fun`) for every item in the batch. + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + wallet_id (Union[str, None]): Wallet ID + cancel_info_list (Optional[List[BatchCancelOrdersCancelInfoListParameterInner]] = None): List of orders to cancel (index `i` starts from 0) + + Returns: + ApiResponse[BatchCancelOrdersResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._tradeApi.batch_cancel_orders( + wallet_address, wallet_id, cancel_info_list + ) + + def get_quote( + self, + wallet_address: Union[str, None], + token_id: Union[str, None], + side: Union[GetQuoteSideEnum, None], + amount_in: Union[str, None], + order_type: Union[GetQuoteOrderTypeEnum, None], + slippage_bps: Union[int, None], + price_limit: Optional[str] = None, + chain_id: Optional[str] = None, + fee_rate_bps: Optional[int] = None, + funding_source: Optional[GetQuoteFundingSourceEnum] = None, + fund_transfer_amount: Optional[str] = None, + ) -> ApiResponse[GetQuoteResponse]: + """ + Get Quote + + Get a price quote for a prediction order. The returned `quoteId` must be used in the subsequent Place Order request. + + Weight(IP): 200 + + Security Type: TRADE + + Response Notes: + - `feeAmount` is a string because it is denominated in wei (18 decimals) and may exceed JavaScript's safe integer range. `feeDiscountBps` is also a string to allow fractional basis-point values in the future. `feeRateBps` and `slippageBps` are integers and will never exceed safe integer bounds. + - **MARKET order minimum amount:** For `MARKET` orders, `amountIn` must be at least approximately **1.5 USDT** (in wei: `1500000000000000000`). The exact minimum varies by market liquidity. If the amount is too small, the server returns `-9000 Your order amount is too small`. This limit does **not** apply to `LIMIT` orders. + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Union[str, None]): Prediction outcome token ID + side (Union[GetQuoteSideEnum, None]): Trade direction. Enum: `BUY`, `SELL` + amount_in (Union[str, None]): Input amount in wei (18 decimals). Must be > 0. For `MARKET` orders, minimum is approximately 1.5 USDT (varies by market depth). Example: `1000000000000000000` = 1 USDT + order_type (Union[GetQuoteOrderTypeEnum, None]): Order type. Enum: `MARKET`, `LIMIT` + slippage_bps (Union[int, None]): Slippage tolerance in basis points. Range 1–10000 + price_limit (Optional[str] = None): Limit price. Required when `orderType=LIMIT`. Must be > 0 + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + fee_rate_bps (Optional[int] = None): Fee rate in basis points. Default `200`, range 1–10000 + funding_source (Optional[GetQuoteFundingSourceEnum] = None): Funding source. Enum: `MPC`, `CEX`. Default `MPC` + fund_transfer_amount (Optional[str] = None): Auto-transfer amount before order (wei). Must be > 0 if provided + + Returns: + ApiResponse[GetQuoteResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._tradeApi.get_quote( + wallet_address, + token_id, + side, + amount_in, + order_type, + slippage_bps, + price_limit, + chain_id, + fee_rate_bps, + funding_source, + fund_transfer_amount, + ) + + def place_order( + self, + wallet_address: Union[str, None], + wallet_id: Union[str, None], + quote_id: Union[str, None], + time_in_force: Union[str, None], + account_type: Union[PlaceOrderAccountTypeEnum, None], + order_type: Union[PlaceOrderOrderTypeEnum, None], + slippage_bps: Union[int, None], + price_limit: Optional[str] = None, + funding_source: Optional[PlaceOrderFundingSourceEnum] = None, + fund_transfer_amount: Optional[str] = None, + ) -> ApiResponse[PlaceOrderResponse]: + """ + Place Order + + Place a prediction order using a previously obtained quote. Requires SAS authorization. + + Weight(IP): 200 + + Security Type: TRADE + + Notes: + - Validation rules: + + | orderType | timeInForce | priceLimit | + | --------- | ------------- | --------------------- | + | `MARKET` | Must be `FOK` | Not required | + | `LIMIT` | Must be `GTC` | Required, must be > 0 | + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + wallet_id (Union[str, None]): Wallet ID + quote_id (Union[str, None]): Quote ID obtained from `Get Quote` + time_in_force (Union[str, None]): Must match `orderType`: `FOK` for `MARKET`, `GTC` for `LIMIT` + account_type (Union[PlaceOrderAccountTypeEnum, None]): Payment account type. Enum: `SPOT`, `FUNDING` + order_type (Union[PlaceOrderOrderTypeEnum, None]): Order type. Enum: `MARKET`, `LIMIT` + slippage_bps (Union[int, None]): Slippage tolerance in basis points. Range 1–10000 + price_limit (Optional[str] = None): Limit price. Required when `orderType=LIMIT`. Must be > 0 + funding_source (Optional[PlaceOrderFundingSourceEnum] = None): Funding source. Enum: `MPC`, `CEX`. Default `MPC` + fund_transfer_amount (Optional[str] = None): Auto-transfer amount before order (wei). Must be > 0 if provided + + Returns: + ApiResponse[PlaceOrderResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._tradeApi.place_order( + wallet_address, + wallet_id, + quote_id, + time_in_force, + account_type, + order_type, + slippage_bps, + price_limit, + funding_source, + fund_transfer_amount, + ) + + def query_active_orders( + self, + wallet_address: Union[str, None], + trade_side: Optional[QueryActiveOrdersTradeSideEnum] = None, + l1_category: Optional[str] = None, + market_id: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryActiveOrdersResponse]: + """ + Query Active Orders + + Get active (open) prediction orders for the authenticated user. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + trade_side (Optional[QueryActiveOrdersTradeSideEnum] = None): Filter by trade side. Enum: `BUY`, `SELL` + l1_category (Optional[str] = None): Filter by level-1 category + market_id (Optional[int] = None): Filter by market ID + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryActiveOrdersResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._tradeApi.query_active_orders( + wallet_address, + trade_side, + l1_category, + market_id, + offset, + limit, + recv_window, + ) + + def query_order_history( + self, + wallet_address: Union[str, None], + l1_category: Optional[str] = None, + order_type: Optional[QueryOrderHistoryOrderTypeEnum] = None, + status: Optional[str] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryOrderHistoryResponse]: + """ + Query Order History + + Get historical prediction orders (all statuses) for the authenticated user, with optional filters. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + l1_category (Optional[str] = None): Filter by level-1 category + order_type (Optional[QueryOrderHistoryOrderTypeEnum] = None): Filter by order type. Enum: `MARKET`, `LIMIT` + status (Optional[str] = None): Filter by order status + start_date (Optional[str] = None): Start date. Format: `yyyy-MM-dd`. Must be ≤ `endDate` + end_date (Optional[str] = None): End date. Format: `yyyy-MM-dd`. Must be ≥ `startDate` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryOrderHistoryResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._tradeApi.query_order_history( + wallet_address, + l1_category, + order_type, + status, + start_date, + end_date, + offset, + limit, + recv_window, + ) + + def create_inbound_transfer( + self, + wallet_id: Union[str, None], + wallet_address: Union[str, None], + from_token_amount: Union[str, None], + account_type: Union[CreateInboundTransferAccountTypeEnum, None], + from_token: Optional[str] = None, + to_token: Optional[str] = None, + chain_id: Optional[str] = None, + ) -> ApiResponse[CreateInboundTransferResponse]: + """ + Create Inbound Transfer + + Transfer funds from the prediction wallet back to the user's CEX account (SPOT or FUNDING). Requires SAS authorization. + + ⚠️ **SAS Authorization Required:** This endpoint enforces SAS (Self-Authorization Service) authorization. If SAS is not enabled for the wallet, the request will be rejected with `-31003 SAS authorization required`. Enable SAS for your wallet before calling this endpoint. + + Weight(IP): 200 + + Security Type: TRADE + + Args: + wallet_id (Union[str, None]): Wallet ID + wallet_address (Union[str, None]): User's prediction wallet address + from_token_amount (Union[str, None]): Transfer amount in wei (18 decimals). Must be > 0. Example: `1000000000000000000` = 1 USDT + account_type (Union[CreateInboundTransferAccountTypeEnum, None]): Destination CEX account. Enum: `SPOT`, `FUNDING` + from_token (Optional[str] = None): Source token symbol. Default `USDT` + to_token (Optional[str] = None): Destination token symbol. Default `USDT` + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + + Returns: + ApiResponse[CreateInboundTransferResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._transferApi.create_inbound_transfer( + wallet_id, + wallet_address, + from_token_amount, + account_type, + from_token, + to_token, + chain_id, + ) + + def create_outbound_transfer( + self, + wallet_id: Union[str, None], + wallet_address: Union[str, None], + from_token_amount: Union[str, None], + account_type: Union[CreateOutboundTransferAccountTypeEnum, None], + source_biz: Union[CreateOutboundTransferSourceBizEnum, None], + from_token: Optional[str] = None, + to_token: Optional[str] = None, + chain_id: Optional[str] = None, + ) -> ApiResponse[CreateOutboundTransferResponse]: + """ + Create Outbound Transfer + + Transfer funds from the user's CEX account (SPOT or FUNDING) into the prediction wallet. Requires SAS authorization. + + Weight(IP): 200 + + Security Type: TRADE + + Args: + wallet_id (Union[str, None]): Wallet ID + wallet_address (Union[str, None]): User's prediction wallet address + from_token_amount (Union[str, None]): Transfer amount in wei (18 decimals). Must be > 0. Example: `1000000000000000000` = 1 USDT + account_type (Union[CreateOutboundTransferAccountTypeEnum, None]): Source CEX account. Enum: `SPOT`, `FUNDING` + source_biz (Union[CreateOutboundTransferSourceBizEnum, None]): Business source. Enum: `USER_TRANSFER`, `PREDICTION_BUY` + from_token (Optional[str] = None): Source token symbol. Default `USDT` + to_token (Optional[str] = None): Destination token symbol. Default `USDT` + chain_id (Optional[str] = None): Chain ID. Default `56` (BSC) + + Returns: + ApiResponse[CreateOutboundTransferResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._transferApi.create_outbound_transfer( + wallet_id, + wallet_address, + from_token_amount, + account_type, + source_biz, + from_token, + to_token, + chain_id, + ) + + def query_transfer_list( + self, + wallet_address: Union[str, None], + start_date: Union[str, None], + end_date: Union[str, None], + token_symbol: Optional[str] = None, + direction: Optional[QueryTransferListDirectionEnum] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryTransferListResponse]: + """ + Query Transfer List + + Get the authenticated user's prediction wallet transfer history within a date range. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + start_date (Union[str, None]): Start date. Format: `yyyy-MM-dd`. Must be ≤ `endDate` + end_date (Union[str, None]): End date. Format: `yyyy-MM-dd`. Must be ≥ `startDate` + token_symbol (Optional[str] = None): Filter by token symbol (e.g. `USDT`) + direction (Optional[QueryTransferListDirectionEnum] = None): Filter by direction. Enum: `INBOUND`, `OUTBOUND` + offset (Optional[int] = None): Pagination offset. Default `0` + limit (Optional[int] = None): Page size. Default `20`, range 1–100 + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryTransferListResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._transferApi.query_transfer_list( + wallet_address, + start_date, + end_date, + token_symbol, + direction, + offset, + limit, + recv_window, + ) + + def query_transfer_status( + self, + transfer_id: Union[str, None], + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryTransferStatusResponse]: + """ + Query Transfer Status + + Query the current status of a prediction wallet transfer by transfer ID. + + **`status` values:** Terminal states are `COMPLETED` and `FAILED`. Intermediate states are `PROCESSING` and `PENDING`. **Do not** poll for `SUCCESS` — it is not a valid terminal state. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + transfer_id (Union[str, None]): Transfer ID returned from outbound/inbound transfer + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryTransferStatusResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._transferApi.query_transfer_status(transfer_id, recv_window) + + def get_portfolio( + self, + wallet_address: Union[str, None], + token_id: Optional[str] = None, + market_id: Optional[int] = None, + market_topic_id: Optional[int] = None, + active_only: Optional[bool] = None, + recv_window: Optional[int] = None, + ) -> ApiResponse[GetPortfolioResponse]: + """ + Get Portfolio + + Get the authenticated user's prediction portfolio overview including active positions count, aggregated PnL, and full position list. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + wallet_address (Union[str, None]): User's prediction wallet address + token_id (Optional[str] = None): Filter by prediction token ID + market_id (Optional[int] = None): Filter by market ID. Must be > 0 + market_topic_id (Optional[int] = None): Filter by market topic ID. Must be > 0 + active_only (Optional[bool] = None): If `true`, return only active (unresolved) positions + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetPortfolioResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._walletApi.get_portfolio( + wallet_address, + token_id, + market_id, + market_topic_id, + active_only, + recv_window, + ) + + def get_quota_status( + self, + recv_window: Optional[int] = None, + ) -> ApiResponse[GetQuotaStatusResponse]: + """ + Get Quota Status + + Query the current user's daily trading quota limit and remaining allowance for prediction markets. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[GetQuotaStatusResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._walletApi.get_quota_status(recv_window) + + def list_prediction_wallets( + self, + recv_window: Optional[int] = None, + ) -> ApiResponse[ListPredictionWalletsResponse]: + """ + List Prediction Wallets + + Get all prediction wallets registered for the authenticated user. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[ListPredictionWalletsResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._walletApi.list_prediction_wallets(recv_window) + + def query_payment_option_balances( + self, + recv_window: Optional[int] = None, + ) -> ApiResponse[QueryPaymentOptionBalancesResponse]: + """ + Query Payment Option Balances + + Get available balances for each payment option that can be used for prediction trading. + + Weight(IP): 200 + + Security Type: USER_DATA + + Args: + recv_window (Optional[int] = None): Request validity window in milliseconds + + Returns: + ApiResponse[QueryPaymentOptionBalancesResponse] + + Raises: + RequiredError: If a required parameter is missing. + + """ + + return self._walletApi.query_payment_option_balances(recv_window) diff --git a/clients/w3w_prediction/src/binance_sdk_w3w_prediction/w3w_prediction.py b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/w3w_prediction.py new file mode 100644 index 00000000..50b2e118 --- /dev/null +++ b/clients/w3w_prediction/src/binance_sdk_w3w_prediction/w3w_prediction.py @@ -0,0 +1,34 @@ +import platform +from importlib.metadata import version + +from binance_common.configuration import ConfigurationRestAPI +from binance_common.constants import W3W_PREDICTION_REST_API_PROD_URL +from . import metadata +from .rest_api import W3wPredictionRestAPI + +LIB_NAME = metadata.NAME +LIB_VERSION = version(LIB_NAME) + + +class W3wPrediction: + """W3wPrediction API that exposes REST APIs in a single interface.""" + + def __init__(self, config_rest_api: ConfigurationRestAPI = None) -> None: + self._rest_api = None + self._rest_api_config = ( + ConfigurationRestAPI() if config_rest_api is None else config_rest_api + ) + + @property + def rest_api(self) -> W3wPredictionRestAPI: + if self._rest_api is None and self._rest_api_config: + self._rest_api_config.base_headers["User-Agent"] = ( + f"{LIB_NAME}/{LIB_VERSION} (Python/{platform.python_version()}; {platform.system()}; {platform.machine()})" + ) + self._rest_api_config.base_path = ( + W3W_PREDICTION_REST_API_PROD_URL + if self._rest_api_config.base_path is None + else self._rest_api_config.base_path + ) + self._rest_api = W3wPredictionRestAPI(self._rest_api_config) + return self._rest_api diff --git a/clients/w3w_prediction/tests/unit/rest_api/test_market_data_api.py b/clients/w3w_prediction/tests/unit/rest_api/test_market_data_api.py new file mode 100644 index 00000000..0c37989a --- /dev/null +++ b/clients/w3w_prediction/tests/unit/rest_api/test_market_data_api.py @@ -0,0 +1,916 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +import json +import pytest +import requests + +from unittest.mock import MagicMock, patch +from urllib.parse import parse_qs + +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel + +from binance_sdk_w3w_prediction.rest_api.api import MarketDataApi +from binance_sdk_w3w_prediction.rest_api.models import GetMarketDetailResponse +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionCategoriesResponse +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionMarketsResponse +from binance_sdk_w3w_prediction.rest_api.models import MarketSearchResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryLastTradePriceResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryOrderBookResponse + + +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionMarketsSortByEnum +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionMarketsOrderByEnum + + +class TestMarketDataApi: + @pytest.fixture(autouse=True) + def setup_client(self): + """Setup a client instance with mocked session before each test method.""" + self.mock_session = MagicMock(spec=requests.Session) + config = ConfigurationRestAPI( + api_key="test-api-key", + api_secret="test-api-secret", + ) + self.client = MarketDataApi(configuration=config, session=self.mock_session) + + def set_mock_response(self, data: dict = {}, status_code=200, headers=None): + """Helper method to setup mock response for the client's session request.""" + if headers is None: + headers = {} + + mock_response = MagicMock() + mock_response.status_code = status_code + mock_response.json.return_value = data + mock_response.text = json.dumps(data) + mock_response.headers = headers + + self.mock_session.request.return_value = mock_response + + @patch("binance_common.utils.get_signature") + def test_get_market_detail_success(self, mock_get_signature): + """Test get_market_detail() successfully with required parameters only.""" + + params = {"market_topic_id": 4229564} + + expected_response = { + "marketTopicId": 4229564, + "vendor": "PREDICT_FUN", + "chainId": "56", + "slug": "btc-price-1h-up-or-down", + "title": "BTC Price 1h Up or Down?", + "question": "Will BTC price go UP in the next 1 hour?", + "description": "Resolves YES if BTC spot price is higher than the starting price at resolution time.", + "imageUrl": "https://cdn.example.com/prediction/btc-1h.png", + "topicType": "FLAT", + "chartType": "CRYPTO_UP_DOWN", + "symbol": "BTCUSDT", + "variantData": { + "type": "CRYPTO_UP_DOWN", + "startPrice": "67890.12", + "endPrice": "endPrice", + "priceFeedId": "0xpricefeedid123", + "priceFeedProvider": "BINANCE", + "priceFeedSymbol": "BTCUSDT", + }, + "participantCount": 3420, + "collateral": "USDT", + "feeRateBps": 200, + "slippageBps": 1200, + "isYieldBearing": False, + "tradeVolume": "158234.56", + "liquidity": "45000.00", + "publishedAt": 1748100000000, + "startDate": 1748131200000, + "endDate": 1748134800000, + "status": "REGISTERED", + "timeline": [ + { + "marketTopicId": 4229560, + "startDate": 1748127600000, + "endDate": 1748131200000, + } + ], + "markets": [ + { + "marketId": 5567895, + "externalId": "ext_001", + "title": "UP", + "question": "Will BTC go UP?", + "description": "Resolves YES if BTC price increases.", + "conditionId": "0xabc123", + "status": "REGISTERED", + "tradingStatus": "OPEN", + "tradeVolume": "90000.00", + "liquidity": "25000.00", + "decimalPrecision": 2, + "outcomes": [ + { + "name": "YES", + "price": "0.52", + "chance": "0.52", + "index": 0, + "tokenId": "112233", + } + ], + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_market_detail(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/market/detail" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert normalized["marketTopicId"] == 4229564 + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetMarketDetailResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetMarketDetailResponse, "from_dict"): + expected = GetMarketDetailResponse.from_dict(expected_response) + else: + expected = GetMarketDetailResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_get_market_detail_success_with_optional_params(self, mock_get_signature): + """Test get_market_detail() successfully with optional parameters.""" + + params = {"market_topic_id": 4229564} + + expected_response = { + "marketTopicId": 4229564, + "vendor": "PREDICT_FUN", + "chainId": "56", + "slug": "btc-price-1h-up-or-down", + "title": "BTC Price 1h Up or Down?", + "question": "Will BTC price go UP in the next 1 hour?", + "description": "Resolves YES if BTC spot price is higher than the starting price at resolution time.", + "imageUrl": "https://cdn.example.com/prediction/btc-1h.png", + "topicType": "FLAT", + "chartType": "CRYPTO_UP_DOWN", + "symbol": "BTCUSDT", + "variantData": { + "type": "CRYPTO_UP_DOWN", + "startPrice": "67890.12", + "endPrice": "endPrice", + "priceFeedId": "0xpricefeedid123", + "priceFeedProvider": "BINANCE", + "priceFeedSymbol": "BTCUSDT", + }, + "participantCount": 3420, + "collateral": "USDT", + "feeRateBps": 200, + "slippageBps": 1200, + "isYieldBearing": False, + "tradeVolume": "158234.56", + "liquidity": "45000.00", + "publishedAt": 1748100000000, + "startDate": 1748131200000, + "endDate": 1748134800000, + "status": "REGISTERED", + "timeline": [ + { + "marketTopicId": 4229560, + "startDate": 1748127600000, + "endDate": 1748131200000, + } + ], + "markets": [ + { + "marketId": 5567895, + "externalId": "ext_001", + "title": "UP", + "question": "Will BTC go UP?", + "description": "Resolves YES if BTC price increases.", + "conditionId": "0xabc123", + "status": "REGISTERED", + "tradingStatus": "OPEN", + "tradeVolume": "90000.00", + "liquidity": "25000.00", + "decimalPrecision": 2, + "outcomes": [ + { + "name": "YES", + "price": "0.52", + "chance": "0.52", + "index": 0, + "tokenId": "112233", + } + ], + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_market_detail(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/market/detail" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetMarketDetailResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetMarketDetailResponse, "from_dict"): + expected = GetMarketDetailResponse.from_dict(expected_response) + else: + expected = GetMarketDetailResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_get_market_detail_missing_required_param_market_topic_id(self): + """Test that get_market_detail() raises RequiredError when 'market_topic_id' is missing.""" + params = {"market_topic_id": 4229564} + params["market_topic_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'market_topic_id'" + ): + self.client.get_market_detail(**params) + + def test_get_market_detail_server_error(self): + """Test that get_market_detail() raises an error when the server returns an error.""" + + params = {"market_topic_id": 4229564} + + mock_error = Exception("ResponseError") + self.client.get_market_detail = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.get_market_detail(**params) + + @patch("binance_common.utils.get_signature") + def test_list_prediction_categories_success(self, mock_get_signature): + """Test list_prediction_categories() successfully with required parameters only.""" + + expected_response = { + "categories": [ + { + "id": "crypto", + "name": "Crypto", + "icon": "crypto_icon", + "order": 1, + "subcategories": [ + { + "id": "up-down", + "name": "Up/Down", + "icon": "updown_icon", + "order": 1, + } + ], + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.list_prediction_categories() + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/category/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(ListPredictionCategoriesResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof + or is_list + or hasattr(ListPredictionCategoriesResponse, "from_dict") + ): + expected = ListPredictionCategoriesResponse.from_dict(expected_response) + else: + expected = ListPredictionCategoriesResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_list_prediction_categories_server_error(self): + """Test that list_prediction_categories() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.client.list_prediction_categories = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.list_prediction_categories() + + @patch("binance_common.utils.get_signature") + def test_list_prediction_markets_success(self, mock_get_signature): + """Test list_prediction_markets() successfully with required parameters only.""" + + expected_response = { + "marketTopics": [ + { + "marketTopicId": 4229564, + "vendor": "PREDICT_FUN", + "chainId": "56", + "slug": "btc-price-1h-up-or-down", + "title": "BTC Price 1h Up or Down?", + "question": "Will BTC price go UP in the next 1 hour?", + "description": "Resolves YES if BTC spot price is higher than the starting price at resolution time.", + "imageUrl": "https://cdn.example.com/prediction/btc-1h.png", + "topicType": "FLAT", + "chartType": "CRYPTO_UP_DOWN", + "symbol": "BTCUSDT", + "participantCount": 3420, + "collateral": "USDT", + "feeRateBps": 200, + "slippageBps": 1200, + "isYieldBearing": False, + "tradeVolume": "158234.56", + "liquidity": "45000.00", + "publishedAt": 1748100000000, + "startDate": 1748131200000, + "endDate": 1748134800000, + "status": "REGISTERED", + "markets": [{}], + } + ], + "total": 128, + "offset": 0, + "limit": 20, + "hasMore": True, + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.list_prediction_markets() + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/market/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(ListPredictionMarketsResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(ListPredictionMarketsResponse, "from_dict"): + expected = ListPredictionMarketsResponse.from_dict(expected_response) + else: + expected = ListPredictionMarketsResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_list_prediction_markets_success_with_optional_params( + self, mock_get_signature + ): + """Test list_prediction_markets() successfully with optional parameters.""" + + params = { + "l1_category": "crypto", + "l2_category": "up-down", + "sort_by": ListPredictionMarketsSortByEnum["RECOMMENDED"].value, + "order_by": ListPredictionMarketsOrderByEnum["ASC"].value, + "offset": 0, + "limit": 20, + } + + expected_response = { + "marketTopics": [ + { + "marketTopicId": 4229564, + "vendor": "PREDICT_FUN", + "chainId": "56", + "slug": "btc-price-1h-up-or-down", + "title": "BTC Price 1h Up or Down?", + "question": "Will BTC price go UP in the next 1 hour?", + "description": "Resolves YES if BTC spot price is higher than the starting price at resolution time.", + "imageUrl": "https://cdn.example.com/prediction/btc-1h.png", + "topicType": "FLAT", + "chartType": "CRYPTO_UP_DOWN", + "symbol": "BTCUSDT", + "participantCount": 3420, + "collateral": "USDT", + "feeRateBps": 200, + "slippageBps": 1200, + "isYieldBearing": False, + "tradeVolume": "158234.56", + "liquidity": "45000.00", + "publishedAt": 1748100000000, + "startDate": 1748131200000, + "endDate": 1748134800000, + "status": "REGISTERED", + "markets": [{}], + } + ], + "total": 128, + "offset": 0, + "limit": 20, + "hasMore": True, + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.list_prediction_markets(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/market/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(ListPredictionMarketsResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(ListPredictionMarketsResponse, "from_dict"): + expected = ListPredictionMarketsResponse.from_dict(expected_response) + else: + expected = ListPredictionMarketsResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_list_prediction_markets_server_error(self): + """Test that list_prediction_markets() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.client.list_prediction_markets = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.list_prediction_markets() + + @patch("binance_common.utils.get_signature") + def test_market_search_success(self, mock_get_signature): + """Test market_search() successfully with required parameters only.""" + + params = { + "query": "BTC price", + } + + expected_response = [ + { + "marketTopicId": 4229564, + "vendor": "PREDICT_FUN", + "chainId": "56", + "slug": "btc-price-1h-up-or-down", + "title": "BTC Price 1h Up or Down?", + "question": "Will BTC price go UP in the next 1 hour?", + "description": "Resolves YES if BTC spot price is higher than the starting price.", + "topicType": "FLAT", + "chartType": "CRYPTO_UP_DOWN", + "symbol": "BTCUSDT", + "participantCount": 3420, + "collateral": "USDT", + "tradeVolume": "158234.56", + "liquidity": "45000.00", + "startDate": 1748131200000, + "endDate": 1748134800000, + "status": "REGISTERED", + "markets": [{}], + } + ] + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.market_search(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/market/search" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert normalized["query"] == "BTC price" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(MarketSearchResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(MarketSearchResponse, "from_dict"): + expected = MarketSearchResponse.from_dict(expected_response) + else: + expected = MarketSearchResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_market_search_success_with_optional_params(self, mock_get_signature): + """Test market_search() successfully with optional parameters.""" + + params = {"query": "BTC price", "top_k": 20} + + expected_response = [ + { + "marketTopicId": 4229564, + "vendor": "PREDICT_FUN", + "chainId": "56", + "slug": "btc-price-1h-up-or-down", + "title": "BTC Price 1h Up or Down?", + "question": "Will BTC price go UP in the next 1 hour?", + "description": "Resolves YES if BTC spot price is higher than the starting price.", + "topicType": "FLAT", + "chartType": "CRYPTO_UP_DOWN", + "symbol": "BTCUSDT", + "participantCount": 3420, + "collateral": "USDT", + "tradeVolume": "158234.56", + "liquidity": "45000.00", + "startDate": 1748131200000, + "endDate": 1748134800000, + "status": "REGISTERED", + "markets": [{}], + } + ] + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.market_search(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/market/search" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(MarketSearchResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(MarketSearchResponse, "from_dict"): + expected = MarketSearchResponse.from_dict(expected_response) + else: + expected = MarketSearchResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_market_search_missing_required_param_query(self): + """Test that market_search() raises RequiredError when 'query' is missing.""" + params = { + "query": "BTC price", + } + params["query"] = None + + with pytest.raises(RequiredError, match="Missing required parameter 'query'"): + self.client.market_search(**params) + + def test_market_search_server_error(self): + """Test that market_search() raises an error when the server returns an error.""" + + params = { + "query": "BTC price", + } + + mock_error = Exception("ResponseError") + self.client.market_search = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.market_search(**params) + + @patch("binance_common.utils.get_signature") + def test_query_last_trade_price_success(self, mock_get_signature): + """Test query_last_trade_price() successfully with required parameters only.""" + + params = {"market_id": 5567895} + + expected_response = {"marketId": 5567895, "lastTradePrice": "0.52"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_last_trade_price(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/order-book/last-trade-price" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + assert normalized["marketId"] == 5567895 + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryLastTradePriceResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryLastTradePriceResponse, "from_dict"): + expected = QueryLastTradePriceResponse.from_dict(expected_response) + else: + expected = QueryLastTradePriceResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_last_trade_price_success_with_optional_params( + self, mock_get_signature + ): + """Test query_last_trade_price() successfully with optional parameters.""" + + params = {"market_id": 5567895} + + expected_response = {"marketId": 5567895, "lastTradePrice": "0.52"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_last_trade_price(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/order-book/last-trade-price" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryLastTradePriceResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryLastTradePriceResponse, "from_dict"): + expected = QueryLastTradePriceResponse.from_dict(expected_response) + else: + expected = QueryLastTradePriceResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_last_trade_price_missing_required_param_market_id(self): + """Test that query_last_trade_price() raises RequiredError when 'market_id' is missing.""" + params = {"market_id": 5567895} + params["market_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'market_id'" + ): + self.client.query_last_trade_price(**params) + + def test_query_last_trade_price_server_error(self): + """Test that query_last_trade_price() raises an error when the server returns an error.""" + + params = {"market_id": 5567895} + + mock_error = Exception("ResponseError") + self.client.query_last_trade_price = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_last_trade_price(**params) + + @patch("binance_common.utils.get_signature") + def test_query_order_book_success(self, mock_get_signature): + """Test query_order_book() successfully with required parameters only.""" + + params = {"vendor": "predict_fun", "market_id": 5567895, "token_id": "112233"} + + expected_response = { + "outcome": "YES", + "tokenId": "112233", + "timestamp": 1748131800000, + "bids": [{"price": "0.51", "size": "5000.00"}], + "asks": [{"price": "0.52", "size": "3000.00"}], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_order_book(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/order-book" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert normalized["vendor"] == "predict_fun" + assert normalized["marketId"] == 5567895 + assert normalized["tokenId"] == "112233" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryOrderBookResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryOrderBookResponse, "from_dict"): + expected = QueryOrderBookResponse.from_dict(expected_response) + else: + expected = QueryOrderBookResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_order_book_success_with_optional_params(self, mock_get_signature): + """Test query_order_book() successfully with optional parameters.""" + + params = {"vendor": "predict_fun", "market_id": 5567895, "token_id": "112233"} + + expected_response = { + "outcome": "YES", + "tokenId": "112233", + "timestamp": 1748131800000, + "bids": [{"price": "0.51", "size": "5000.00"}], + "asks": [{"price": "0.52", "size": "3000.00"}], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_order_book(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/order-book" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryOrderBookResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryOrderBookResponse, "from_dict"): + expected = QueryOrderBookResponse.from_dict(expected_response) + else: + expected = QueryOrderBookResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_order_book_missing_required_param_vendor(self): + """Test that query_order_book() raises RequiredError when 'vendor' is missing.""" + params = {"vendor": "predict_fun", "market_id": 5567895, "token_id": "112233"} + params["vendor"] = None + + with pytest.raises(RequiredError, match="Missing required parameter 'vendor'"): + self.client.query_order_book(**params) + + def test_query_order_book_missing_required_param_market_id(self): + """Test that query_order_book() raises RequiredError when 'market_id' is missing.""" + params = {"vendor": "predict_fun", "market_id": 5567895, "token_id": "112233"} + params["market_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'market_id'" + ): + self.client.query_order_book(**params) + + def test_query_order_book_missing_required_param_token_id(self): + """Test that query_order_book() raises RequiredError when 'token_id' is missing.""" + params = {"vendor": "predict_fun", "market_id": 5567895, "token_id": "112233"} + params["token_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'token_id'" + ): + self.client.query_order_book(**params) + + def test_query_order_book_server_error(self): + """Test that query_order_book() raises an error when the server returns an error.""" + + params = {"vendor": "predict_fun", "market_id": 5567895, "token_id": "112233"} + + mock_error = Exception("ResponseError") + self.client.query_order_book = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_order_book(**params) diff --git a/clients/w3w_prediction/tests/unit/rest_api/test_position_api.py b/clients/w3w_prediction/tests/unit/rest_api/test_position_api.py new file mode 100644 index 00000000..3de291d1 --- /dev/null +++ b/clients/w3w_prediction/tests/unit/rest_api/test_position_api.py @@ -0,0 +1,982 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +import json +import pytest +import requests + +from unittest.mock import MagicMock, patch +from urllib.parse import parse_qs + +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel + +from binance_sdk_w3w_prediction.rest_api.api import PositionApi +from binance_sdk_w3w_prediction.rest_api.models import GetPositionByTokenResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryPnLResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryPositionsResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryPositionsByFilterResponse +from binance_sdk_w3w_prediction.rest_api.models import ( + QuerySettledPositionHistoryResponse, +) + + +class TestPositionApi: + @pytest.fixture(autouse=True) + def setup_client(self): + """Setup a client instance with mocked session before each test method.""" + self.mock_session = MagicMock(spec=requests.Session) + config = ConfigurationRestAPI( + api_key="test-api-key", + api_secret="test-api-secret", + ) + self.client = PositionApi(configuration=config, session=self.mock_session) + + def set_mock_response(self, data: dict = {}, status_code=200, headers=None): + """Helper method to setup mock response for the client's session request.""" + if headers is None: + headers = {} + + mock_response = MagicMock() + mock_response.status_code = status_code + mock_response.json.return_value = data + mock_response.text = json.dumps(data) + mock_response.headers = headers + + self.mock_session.request.return_value = mock_response + + @patch("binance_common.utils.get_signature") + def test_get_position_by_token_success(self, mock_get_signature): + """Test get_position_by_token() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + } + + expected_response = { + "position": { + "positionId": 1001, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112233", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229564, + "marketId": 5567895, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "1923.07", + "avgPrice": "0.52", + "totalCost": "1.00", + "value": "1.06", + "currentPrice": "0.55", + "positionStatus": "OPEN", + "endDate": 1748134800000, + "unrealizedPnl": "0.06", + "realizedPnl": "0.00", + "pnl": "0.06", + "createdTime": 1748131500000, + "updatedTime": 1748132000000, + } + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_position_by_token(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/position/token" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["tokenId"] == "112233" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetPositionByTokenResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetPositionByTokenResponse, "from_dict"): + expected = GetPositionByTokenResponse.from_dict(expected_response) + else: + expected = GetPositionByTokenResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_get_position_by_token_success_with_optional_params( + self, mock_get_signature + ): + """Test get_position_by_token() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "recv_window": 5000, + } + + expected_response = { + "position": { + "positionId": 1001, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112233", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229564, + "marketId": 5567895, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "1923.07", + "avgPrice": "0.52", + "totalCost": "1.00", + "value": "1.06", + "currentPrice": "0.55", + "positionStatus": "OPEN", + "endDate": 1748134800000, + "unrealizedPnl": "0.06", + "realizedPnl": "0.00", + "pnl": "0.06", + "createdTime": 1748131500000, + "updatedTime": 1748132000000, + } + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_position_by_token(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/position/token" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetPositionByTokenResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetPositionByTokenResponse, "from_dict"): + expected = GetPositionByTokenResponse.from_dict(expected_response) + else: + expected = GetPositionByTokenResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_get_position_by_token_missing_required_param_wallet_address(self): + """Test that get_position_by_token() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.get_position_by_token(**params) + + def test_get_position_by_token_missing_required_param_token_id(self): + """Test that get_position_by_token() raises RequiredError when 'token_id' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + } + params["token_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'token_id'" + ): + self.client.get_position_by_token(**params) + + def test_get_position_by_token_server_error(self): + """Test that get_position_by_token() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + } + + mock_error = Exception("ResponseError") + self.client.get_position_by_token = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.get_position_by_token(**params) + + @patch("binance_common.utils.get_signature") + def test_query_pn_l_success(self, mock_get_signature): + """Test query_pn_l() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + expected_response = { + "chainId": "56", + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "pnl": "pnl", + "pnlList": [ + { + "id": 10001, + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "marketTopicId": 4229564, + "marketId": 5567895, + "tokenId": "112233", + "vendor": "PREDICT_FUN", + "currentShares": "1923.07", + "avgPrice": "0.52", + "currentPrice": "0.55", + "realizedPnl": "0.00", + "unrealizedPnl": "0.06", + "totalPnl": "0.06", + "pnlPercentage": "6.00", + "isResolved": False, + } + ], + "totalCount": 1, + "totalRealizedPnl": "0.00", + "totalUnrealizedPnl": "0.06", + "totalPnl": "0.06", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_pn_l(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/pnl/query" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPnLResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryPnLResponse, "from_dict"): + expected = QueryPnLResponse.from_dict(expected_response) + else: + expected = QueryPnLResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_pn_l_success_with_optional_params(self, mock_get_signature): + """Test query_pn_l() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "market_id": 5567895, + "market_topic_id": 4229564, + "active_only": False, + "recv_window": 5000, + } + + expected_response = { + "chainId": "56", + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "pnl": "pnl", + "pnlList": [ + { + "id": 10001, + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "marketTopicId": 4229564, + "marketId": 5567895, + "tokenId": "112233", + "vendor": "PREDICT_FUN", + "currentShares": "1923.07", + "avgPrice": "0.52", + "currentPrice": "0.55", + "realizedPnl": "0.00", + "unrealizedPnl": "0.06", + "totalPnl": "0.06", + "pnlPercentage": "6.00", + "isResolved": False, + } + ], + "totalCount": 1, + "totalRealizedPnl": "0.00", + "totalUnrealizedPnl": "0.06", + "totalPnl": "0.06", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_pn_l(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/pnl/query" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPnLResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryPnLResponse, "from_dict"): + expected = QueryPnLResponse.from_dict(expected_response) + else: + expected = QueryPnLResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_pn_l_missing_required_param_wallet_address(self): + """Test that query_pn_l() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.query_pn_l(**params) + + def test_query_pn_l_server_error(self): + """Test that query_pn_l() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + mock_error = Exception("ResponseError") + self.client.query_pn_l = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_pn_l(**params) + + @patch("binance_common.utils.get_signature") + def test_query_positions_success(self, mock_get_signature): + """Test query_positions() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + expected_response = { + "summary": { + "totalValue": "1523.45", + "positionValue": "523.45", + "walletBalance": "1000.00", + "totalClaimableAmount": "50.00", + "todayRealizedPnl": "15.30", + "todayRealizedPnlPercent": "3.10", + "todayTotalCost": "493.55", + }, + "counts": {"ongoingCount": 3, "endedCount": 12, "pendingClaimCount": 1}, + "positions": [ + { + "positionId": 1001, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112233", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229564, + "marketId": 5567895, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "1923.07", + "avgPrice": "0.52", + "totalCost": "1.00", + "value": "1.06", + "currentPrice": "0.55", + "toWin": "1923.07", + "positionStatus": "OPEN", + "canClaim": False, + "endDate": 1748134800000, + "unrealizedPnl": "0.06", + "unrealizedPnlPercent": "6.00", + "realizedPnl": "0.00", + "pnl": "0.06", + "createdTime": 1748131500000, + "updatedTime": 1748132000000, + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_positions(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/position/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPositionsResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryPositionsResponse, "from_dict"): + expected = QueryPositionsResponse.from_dict(expected_response) + else: + expected = QueryPositionsResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_positions_success_with_optional_params(self, mock_get_signature): + """Test query_positions() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "tab": "ONGOING", + "offset": 0, + "limit": 20, + "recv_window": 5000, + } + + expected_response = { + "summary": { + "totalValue": "1523.45", + "positionValue": "523.45", + "walletBalance": "1000.00", + "totalClaimableAmount": "50.00", + "todayRealizedPnl": "15.30", + "todayRealizedPnlPercent": "3.10", + "todayTotalCost": "493.55", + }, + "counts": {"ongoingCount": 3, "endedCount": 12, "pendingClaimCount": 1}, + "positions": [ + { + "positionId": 1001, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112233", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229564, + "marketId": 5567895, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "1923.07", + "avgPrice": "0.52", + "totalCost": "1.00", + "value": "1.06", + "currentPrice": "0.55", + "toWin": "1923.07", + "positionStatus": "OPEN", + "canClaim": False, + "endDate": 1748134800000, + "unrealizedPnl": "0.06", + "unrealizedPnlPercent": "6.00", + "realizedPnl": "0.00", + "pnl": "0.06", + "createdTime": 1748131500000, + "updatedTime": 1748132000000, + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_positions(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/position/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPositionsResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryPositionsResponse, "from_dict"): + expected = QueryPositionsResponse.from_dict(expected_response) + else: + expected = QueryPositionsResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_positions_missing_required_param_wallet_address(self): + """Test that query_positions() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.query_positions(**params) + + def test_query_positions_server_error(self): + """Test that query_positions() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + mock_error = Exception("ResponseError") + self.client.query_positions = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_positions(**params) + + @patch("binance_common.utils.get_signature") + def test_query_positions_by_filter_success(self, mock_get_signature): + """Test query_positions_by_filter() successfully with required parameters only.""" + + expected_response = { + "positions": [ + { + "positionId": 1001, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112233", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229564, + "marketId": 5567895, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "1923.07", + "avgPrice": "0.52", + "totalCost": "1.00", + "value": "1.06", + "currentPrice": "0.55", + "positionStatus": "OPEN", + "endDate": 1748134800000, + "unrealizedPnl": "0.06", + "realizedPnl": "0.00", + "pnl": "0.06", + "createdTime": 1748131500000, + "updatedTime": 1748132000000, + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_positions_by_filter() + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/position/filter" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPositionsByFilterResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof or is_list or hasattr(QueryPositionsByFilterResponse, "from_dict") + ): + expected = QueryPositionsByFilterResponse.from_dict(expected_response) + else: + expected = QueryPositionsByFilterResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_positions_by_filter_success_with_optional_params( + self, mock_get_signature + ): + """Test query_positions_by_filter() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "market_topic_id": 4229564, + "recv_window": 5000, + } + + expected_response = { + "positions": [ + { + "positionId": 1001, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112233", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229564, + "marketId": 5567895, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "1923.07", + "avgPrice": "0.52", + "totalCost": "1.00", + "value": "1.06", + "currentPrice": "0.55", + "positionStatus": "OPEN", + "endDate": 1748134800000, + "unrealizedPnl": "0.06", + "realizedPnl": "0.00", + "pnl": "0.06", + "createdTime": 1748131500000, + "updatedTime": 1748132000000, + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_positions_by_filter(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/position/filter" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPositionsByFilterResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof or is_list or hasattr(QueryPositionsByFilterResponse, "from_dict") + ): + expected = QueryPositionsByFilterResponse.from_dict(expected_response) + else: + expected = QueryPositionsByFilterResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_positions_by_filter_server_error(self): + """Test that query_positions_by_filter() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.client.query_positions_by_filter = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_positions_by_filter() + + @patch("binance_common.utils.get_signature") + def test_query_settled_position_history_success(self, mock_get_signature): + """Test query_settled_position_history() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + expected_response = { + "totalCount": 5, + "positions": [ + { + "positionId": 998, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112200", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229500, + "marketId": 5567800, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "5000.00", + "avgPrice": "0.30", + "totalCost": "1.50", + "value": "5000.00", + "currentPrice": "1.00", + "toWin": "5000.00", + "positionStatus": "CLAIMED", + "isWinner": True, + "redeemStatus": "CONFIRMED", + "endDate": 1748040000000, + "finalOutcome": "YES", + "realizedPnl": "4998.50", + "pnl": "4998.50", + "claimAmount": "5000.00", + "settledDate": 1748040000000, + "createdTime": 1748020000000, + "updatedTime": 1748040500000, + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_settled_position_history(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/position/settled-history" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QuerySettledPositionHistoryResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof + or is_list + or hasattr(QuerySettledPositionHistoryResponse, "from_dict") + ): + expected = QuerySettledPositionHistoryResponse.from_dict(expected_response) + else: + expected = QuerySettledPositionHistoryResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_settled_position_history_success_with_optional_params( + self, mock_get_signature + ): + """Test query_settled_position_history() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "l1_category": "crypto", + "result": 1, + "start_date": "2026-05-01", + "end_date": "2026-05-25", + "offset": 0, + "limit": 20, + "recv_window": 5000, + } + + expected_response = { + "totalCount": 5, + "positions": [ + { + "positionId": 998, + "vendor": "PREDICT_FUN", + "chainId": "56", + "tokenId": "112200", + "collateralSymbol": "USDT", + "topicType": "FLAT", + "marketTopicId": 4229500, + "marketId": 5567800, + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketTitle": "UP", + "outcomeName": "YES", + "outcomeIndex": 0, + "shares": "5000.00", + "avgPrice": "0.30", + "totalCost": "1.50", + "value": "5000.00", + "currentPrice": "1.00", + "toWin": "5000.00", + "positionStatus": "CLAIMED", + "isWinner": True, + "redeemStatus": "CONFIRMED", + "endDate": 1748040000000, + "finalOutcome": "YES", + "realizedPnl": "4998.50", + "pnl": "4998.50", + "claimAmount": "5000.00", + "settledDate": 1748040000000, + "createdTime": 1748020000000, + "updatedTime": 1748040500000, + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_settled_position_history(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/position/settled-history" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QuerySettledPositionHistoryResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof + or is_list + or hasattr(QuerySettledPositionHistoryResponse, "from_dict") + ): + expected = QuerySettledPositionHistoryResponse.from_dict(expected_response) + else: + expected = QuerySettledPositionHistoryResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_settled_position_history_missing_required_param_wallet_address(self): + """Test that query_settled_position_history() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.query_settled_position_history(**params) + + def test_query_settled_position_history_server_error(self): + """Test that query_settled_position_history() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + mock_error = Exception("ResponseError") + self.client.query_settled_position_history = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_settled_position_history(**params) diff --git a/clients/w3w_prediction/tests/unit/rest_api/test_redeem_api.py b/clients/w3w_prediction/tests/unit/rest_api/test_redeem_api.py new file mode 100644 index 00000000..b4bac21d --- /dev/null +++ b/clients/w3w_prediction/tests/unit/rest_api/test_redeem_api.py @@ -0,0 +1,364 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +import json +import pytest +import requests + +from unittest.mock import MagicMock, patch +from urllib.parse import parse_qs + +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel + +from binance_sdk_w3w_prediction.rest_api.api import RedeemApi +from binance_sdk_w3w_prediction.rest_api.models import BatchRedeemResponse +from binance_sdk_w3w_prediction.rest_api.models import GetRedeemStatusResponse + + +class TestRedeemApi: + @pytest.fixture(autouse=True) + def setup_client(self): + """Setup a client instance with mocked session before each test method.""" + self.mock_session = MagicMock(spec=requests.Session) + config = ConfigurationRestAPI( + api_key="test-api-key", + api_secret="test-api-secret", + ) + self.client = RedeemApi(configuration=config, session=self.mock_session) + + def set_mock_response(self, data: dict = {}, status_code=200, headers=None): + """Helper method to setup mock response for the client's session request.""" + if headers is None: + headers = {} + + mock_response = MagicMock() + mock_response.status_code = status_code + mock_response.json.return_value = data + mock_response.text = json.dumps(data) + mock_response.headers = headers + + self.mock_session.request.return_value = mock_response + + @patch("binance_common.utils.get_signature") + def test_batch_redeem_success(self, mock_get_signature): + """Test batch_redeem() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "token_ids": ["112233"], + } + + expected_response = { + "batchId": "batch_20260525_redeem_001", + "results": [ + { + "requestId": "req_001", + "txHash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + "status": "PENDING", + "error": "error", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.batch_redeem(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/batch-redeem" in request_kwargs["url"] + assert request_kwargs["method"] == "POST" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["walletId"] == "5b5c1ec3be4e4416a5872b21c1ca5d20" + assert "tokenIds" in normalized + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(BatchRedeemResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(BatchRedeemResponse, "from_dict"): + expected = BatchRedeemResponse.from_dict(expected_response) + else: + expected = BatchRedeemResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_batch_redeem_success_with_optional_params(self, mock_get_signature): + """Test batch_redeem() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "token_ids": ["112233"], + "chain_id": "56", + } + + expected_response = { + "batchId": "batch_20260525_redeem_001", + "results": [ + { + "requestId": "req_001", + "txHash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + "status": "PENDING", + "error": "error", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.batch_redeem(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/batch-redeem" in request_kwargs["url"] + assert request_kwargs["method"] == "POST" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(BatchRedeemResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(BatchRedeemResponse, "from_dict"): + expected = BatchRedeemResponse.from_dict(expected_response) + else: + expected = BatchRedeemResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_batch_redeem_missing_required_param_wallet_address(self): + """Test that batch_redeem() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "token_ids": ["112233"], + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.batch_redeem(**params) + + def test_batch_redeem_missing_required_param_wallet_id(self): + """Test that batch_redeem() raises RequiredError when 'wallet_id' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "token_ids": ["112233"], + } + params["wallet_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_id'" + ): + self.client.batch_redeem(**params) + + def test_batch_redeem_missing_required_param_token_ids(self): + """Test that batch_redeem() raises RequiredError when 'token_ids' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "token_ids": ["112233"], + } + params["token_ids"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'token_ids'" + ): + self.client.batch_redeem(**params) + + def test_batch_redeem_server_error(self): + """Test that batch_redeem() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "token_ids": ["112233"], + } + + mock_error = Exception("ResponseError") + self.client.batch_redeem = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.batch_redeem(**params) + + @patch("binance_common.utils.get_signature") + def test_get_redeem_status_success(self, mock_get_signature): + """Test get_redeem_status() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "tx_hash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + } + + expected_response = { + "txHash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + "status": "CONFIRMED", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_redeem_status(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/redeem/status" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert ( + normalized["txHash"] + == "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd" + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetRedeemStatusResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetRedeemStatusResponse, "from_dict"): + expected = GetRedeemStatusResponse.from_dict(expected_response) + else: + expected = GetRedeemStatusResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_get_redeem_status_success_with_optional_params(self, mock_get_signature): + """Test get_redeem_status() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "tx_hash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + "recv_window": 5000, + } + + expected_response = { + "txHash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + "status": "CONFIRMED", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_redeem_status(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/redeem/status" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetRedeemStatusResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetRedeemStatusResponse, "from_dict"): + expected = GetRedeemStatusResponse.from_dict(expected_response) + else: + expected = GetRedeemStatusResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_get_redeem_status_missing_required_param_wallet_address(self): + """Test that get_redeem_status() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "tx_hash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.get_redeem_status(**params) + + def test_get_redeem_status_missing_required_param_tx_hash(self): + """Test that get_redeem_status() raises RequiredError when 'tx_hash' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "tx_hash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + } + params["tx_hash"] = None + + with pytest.raises(RequiredError, match="Missing required parameter 'tx_hash'"): + self.client.get_redeem_status(**params) + + def test_get_redeem_status_server_error(self): + """Test that get_redeem_status() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "tx_hash": "0xabc123def456789abcdef123456789abcdef123456789abcdef123456789abcd", + } + + mock_error = Exception("ResponseError") + self.client.get_redeem_status = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.get_redeem_status(**params) diff --git a/clients/w3w_prediction/tests/unit/rest_api/test_trade_api.py b/clients/w3w_prediction/tests/unit/rest_api/test_trade_api.py new file mode 100644 index 00000000..d500fbcf --- /dev/null +++ b/clients/w3w_prediction/tests/unit/rest_api/test_trade_api.py @@ -0,0 +1,1138 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +import json +import pytest +import requests + +from unittest.mock import MagicMock, patch +from urllib.parse import parse_qs + +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel + +from binance_sdk_w3w_prediction.rest_api.api import TradeApi +from binance_sdk_w3w_prediction.rest_api.models import BatchCancelOrdersResponse +from binance_sdk_w3w_prediction.rest_api.models import GetQuoteResponse +from binance_sdk_w3w_prediction.rest_api.models import PlaceOrderResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryActiveOrdersResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryOrderHistoryResponse + + +from binance_sdk_w3w_prediction.rest_api.models import ( + BatchCancelOrdersCancelInfoListParameterInner, +) + + +from binance_sdk_w3w_prediction.rest_api.models import GetQuoteSideEnum + +from binance_sdk_w3w_prediction.rest_api.models import GetQuoteOrderTypeEnum + + +from binance_sdk_w3w_prediction.rest_api.models import GetQuoteFundingSourceEnum + + +from binance_sdk_w3w_prediction.rest_api.models import PlaceOrderAccountTypeEnum +from binance_sdk_w3w_prediction.rest_api.models import PlaceOrderOrderTypeEnum + + +from binance_sdk_w3w_prediction.rest_api.models import PlaceOrderFundingSourceEnum + + +from binance_sdk_w3w_prediction.rest_api.models import QueryActiveOrdersTradeSideEnum + + +from binance_sdk_w3w_prediction.rest_api.models import QueryOrderHistoryOrderTypeEnum + + +class TestTradeApi: + @pytest.fixture(autouse=True) + def setup_client(self): + """Setup a client instance with mocked session before each test method.""" + self.mock_session = MagicMock(spec=requests.Session) + config = ConfigurationRestAPI( + api_key="test-api-key", + api_secret="test-api-secret", + ) + self.client = TradeApi(configuration=config, session=self.mock_session) + + def set_mock_response(self, data: dict = {}, status_code=200, headers=None): + """Helper method to setup mock response for the client's session request.""" + if headers is None: + headers = {} + + mock_response = MagicMock() + mock_response.status_code = status_code + mock_response.json.return_value = data + mock_response.text = json.dumps(data) + mock_response.headers = headers + + self.mock_session.request.return_value = mock_response + + @patch("binance_common.utils.get_signature") + def test_batch_cancel_orders_success(self, mock_get_signature): + """Test batch_cancel_orders() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + } + + expected_response = { + "canceled": ["54124"], + "failed": [{"orderId": "54126", "reason": "ORDER_NOT_FOUND"}], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.batch_cancel_orders(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/trade/batch-cancel" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["walletId"] == "5b5c1ec3be4e4416a5872b21c1ca5d20" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(BatchCancelOrdersResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(BatchCancelOrdersResponse, "from_dict"): + expected = BatchCancelOrdersResponse.from_dict(expected_response) + else: + expected = BatchCancelOrdersResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_batch_cancel_orders_success_with_optional_params(self, mock_get_signature): + """Test batch_cancel_orders() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "cancel_info_list": [ + BatchCancelOrdersCancelInfoListParameterInner( + order_id="54124", + ) + ], + } + + expected_response = { + "canceled": ["54124"], + "failed": [{"orderId": "54126", "reason": "ORDER_NOT_FOUND"}], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.batch_cancel_orders(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/trade/batch-cancel" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(BatchCancelOrdersResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(BatchCancelOrdersResponse, "from_dict"): + expected = BatchCancelOrdersResponse.from_dict(expected_response) + else: + expected = BatchCancelOrdersResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_batch_cancel_orders_missing_required_param_wallet_address(self): + """Test that batch_cancel_orders() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.batch_cancel_orders(**params) + + def test_batch_cancel_orders_missing_required_param_wallet_id(self): + """Test that batch_cancel_orders() raises RequiredError when 'wallet_id' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + } + params["wallet_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_id'" + ): + self.client.batch_cancel_orders(**params) + + def test_batch_cancel_orders_server_error(self): + """Test that batch_cancel_orders() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + } + + mock_error = Exception("ResponseError") + self.client.batch_cancel_orders = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.batch_cancel_orders(**params) + + @patch("binance_common.utils.get_signature") + def test_get_quote_success(self, mock_get_signature): + """Test get_quote() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + + expected_response = { + "quoteId": "q_20260525_abc123xyz", + "tokenId": "112233", + "chance": "0.52", + "vendor": "PREDICT_FUN", + "marketTitle": "UP", + "marketExtId": "ext_001", + "side": "BUY", + "amountIn": "1000000000000000000", + "amountOut": "1923070000000000000", + "isMinAmountOut": False, + "feeAmount": "20000000000000000", + "feeDiscountBps": "0", + "averagePrice": 0.52, + "lastPrice": 0.52, + "priceImpact": 0.001, + "timestamp": 1748131500000, + "chainId": "56", + "userId": 100103755893, + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "orderType": "MARKET", + "slippageBps": 1200, + "feeRateBps": 200, + "minReceive": "1900000000000000000", + "expireAt": 1748131800000, + "priceLimit": "priceLimit", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_quote(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/trade/get-quote" in request_kwargs["url"] + assert request_kwargs["method"] == "POST" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["tokenId"] == "112233" + assert normalized["side"] == GetQuoteSideEnum["BUY"].value + assert normalized["amountIn"] == "1000000000000000000" + assert normalized["orderType"] == GetQuoteOrderTypeEnum["MARKET"].value + assert normalized["slippageBps"] == 1200 + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetQuoteResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetQuoteResponse, "from_dict"): + expected = GetQuoteResponse.from_dict(expected_response) + else: + expected = GetQuoteResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_get_quote_success_with_optional_params(self, mock_get_signature): + """Test get_quote() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + "price_limit": "0.5", + "chain_id": "56", + "fee_rate_bps": 200, + "funding_source": GetQuoteFundingSourceEnum["MPC"].value, + "fund_transfer_amount": "1000000000000000000", + } + + expected_response = { + "quoteId": "q_20260525_abc123xyz", + "tokenId": "112233", + "chance": "0.52", + "vendor": "PREDICT_FUN", + "marketTitle": "UP", + "marketExtId": "ext_001", + "side": "BUY", + "amountIn": "1000000000000000000", + "amountOut": "1923070000000000000", + "isMinAmountOut": False, + "feeAmount": "20000000000000000", + "feeDiscountBps": "0", + "averagePrice": 0.52, + "lastPrice": 0.52, + "priceImpact": 0.001, + "timestamp": 1748131500000, + "chainId": "56", + "userId": 100103755893, + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "orderType": "MARKET", + "slippageBps": 1200, + "feeRateBps": 200, + "minReceive": "1900000000000000000", + "expireAt": 1748131800000, + "priceLimit": "priceLimit", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_quote(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/trade/get-quote" in request_kwargs["url"] + assert request_kwargs["method"] == "POST" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetQuoteResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetQuoteResponse, "from_dict"): + expected = GetQuoteResponse.from_dict(expected_response) + else: + expected = GetQuoteResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_get_quote_missing_required_param_wallet_address(self): + """Test that get_quote() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.get_quote(**params) + + def test_get_quote_missing_required_param_token_id(self): + """Test that get_quote() raises RequiredError when 'token_id' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["token_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'token_id'" + ): + self.client.get_quote(**params) + + def test_get_quote_missing_required_param_side(self): + """Test that get_quote() raises RequiredError when 'side' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["side"] = None + + with pytest.raises(RequiredError, match="Missing required parameter 'side'"): + self.client.get_quote(**params) + + def test_get_quote_missing_required_param_amount_in(self): + """Test that get_quote() raises RequiredError when 'amount_in' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["amount_in"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'amount_in'" + ): + self.client.get_quote(**params) + + def test_get_quote_missing_required_param_order_type(self): + """Test that get_quote() raises RequiredError when 'order_type' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["order_type"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'order_type'" + ): + self.client.get_quote(**params) + + def test_get_quote_missing_required_param_slippage_bps(self): + """Test that get_quote() raises RequiredError when 'slippage_bps' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["slippage_bps"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'slippage_bps'" + ): + self.client.get_quote(**params) + + def test_get_quote_server_error(self): + """Test that get_quote() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "side": GetQuoteSideEnum["BUY"].value, + "amount_in": "1000000000000000000", + "order_type": GetQuoteOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + + mock_error = Exception("ResponseError") + self.client.get_quote = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.get_quote(**params) + + @patch("binance_common.utils.get_signature") + def test_place_order_success(self, mock_get_signature): + """Test place_order() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + + expected_response = {"orderId": "54124"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.place_order(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/trade/place-order-bundle" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["walletId"] == "5b5c1ec3be4e4416a5872b21c1ca5d20" + assert normalized["quoteId"] == "q_20260525_abc123xyz" + assert normalized["timeInForce"] == "FOK" + assert normalized["accountType"] == PlaceOrderAccountTypeEnum["SPOT"].value + assert normalized["orderType"] == PlaceOrderOrderTypeEnum["MARKET"].value + assert normalized["slippageBps"] == 1200 + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(PlaceOrderResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(PlaceOrderResponse, "from_dict"): + expected = PlaceOrderResponse.from_dict(expected_response) + else: + expected = PlaceOrderResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_place_order_success_with_optional_params(self, mock_get_signature): + """Test place_order() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + "price_limit": "0.5", + "funding_source": PlaceOrderFundingSourceEnum["MPC"].value, + "fund_transfer_amount": "1000000000000000000", + } + + expected_response = {"orderId": "54124"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.place_order(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/trade/place-order-bundle" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(PlaceOrderResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(PlaceOrderResponse, "from_dict"): + expected = PlaceOrderResponse.from_dict(expected_response) + else: + expected = PlaceOrderResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_place_order_missing_required_param_wallet_address(self): + """Test that place_order() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.place_order(**params) + + def test_place_order_missing_required_param_wallet_id(self): + """Test that place_order() raises RequiredError when 'wallet_id' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["wallet_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_id'" + ): + self.client.place_order(**params) + + def test_place_order_missing_required_param_quote_id(self): + """Test that place_order() raises RequiredError when 'quote_id' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["quote_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'quote_id'" + ): + self.client.place_order(**params) + + def test_place_order_missing_required_param_time_in_force(self): + """Test that place_order() raises RequiredError when 'time_in_force' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["time_in_force"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'time_in_force'" + ): + self.client.place_order(**params) + + def test_place_order_missing_required_param_account_type(self): + """Test that place_order() raises RequiredError when 'account_type' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["account_type"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'account_type'" + ): + self.client.place_order(**params) + + def test_place_order_missing_required_param_order_type(self): + """Test that place_order() raises RequiredError when 'order_type' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["order_type"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'order_type'" + ): + self.client.place_order(**params) + + def test_place_order_missing_required_param_slippage_bps(self): + """Test that place_order() raises RequiredError when 'slippage_bps' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + params["slippage_bps"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'slippage_bps'" + ): + self.client.place_order(**params) + + def test_place_order_server_error(self): + """Test that place_order() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "quote_id": "q_20260525_abc123xyz", + "time_in_force": "FOK", + "account_type": PlaceOrderAccountTypeEnum["SPOT"].value, + "order_type": PlaceOrderOrderTypeEnum["MARKET"].value, + "slippage_bps": 1200, + } + + mock_error = Exception("ResponseError") + self.client.place_order = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.place_order(**params) + + @patch("binance_common.utils.get_signature") + def test_query_active_orders_success(self, mock_get_signature): + """Test query_active_orders() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + expected_response = { + "total": 2, + "offset": 0, + "limit": 20, + "orders": [ + { + "orderId": "54124", + "vendorOrderId": "0x1234abcd...", + "vendor": "PREDICT_FUN", + "marketTopicId": 4229564, + "slug": "btc-price-1h-up-or-down", + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketId": 5567895, + "marketTitle": "UP", + "outcome": "YES", + "outcomeIndex": 0, + "status": "OPENING", + "side": "BUY", + "orderType": "LIMIT", + "createTime": 1748131500000, + "modifyTime": 1748131500000, + "makerUsdtAmount": "1.00", + "makerShareQty": "2000.00", + "filledUsdtAmount": "0.00", + "filledShareQty": "0.00", + "fillPercentage": "0.00", + "price": "0.50", + "marketProviderFee": "0.02", + "networkFee": "0.000001", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_active_orders(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/order/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryActiveOrdersResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryActiveOrdersResponse, "from_dict"): + expected = QueryActiveOrdersResponse.from_dict(expected_response) + else: + expected = QueryActiveOrdersResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_active_orders_success_with_optional_params(self, mock_get_signature): + """Test query_active_orders() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "trade_side": QueryActiveOrdersTradeSideEnum["BUY"].value, + "l1_category": "crypto", + "market_id": 5567895, + "offset": 0, + "limit": 20, + "recv_window": 5000, + } + + expected_response = { + "total": 2, + "offset": 0, + "limit": 20, + "orders": [ + { + "orderId": "54124", + "vendorOrderId": "0x1234abcd...", + "vendor": "PREDICT_FUN", + "marketTopicId": 4229564, + "slug": "btc-price-1h-up-or-down", + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketId": 5567895, + "marketTitle": "UP", + "outcome": "YES", + "outcomeIndex": 0, + "status": "OPENING", + "side": "BUY", + "orderType": "LIMIT", + "createTime": 1748131500000, + "modifyTime": 1748131500000, + "makerUsdtAmount": "1.00", + "makerShareQty": "2000.00", + "filledUsdtAmount": "0.00", + "filledShareQty": "0.00", + "fillPercentage": "0.00", + "price": "0.50", + "marketProviderFee": "0.02", + "networkFee": "0.000001", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_active_orders(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/order/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryActiveOrdersResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryActiveOrdersResponse, "from_dict"): + expected = QueryActiveOrdersResponse.from_dict(expected_response) + else: + expected = QueryActiveOrdersResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_active_orders_missing_required_param_wallet_address(self): + """Test that query_active_orders() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.query_active_orders(**params) + + def test_query_active_orders_server_error(self): + """Test that query_active_orders() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + mock_error = Exception("ResponseError") + self.client.query_active_orders = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_active_orders(**params) + + @patch("binance_common.utils.get_signature") + def test_query_order_history_success(self, mock_get_signature): + """Test query_order_history() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + expected_response = { + "total": 15, + "offset": 0, + "limit": 20, + "orders": [ + { + "orderId": "54100", + "vendorOrderId": "0xabcd5678...", + "vendor": "PREDICT_FUN", + "marketTopicId": 4229500, + "slug": "btc-price-1h-up-or-down-prev", + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketId": 5567800, + "marketTitle": "UP", + "outcome": "YES", + "outcomeIndex": 0, + "status": "CLOSED", + "side": "BUY", + "orderType": "MARKET", + "createTime": 1748045100000, + "modifyTime": 1748045101000, + "terminalTime": 1748045101000, + "makerUsdtAmount": "1.00", + "makerShareQty": "1923.07", + "filledUsdtAmount": "1.00", + "filledShareQty": "1923.07", + "fillPercentage": "1.00", + "price": "0.52", + "marketProviderFee": "0.02", + "networkFee": "0.000001", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_order_history(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/order/history" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryOrderHistoryResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryOrderHistoryResponse, "from_dict"): + expected = QueryOrderHistoryResponse.from_dict(expected_response) + else: + expected = QueryOrderHistoryResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_order_history_success_with_optional_params(self, mock_get_signature): + """Test query_order_history() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "l1_category": "crypto", + "order_type": QueryOrderHistoryOrderTypeEnum["MARKET"].value, + "status": "CLOSED", + "start_date": "2026-05-01", + "end_date": "2026-05-25", + "offset": 0, + "limit": 20, + "recv_window": 5000, + } + + expected_response = { + "total": 15, + "offset": 0, + "limit": 20, + "orders": [ + { + "orderId": "54100", + "vendorOrderId": "0xabcd5678...", + "vendor": "PREDICT_FUN", + "marketTopicId": 4229500, + "slug": "btc-price-1h-up-or-down-prev", + "marketTopicTitle": "BTC Price 1h Up or Down?", + "marketId": 5567800, + "marketTitle": "UP", + "outcome": "YES", + "outcomeIndex": 0, + "status": "CLOSED", + "side": "BUY", + "orderType": "MARKET", + "createTime": 1748045100000, + "modifyTime": 1748045101000, + "terminalTime": 1748045101000, + "makerUsdtAmount": "1.00", + "makerShareQty": "1923.07", + "filledUsdtAmount": "1.00", + "filledShareQty": "1923.07", + "fillPercentage": "1.00", + "price": "0.52", + "marketProviderFee": "0.02", + "networkFee": "0.000001", + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_order_history(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/order/history" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryOrderHistoryResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryOrderHistoryResponse, "from_dict"): + expected = QueryOrderHistoryResponse.from_dict(expected_response) + else: + expected = QueryOrderHistoryResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_order_history_missing_required_param_wallet_address(self): + """Test that query_order_history() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.query_order_history(**params) + + def test_query_order_history_server_error(self): + """Test that query_order_history() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + mock_error = Exception("ResponseError") + self.client.query_order_history = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_order_history(**params) diff --git a/clients/w3w_prediction/tests/unit/rest_api/test_transfer_api.py b/clients/w3w_prediction/tests/unit/rest_api/test_transfer_api.py new file mode 100644 index 00000000..fb133364 --- /dev/null +++ b/clients/w3w_prediction/tests/unit/rest_api/test_transfer_api.py @@ -0,0 +1,809 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +import json +import pytest +import requests + +from unittest.mock import MagicMock, patch +from urllib.parse import parse_qs + +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel + +from binance_sdk_w3w_prediction.rest_api.api import TransferApi +from binance_sdk_w3w_prediction.rest_api.models import CreateInboundTransferResponse +from binance_sdk_w3w_prediction.rest_api.models import CreateOutboundTransferResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryTransferListResponse +from binance_sdk_w3w_prediction.rest_api.models import QueryTransferStatusResponse + + +from binance_sdk_w3w_prediction.rest_api.models import ( + CreateInboundTransferAccountTypeEnum, +) + + +from binance_sdk_w3w_prediction.rest_api.models import ( + CreateOutboundTransferAccountTypeEnum, +) +from binance_sdk_w3w_prediction.rest_api.models import ( + CreateOutboundTransferSourceBizEnum, +) + + +from binance_sdk_w3w_prediction.rest_api.models import QueryTransferListDirectionEnum + + +class TestTransferApi: + @pytest.fixture(autouse=True) + def setup_client(self): + """Setup a client instance with mocked session before each test method.""" + self.mock_session = MagicMock(spec=requests.Session) + config = ConfigurationRestAPI( + api_key="test-api-key", + api_secret="test-api-secret", + ) + self.client = TransferApi(configuration=config, session=self.mock_session) + + def set_mock_response(self, data: dict = {}, status_code=200, headers=None): + """Helper method to setup mock response for the client's session request.""" + if headers is None: + headers = {} + + mock_response = MagicMock() + mock_response.status_code = status_code + mock_response.json.return_value = data + mock_response.text = json.dumps(data) + mock_response.headers = headers + + self.mock_session.request.return_value = mock_response + + @patch("binance_common.utils.get_signature") + def test_create_inbound_transfer_success(self, mock_get_signature): + """Test create_inbound_transfer() successfully with required parameters only.""" + + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateInboundTransferAccountTypeEnum["SPOT"].value, + } + + expected_response = {"transferId": "tf_20260525_in_001", "status": "PROCESSING"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.create_inbound_transfer(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/transfer/inbound" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + assert normalized["walletId"] == "5b5c1ec3be4e4416a5872b21c1ca5d20" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["fromTokenAmount"] == "1000000000000000000" + assert ( + normalized["accountType"] + == CreateInboundTransferAccountTypeEnum["SPOT"].value + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(CreateInboundTransferResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(CreateInboundTransferResponse, "from_dict"): + expected = CreateInboundTransferResponse.from_dict(expected_response) + else: + expected = CreateInboundTransferResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_create_inbound_transfer_success_with_optional_params( + self, mock_get_signature + ): + """Test create_inbound_transfer() successfully with optional parameters.""" + + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateInboundTransferAccountTypeEnum["SPOT"].value, + "from_token": "USDT", + "to_token": "USDT", + "chain_id": "56", + } + + expected_response = {"transferId": "tf_20260525_in_001", "status": "PROCESSING"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.create_inbound_transfer(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/transfer/inbound" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(CreateInboundTransferResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(CreateInboundTransferResponse, "from_dict"): + expected = CreateInboundTransferResponse.from_dict(expected_response) + else: + expected = CreateInboundTransferResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_create_inbound_transfer_missing_required_param_wallet_id(self): + """Test that create_inbound_transfer() raises RequiredError when 'wallet_id' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateInboundTransferAccountTypeEnum["SPOT"].value, + } + params["wallet_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_id'" + ): + self.client.create_inbound_transfer(**params) + + def test_create_inbound_transfer_missing_required_param_wallet_address(self): + """Test that create_inbound_transfer() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateInboundTransferAccountTypeEnum["SPOT"].value, + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.create_inbound_transfer(**params) + + def test_create_inbound_transfer_missing_required_param_from_token_amount(self): + """Test that create_inbound_transfer() raises RequiredError when 'from_token_amount' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateInboundTransferAccountTypeEnum["SPOT"].value, + } + params["from_token_amount"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'from_token_amount'" + ): + self.client.create_inbound_transfer(**params) + + def test_create_inbound_transfer_missing_required_param_account_type(self): + """Test that create_inbound_transfer() raises RequiredError when 'account_type' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateInboundTransferAccountTypeEnum["SPOT"].value, + } + params["account_type"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'account_type'" + ): + self.client.create_inbound_transfer(**params) + + def test_create_inbound_transfer_server_error(self): + """Test that create_inbound_transfer() raises an error when the server returns an error.""" + + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateInboundTransferAccountTypeEnum["SPOT"].value, + } + + mock_error = Exception("ResponseError") + self.client.create_inbound_transfer = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.create_inbound_transfer(**params) + + @patch("binance_common.utils.get_signature") + def test_create_outbound_transfer_success(self, mock_get_signature): + """Test create_outbound_transfer() successfully with required parameters only.""" + + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + } + + expected_response = { + "transferId": "tf_20260525_out_001", + "status": "PROCESSING", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.create_outbound_transfer(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/transfer/outbound" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + assert normalized["walletId"] == "5b5c1ec3be4e4416a5872b21c1ca5d20" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["fromTokenAmount"] == "1000000000000000000" + assert ( + normalized["accountType"] + == CreateOutboundTransferAccountTypeEnum["SPOT"].value + ) + assert ( + normalized["sourceBiz"] + == CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(CreateOutboundTransferResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof or is_list or hasattr(CreateOutboundTransferResponse, "from_dict") + ): + expected = CreateOutboundTransferResponse.from_dict(expected_response) + else: + expected = CreateOutboundTransferResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_create_outbound_transfer_success_with_optional_params( + self, mock_get_signature + ): + """Test create_outbound_transfer() successfully with optional parameters.""" + + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + "from_token": "USDT", + "to_token": "USDT", + "chain_id": "56", + } + + expected_response = { + "transferId": "tf_20260525_out_001", + "status": "PROCESSING", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.create_outbound_transfer(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/transfer/outbound" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "POST" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(CreateOutboundTransferResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof or is_list or hasattr(CreateOutboundTransferResponse, "from_dict") + ): + expected = CreateOutboundTransferResponse.from_dict(expected_response) + else: + expected = CreateOutboundTransferResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_create_outbound_transfer_missing_required_param_wallet_id(self): + """Test that create_outbound_transfer() raises RequiredError when 'wallet_id' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + } + params["wallet_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_id'" + ): + self.client.create_outbound_transfer(**params) + + def test_create_outbound_transfer_missing_required_param_wallet_address(self): + """Test that create_outbound_transfer() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.create_outbound_transfer(**params) + + def test_create_outbound_transfer_missing_required_param_from_token_amount(self): + """Test that create_outbound_transfer() raises RequiredError when 'from_token_amount' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + } + params["from_token_amount"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'from_token_amount'" + ): + self.client.create_outbound_transfer(**params) + + def test_create_outbound_transfer_missing_required_param_account_type(self): + """Test that create_outbound_transfer() raises RequiredError when 'account_type' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + } + params["account_type"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'account_type'" + ): + self.client.create_outbound_transfer(**params) + + def test_create_outbound_transfer_missing_required_param_source_biz(self): + """Test that create_outbound_transfer() raises RequiredError when 'source_biz' is missing.""" + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + } + params["source_biz"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'source_biz'" + ): + self.client.create_outbound_transfer(**params) + + def test_create_outbound_transfer_server_error(self): + """Test that create_outbound_transfer() raises an error when the server returns an error.""" + + params = { + "wallet_id": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "from_token_amount": "1000000000000000000", + "account_type": CreateOutboundTransferAccountTypeEnum["SPOT"].value, + "source_biz": CreateOutboundTransferSourceBizEnum["USER_TRANSFER"].value, + } + + mock_error = Exception("ResponseError") + self.client.create_outbound_transfer = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.create_outbound_transfer(**params) + + @patch("binance_common.utils.get_signature") + def test_query_transfer_list_success(self, mock_get_signature): + """Test query_transfer_list() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "start_date": "2026-05-01", + "end_date": "2026-05-25", + } + + expected_response = { + "transfers": [ + { + "transferId": "tf_20260525_out_001", + "direction": "OUTBOUND", + "status": "SUCCESS", + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "fromToken": "USDT", + "fromTokenAmount": "100.00", + "toToken": "USDT", + "toTokenAmount": "100.00", + "errorCode": "errorCode", + "errorMessage": "errorMessage", + "createTime": "2026-05-25T04:00:00.000+00:00", + "updateTime": "2026-05-25T04:00:05.000+00:00", + "completeAt": "2026-05-25T04:00:05.000+00:00", + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_transfer_list(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/transfer/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + assert normalized["startDate"] == "2026-05-01" + assert normalized["endDate"] == "2026-05-25" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryTransferListResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryTransferListResponse, "from_dict"): + expected = QueryTransferListResponse.from_dict(expected_response) + else: + expected = QueryTransferListResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_transfer_list_success_with_optional_params(self, mock_get_signature): + """Test query_transfer_list() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "start_date": "2026-05-01", + "end_date": "2026-05-25", + "token_symbol": "USDT", + "direction": QueryTransferListDirectionEnum["INBOUND"].value, + "offset": 0, + "limit": 20, + "recv_window": 5000, + } + + expected_response = { + "transfers": [ + { + "transferId": "tf_20260525_out_001", + "direction": "OUTBOUND", + "status": "SUCCESS", + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "fromToken": "USDT", + "fromTokenAmount": "100.00", + "toToken": "USDT", + "toTokenAmount": "100.00", + "errorCode": "errorCode", + "errorMessage": "errorMessage", + "createTime": "2026-05-25T04:00:00.000+00:00", + "updateTime": "2026-05-25T04:00:05.000+00:00", + "completeAt": "2026-05-25T04:00:05.000+00:00", + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_transfer_list(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/transfer/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryTransferListResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryTransferListResponse, "from_dict"): + expected = QueryTransferListResponse.from_dict(expected_response) + else: + expected = QueryTransferListResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_transfer_list_missing_required_param_wallet_address(self): + """Test that query_transfer_list() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "start_date": "2026-05-01", + "end_date": "2026-05-25", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.query_transfer_list(**params) + + def test_query_transfer_list_missing_required_param_start_date(self): + """Test that query_transfer_list() raises RequiredError when 'start_date' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "start_date": "2026-05-01", + "end_date": "2026-05-25", + } + params["start_date"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'start_date'" + ): + self.client.query_transfer_list(**params) + + def test_query_transfer_list_missing_required_param_end_date(self): + """Test that query_transfer_list() raises RequiredError when 'end_date' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "start_date": "2026-05-01", + "end_date": "2026-05-25", + } + params["end_date"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'end_date'" + ): + self.client.query_transfer_list(**params) + + def test_query_transfer_list_server_error(self): + """Test that query_transfer_list() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "start_date": "2026-05-01", + "end_date": "2026-05-25", + } + + mock_error = Exception("ResponseError") + self.client.query_transfer_list = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_transfer_list(**params) + + @patch("binance_common.utils.get_signature") + def test_query_transfer_status_success(self, mock_get_signature): + """Test query_transfer_status() successfully with required parameters only.""" + + params = { + "transfer_id": "tf_20260525_out_001", + } + + expected_response = { + "transferId": "tf_20260525_out_001", + "direction": "OUTBOUND", + "status": "COMPLETED", + "fromToken": "USDT", + "fromTokenAmount": "100.00", + "toToken": "USDT", + "toTokenAmount": "100.00", + "errorCode": "errorCode", + "errorMessage": "errorMessage", + "createTime": "2026-05-25T04:00:00.000+00:00", + "updateTime": "2026-05-25T04:00:05.000+00:00", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_transfer_status(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/transfer/status" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert normalized["transferId"] == "tf_20260525_out_001" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryTransferStatusResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryTransferStatusResponse, "from_dict"): + expected = QueryTransferStatusResponse.from_dict(expected_response) + else: + expected = QueryTransferStatusResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_transfer_status_success_with_optional_params( + self, mock_get_signature + ): + """Test query_transfer_status() successfully with optional parameters.""" + + params = {"transfer_id": "tf_20260525_out_001", "recv_window": 5000} + + expected_response = { + "transferId": "tf_20260525_out_001", + "direction": "OUTBOUND", + "status": "COMPLETED", + "fromToken": "USDT", + "fromTokenAmount": "100.00", + "toToken": "USDT", + "toTokenAmount": "100.00", + "errorCode": "errorCode", + "errorMessage": "errorMessage", + "createTime": "2026-05-25T04:00:00.000+00:00", + "updateTime": "2026-05-25T04:00:05.000+00:00", + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_transfer_status(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/transfer/status" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryTransferStatusResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(QueryTransferStatusResponse, "from_dict"): + expected = QueryTransferStatusResponse.from_dict(expected_response) + else: + expected = QueryTransferStatusResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_transfer_status_missing_required_param_transfer_id(self): + """Test that query_transfer_status() raises RequiredError when 'transfer_id' is missing.""" + params = { + "transfer_id": "tf_20260525_out_001", + } + params["transfer_id"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'transfer_id'" + ): + self.client.query_transfer_status(**params) + + def test_query_transfer_status_server_error(self): + """Test that query_transfer_status() raises an error when the server returns an error.""" + + params = { + "transfer_id": "tf_20260525_out_001", + } + + mock_error = Exception("ResponseError") + self.client.query_transfer_status = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_transfer_status(**params) diff --git a/clients/w3w_prediction/tests/unit/rest_api/test_wallet_api.py b/clients/w3w_prediction/tests/unit/rest_api/test_wallet_api.py new file mode 100644 index 00000000..5e2abbaa --- /dev/null +++ b/clients/w3w_prediction/tests/unit/rest_api/test_wallet_api.py @@ -0,0 +1,542 @@ +""" +Prediction Trading REST API + +Place and manage prediction market orders, query positions, and transfer funds via the Prediction Trading REST API. +The version of the OpenAPI document: 1.0.0 +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" + +import json +import pytest +import requests + +from unittest.mock import MagicMock, patch +from urllib.parse import parse_qs + +from binance_common.configuration import ConfigurationRestAPI +from binance_common.errors import RequiredError +from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel + +from binance_sdk_w3w_prediction.rest_api.api import WalletApi +from binance_sdk_w3w_prediction.rest_api.models import GetPortfolioResponse +from binance_sdk_w3w_prediction.rest_api.models import GetQuotaStatusResponse +from binance_sdk_w3w_prediction.rest_api.models import ListPredictionWalletsResponse +from binance_sdk_w3w_prediction.rest_api.models import ( + QueryPaymentOptionBalancesResponse, +) + + +class TestWalletApi: + @pytest.fixture(autouse=True) + def setup_client(self): + """Setup a client instance with mocked session before each test method.""" + self.mock_session = MagicMock(spec=requests.Session) + config = ConfigurationRestAPI( + api_key="test-api-key", + api_secret="test-api-secret", + ) + self.client = WalletApi(configuration=config, session=self.mock_session) + + def set_mock_response(self, data: dict = {}, status_code=200, headers=None): + """Helper method to setup mock response for the client's session request.""" + if headers is None: + headers = {} + + mock_response = MagicMock() + mock_response.status_code = status_code + mock_response.json.return_value = data + mock_response.text = json.dumps(data) + mock_response.headers = headers + + self.mock_session.request.return_value = mock_response + + @patch("binance_common.utils.get_signature") + def test_get_portfolio_success(self, mock_get_signature): + """Test get_portfolio() successfully with required parameters only.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + expected_response = { + "chainId": "56", + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "activePositionsCount": 3, + "totalRealizedPnl": "120.50", + "totalUnrealizedPnl": "15.30", + "totalPnl": "135.80", + "totalCostBasis": "450.00", + "totalCurrentValue": "465.30", + "positions": [ + { + "id": 10001, + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "marketTopicId": 4229564, + "marketId": 5567895, + "tokenId": "112233", + "vendor": "PREDICT_FUN", + "currentShares": "1923.07", + "avgPrice": "0.52", + "currentPrice": "0.55", + "realizedPnl": "0.00", + "unrealizedPnl": "0.06", + "totalPnl": "0.06", + "pnlPercentage": "6.00", + "isResolved": False, + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_portfolio(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + parsed_params = parse_qs(request_kwargs["params"]) + camel_case_params = {snake_to_camel(k): v for k, v in params.items()} + normalized = normalize_query_values(parsed_params, camel_case_params) + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/pnl/portfolio" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + assert ( + normalized["walletAddress"] == "0x12e32db8817e292508c34111cbc4b23340df542c" + ) + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetPortfolioResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetPortfolioResponse, "from_dict"): + expected = GetPortfolioResponse.from_dict(expected_response) + else: + expected = GetPortfolioResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_get_portfolio_success_with_optional_params(self, mock_get_signature): + """Test get_portfolio() successfully with optional parameters.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + "token_id": "112233", + "market_id": 5567895, + "market_topic_id": 4229564, + "active_only": False, + "recv_window": 5000, + } + + expected_response = { + "chainId": "56", + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "activePositionsCount": 3, + "totalRealizedPnl": "120.50", + "totalUnrealizedPnl": "15.30", + "totalPnl": "135.80", + "totalCostBasis": "450.00", + "totalCurrentValue": "465.30", + "positions": [ + { + "id": 10001, + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "marketTopicId": 4229564, + "marketId": 5567895, + "tokenId": "112233", + "vendor": "PREDICT_FUN", + "currentShares": "1923.07", + "avgPrice": "0.52", + "currentPrice": "0.55", + "realizedPnl": "0.00", + "unrealizedPnl": "0.06", + "totalPnl": "0.06", + "pnlPercentage": "6.00", + "isResolved": False, + } + ], + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_portfolio(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/pnl/portfolio" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetPortfolioResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetPortfolioResponse, "from_dict"): + expected = GetPortfolioResponse.from_dict(expected_response) + else: + expected = GetPortfolioResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_get_portfolio_missing_required_param_wallet_address(self): + """Test that get_portfolio() raises RequiredError when 'wallet_address' is missing.""" + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + params["wallet_address"] = None + + with pytest.raises( + RequiredError, match="Missing required parameter 'wallet_address'" + ): + self.client.get_portfolio(**params) + + def test_get_portfolio_server_error(self): + """Test that get_portfolio() raises an error when the server returns an error.""" + + params = { + "wallet_address": "0x12e32db8817e292508c34111cbc4b23340df542c", + } + + mock_error = Exception("ResponseError") + self.client.get_portfolio = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.get_portfolio(**params) + + @patch("binance_common.utils.get_signature") + def test_get_quota_status_success(self, mock_get_signature): + """Test get_quota_status() successfully with required parameters only.""" + + expected_response = {"dailyLimit": "10000.00", "remainingDailyLimit": "8500.00"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_quota_status() + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/quota/limit/status" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetQuotaStatusResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetQuotaStatusResponse, "from_dict"): + expected = GetQuotaStatusResponse.from_dict(expected_response) + else: + expected = GetQuotaStatusResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_get_quota_status_success_with_optional_params(self, mock_get_signature): + """Test get_quota_status() successfully with optional parameters.""" + + params = {"recv_window": 5000} + + expected_response = {"dailyLimit": "10000.00", "remainingDailyLimit": "8500.00"} + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.get_quota_status(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/quota/limit/status" in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(GetQuotaStatusResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(GetQuotaStatusResponse, "from_dict"): + expected = GetQuotaStatusResponse.from_dict(expected_response) + else: + expected = GetQuotaStatusResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_get_quota_status_server_error(self): + """Test that get_quota_status() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.client.get_quota_status = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.get_quota_status() + + @patch("binance_common.utils.get_signature") + def test_list_prediction_wallets_success(self, mock_get_signature): + """Test list_prediction_wallets() successfully with required parameters only.""" + + expected_response = { + "wallets": [ + { + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "walletId": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "registeredTime": 1748000000000, + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.list_prediction_wallets() + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/wallet/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(ListPredictionWalletsResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(ListPredictionWalletsResponse, "from_dict"): + expected = ListPredictionWalletsResponse.from_dict(expected_response) + else: + expected = ListPredictionWalletsResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_list_prediction_wallets_success_with_optional_params( + self, mock_get_signature + ): + """Test list_prediction_wallets() successfully with optional parameters.""" + + params = {"recv_window": 5000} + + expected_response = { + "wallets": [ + { + "walletAddress": "0x12e32db8817e292508c34111cbc4b23340df542c", + "walletId": "5b5c1ec3be4e4416a5872b21c1ca5d20", + "registeredTime": 1748000000000, + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.list_prediction_wallets(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert "/sapi/v1/w3w/wallet/prediction/wallet/list" in request_kwargs["url"] + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(ListPredictionWalletsResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif is_oneof or is_list or hasattr(ListPredictionWalletsResponse, "from_dict"): + expected = ListPredictionWalletsResponse.from_dict(expected_response) + else: + expected = ListPredictionWalletsResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_list_prediction_wallets_server_error(self): + """Test that list_prediction_wallets() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.client.list_prediction_wallets = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.list_prediction_wallets() + + @patch("binance_common.utils.get_signature") + def test_query_payment_option_balances_success(self, mock_get_signature): + """Test query_payment_option_balances() successfully with required parameters only.""" + + expected_response = { + "items": [ + { + "accountType": "SPOT", + "availableBalanceDisplay": "1000.00", + "enabled": True, + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_payment_option_balances() + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + self.mock_session.request.assert_called_once() + mock_get_signature.assert_called_once() + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/balance/payment-options" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPaymentOptionBalancesResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof + or is_list + or hasattr(QueryPaymentOptionBalancesResponse, "from_dict") + ): + expected = QueryPaymentOptionBalancesResponse.from_dict(expected_response) + else: + expected = QueryPaymentOptionBalancesResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + @patch("binance_common.utils.get_signature") + def test_query_payment_option_balances_success_with_optional_params( + self, mock_get_signature + ): + """Test query_payment_option_balances() successfully with optional parameters.""" + + params = {"recv_window": 5000} + + expected_response = { + "items": [ + { + "accountType": "SPOT", + "availableBalanceDisplay": "1000.00", + "enabled": True, + } + ] + } + mock_get_signature.return_value = "mocked_signature" + self.set_mock_response(expected_response) + + response = self.client.query_payment_option_balances(**params) + + actual_call_args = self.mock_session.request.call_args + request_kwargs = actual_call_args.kwargs + + assert "url" in request_kwargs + assert "signature" in parse_qs(request_kwargs["params"]) + assert ( + "/sapi/v1/w3w/wallet/prediction/balance/payment-options" + in request_kwargs["url"] + ) + assert request_kwargs["method"] == "GET" + + self.mock_session.request.assert_called_once() + assert response is not None + is_list = isinstance(expected_response, list) + is_flat_list = ( + is_list and not isinstance(expected_response[0], list) if is_list else False + ) + is_oneof = is_one_of_model(QueryPaymentOptionBalancesResponse) + + if is_list and not is_flat_list: + expected = expected_response + elif ( + is_oneof + or is_list + or hasattr(QueryPaymentOptionBalancesResponse, "from_dict") + ): + expected = QueryPaymentOptionBalancesResponse.from_dict(expected_response) + else: + expected = QueryPaymentOptionBalancesResponse.model_validate_json( + json.dumps(expected_response) + ) + + assert response.data() == expected + + def test_query_payment_option_balances_server_error(self): + """Test that query_payment_option_balances() raises an error when the server returns an error.""" + + mock_error = Exception("ResponseError") + self.client.query_payment_option_balances = MagicMock(side_effect=mock_error) + + with pytest.raises(Exception, match="ResponseError"): + self.client.query_payment_option_balances() diff --git a/clients/w3w_prediction/tox.ini b/clients/w3w_prediction/tox.ini new file mode 100644 index 00000000..8007c66c --- /dev/null +++ b/clients/w3w_prediction/tox.ini @@ -0,0 +1,52 @@ +[tox] +# Define environments to run for comprehensive testing. +# py39, py310, py311, py312, py313, py314 are standard test environments. +# lint and format-check are added for code quality assurance. +envlist = py{39,10,11,12,13,14}, lint, format-check + +# Ensures the project's source distribution is built in isolation before installing. +isolated_build = true + +# ------------------------------------ +# Base Configuration for Test Environments (py39, py310, etc.) +# ------------------------------------ +[testenv] +# Dependencies needed to run tests (pytest itself). +deps = pytest +# Explicitly allow external commands (Poetry) for security/modern tox versions. +allowlist_externals = poetry +# Ensure all project dependencies are installed by Poetry first. +# Note: This relies on 'poetry install' respecting the environment and installing test dependencies. +commands_pre = + poetry install +# Run the tests. +commands = + pytest + +# ------------------------------------ +# Code Quality - LINTING Environment +# Checks static code analysis (style and types) +# ------------------------------------ +[testenv:lint] +skip_install = True +# Linting tools: flake8 for style/errors for type checking. +deps = + flake8 + poetry +# Check all Python files +commands = + flake8 --max-line-length 120 . + +# ------------------------------------ +# Code Quality - FORMAT CHECK Environment +# Checks code formatting using Black (no auto-fix). +# ------------------------------------ +[testenv:format-check] +skip_install = True +# Black is the standard formatter. +deps = + black + poetry +# Check all files recursively without modifying them (-c is check-only). +commands = + black --check . \ No newline at end of file