From 81b0e1cbafacec188dcdceb8cffa1acc90232127 Mon Sep 17 00:00:00 2001 From: davidMkCb <159589283+davidMkCb@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:32:18 -0700 Subject: [PATCH] Release v1.7.0 (#74) --- CHANGELOG.md | 6 + README.md | 16 + coinbase/__version__.py | 2 +- coinbase/rest/__init__.py | 2 +- coinbase/rest/accounts.py | 9 +- coinbase/rest/convert.py | 17 +- coinbase/rest/data_api.py | 5 +- coinbase/rest/fees.py | 5 +- coinbase/rest/futures.py | 51 +- coinbase/rest/market_data.py | 12 +- coinbase/rest/orders.py | 155 +++-- coinbase/rest/payments.py | 14 +- coinbase/rest/perpetuals.py | 42 +- coinbase/rest/portfolios.py | 34 +- coinbase/rest/products.py | 22 +- coinbase/rest/public.py | 40 +- coinbase/rest/types/__init__.py | 0 coinbase/rest/types/accounts_types.py | 28 + coinbase/rest/types/base_response.py | 25 + coinbase/rest/types/common_types.py | 876 ++++++++++++++++++++++++ coinbase/rest/types/convert_types.py | 34 + coinbase/rest/types/data_api_types.py | 22 + coinbase/rest/types/fees_types.py | 39 ++ coinbase/rest/types/futures_types.py | 95 +++ coinbase/rest/types/orders_types.py | 184 +++++ coinbase/rest/types/payments_types.py | 25 + coinbase/rest/types/perpetuals_types.py | 74 ++ coinbase/rest/types/portfolios_types.py | 60 ++ coinbase/rest/types/product_types.py | 157 +++++ coinbase/rest/types/public_types.py | 159 +++++ tests/rest/serialize.py | 7 + tests/rest/test_accounts.py | 19 +- tests/rest/test_convert.py | 6 +- tests/rest/test_data_api.py | 2 +- tests/rest/test_fees.py | 2 +- tests/rest/test_futures.py | 18 +- tests/rest/test_market_data.py | 4 +- tests/rest/test_orders.py | 133 ++-- tests/rest/test_payments.py | 4 +- tests/rest/test_perpetuals.py | 12 +- tests/rest/test_portfolios.py | 12 +- tests/rest/test_products.py | 8 +- tests/rest/test_public.py | 16 +- 43 files changed, 2182 insertions(+), 271 deletions(-) create mode 100644 coinbase/rest/types/__init__.py create mode 100644 coinbase/rest/types/accounts_types.py create mode 100644 coinbase/rest/types/base_response.py create mode 100644 coinbase/rest/types/common_types.py create mode 100644 coinbase/rest/types/convert_types.py create mode 100644 coinbase/rest/types/data_api_types.py create mode 100644 coinbase/rest/types/fees_types.py create mode 100644 coinbase/rest/types/futures_types.py create mode 100644 coinbase/rest/types/orders_types.py create mode 100644 coinbase/rest/types/payments_types.py create mode 100644 coinbase/rest/types/perpetuals_types.py create mode 100644 coinbase/rest/types/portfolios_types.py create mode 100644 coinbase/rest/types/product_types.py create mode 100644 coinbase/rest/types/public_types.py create mode 100644 tests/rest/serialize.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 4395d87..2346b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.7.0] - 2024-OCT-16 + +### Added +- Custom response types to REST endpoints +- Dot-notation and auto-completing fields for defined objects + ## [1.6.2] - 2024-SEP-09 ### Added diff --git a/README.md b/README.md index 2573686..c3a390a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Welcome to the official Coinbase Advanced API Python SDK. This python project was created to allow coders to easily plug into the [Coinbase Advanced API](https://docs.cdp.coinbase.com/advanced-trade/docs/welcome). This SDK also supports easy connection to the [Coinbase Advanced Trade WebSocket API](https://docs.cdp.coinbase.com/advanced-trade/docs/ws-overview). +Coinbase Advanced Trade offers a comprehensive API for traders, providing access to real-time market data, order management, and execution. Elevate your trading strategies and develop sophisticated solutions using our powerful tools and features. + For thorough documentation of all available functions, refer to the following link: https://coinbase.github.io/coinbase-advanced-py ___ @@ -80,6 +82,20 @@ However, this will remove the intended safeguard of accidentally placing duplica Refer to the [Advanced API Reference](https://docs.cdp.coinbase.com/advanced-trade/reference) for detailed information on each exposed endpoint. Look in the `coinbase.rest` module to see the API hooks that are exposed. +### Custom Response Objects +Endpoints will return corresponding, custom class objects. This allows you to retrieve response object fields using dot-notation. Here is an example of how you can access a product's price via the Get Product endpoint: +```python +product = client.get_product("BTC-USD") +print(product.price) +``` +Dot-notation is only available for fields that are defined. Although all higher-level fields have been defined, not every nested field has. Fields that are not defined are still accessible using standard bracket notation. + +For example, we make a call to List Accounts. We take the first account from the defined `accounts` field and access the defined `available_balance` field. Despite its nested fields not being explicitly defined and inaccessible via dot-notation, we can still access them manually using bracket notation, like: +```python +accounts = client.get_accounts() +print(accounts.accounts[0].available_balance['value']) +``` + ### Passing in additional parameters Use `kwargs` to pass in any additional parameters. For example: ```python diff --git a/coinbase/__version__.py b/coinbase/__version__.py index 51bbb3f..14d9d2f 100644 --- a/coinbase/__version__.py +++ b/coinbase/__version__.py @@ -1 +1 @@ -__version__ = "1.6.2" +__version__ = "1.7.0" diff --git a/coinbase/rest/__init__.py b/coinbase/rest/__init__.py index bb0ffc6..3bc8f9d 100755 --- a/coinbase/rest/__init__.py +++ b/coinbase/rest/__init__.py @@ -18,7 +18,7 @@ class RESTClient(RESTBase): - **base_url | (str)** - The base URL for REST requests. Default set to "https://api.coinbase.com" - **timeout | Optional (int)** - Set timeout in seconds for REST requests - **verbose | Optional (bool)** - Enables debug logging. Default set to False - + - **rate_limit_headers | Optional (bool)** - Enables rate limit headers. Default set to False """ diff --git a/coinbase/rest/accounts.py b/coinbase/rest/accounts.py index 5b920f2..20f08b0 100644 --- a/coinbase/rest/accounts.py +++ b/coinbase/rest/accounts.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.accounts_types import GetAccountResponse, ListAccountsResponse def get_accounts( @@ -9,7 +10,7 @@ def get_accounts( cursor: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> ListAccountsResponse: """ **List Accounts** _________________ @@ -33,10 +34,10 @@ def get_accounts( "retail_portfolio_id": retail_portfolio_id, } - return self.get(endpoint, params=params, **kwargs) + return ListAccountsResponse(self.get(endpoint, params=params, **kwargs)) -def get_account(self, account_uuid: str, **kwargs) -> Dict[str, Any]: +def get_account(self, account_uuid: str, **kwargs) -> GetAccountResponse: """ **Get Account** @@ -55,4 +56,4 @@ def get_account(self, account_uuid: str, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/accounts/{account_uuid}" - return self.get(endpoint, **kwargs) + return GetAccountResponse(self.get(endpoint, **kwargs)) diff --git a/coinbase/rest/convert.py b/coinbase/rest/convert.py index c7d5fb7..132d9d8 100644 --- a/coinbase/rest/convert.py +++ b/coinbase/rest/convert.py @@ -1,6 +1,11 @@ from typing import Any, Dict, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.convert_types import ( + CommitConvertTradeResponse, + CreateConvertQuoteResponse, + GetConvertTradeResponse, +) def create_convert_quote( @@ -11,7 +16,7 @@ def create_convert_quote( user_incentive_id: Optional[str] = None, code_val: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateConvertQuoteResponse: """ **Create Convert Quote** ________________________ @@ -49,12 +54,12 @@ def create_convert_quote( if filtered_trade_incentive_metadata: data["trade_incentive_metadata"] = filtered_trade_incentive_metadata - return self.post(endpoint, data=data, **kwargs) + return CreateConvertQuoteResponse(self.post(endpoint, data=data, **kwargs)) def get_convert_trade( self, trade_id: str, from_account: str, to_account: str, **kwargs -) -> Dict[str, Any]: +) -> GetConvertTradeResponse: """ **Get Convert Trade** _____________________ @@ -78,12 +83,12 @@ def get_convert_trade( "to_account": to_account, } - return self.get(endpoint, params=params, **kwargs) + return GetConvertTradeResponse(self.get(endpoint, params=params, **kwargs)) def commit_convert_trade( self, trade_id: str, from_account: str, to_account: str, **kwargs -) -> Dict[str, Any]: +) -> CommitConvertTradeResponse: """ **Commit Convert Trade** ________________________ @@ -107,4 +112,4 @@ def commit_convert_trade( "to_account": to_account, } - return self.post(endpoint, data=data, **kwargs) + return CommitConvertTradeResponse(self.post(endpoint, data=data, **kwargs)) diff --git a/coinbase/rest/data_api.py b/coinbase/rest/data_api.py index f669503..a90d71a 100644 --- a/coinbase/rest/data_api.py +++ b/coinbase/rest/data_api.py @@ -1,12 +1,13 @@ from typing import Any, Dict, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.data_api_types import GetAPIKeyPermissionsResponse def get_api_key_permissions( self, **kwargs, -) -> Dict[str, Any]: +) -> GetAPIKeyPermissionsResponse: """ **Get Api Key Permissions** _____________________________ @@ -25,4 +26,4 @@ def get_api_key_permissions( """ endpoint = f"{API_PREFIX}/key_permissions" - return self.get(endpoint, **kwargs) + return GetAPIKeyPermissionsResponse(self.get(endpoint, **kwargs)) diff --git a/coinbase/rest/fees.py b/coinbase/rest/fees.py index 5df8e98..24429ab 100644 --- a/coinbase/rest/fees.py +++ b/coinbase/rest/fees.py @@ -1,6 +1,7 @@ from typing import Any, Dict, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.fees_types import GetTransactionSummaryResponse def get_transaction_summary( @@ -9,7 +10,7 @@ def get_transaction_summary( contract_expiry_type: Optional[str] = None, product_venue: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> GetTransactionSummaryResponse: """ **Get Transactions Summary** _____________________________ @@ -34,4 +35,4 @@ def get_transaction_summary( "product_venue": product_venue, } - return self.get(endpoint, params=params, **kwargs) + return GetTransactionSummaryResponse(self.get(endpoint, params=params, **kwargs)) diff --git a/coinbase/rest/futures.py b/coinbase/rest/futures.py index f74f15c..226b95d 100644 --- a/coinbase/rest/futures.py +++ b/coinbase/rest/futures.py @@ -1,9 +1,20 @@ from typing import Any, Dict, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.futures_types import ( + CancelPendingFuturesSweepResponse, + GetCurrentMarginWindowResponse, + GetFuturesBalanceSummaryResponse, + GetFuturesPositionResponse, + GetIntradayMarginSettingResponse, + ListFuturesPositionsResponse, + ListFuturesSweepsResponse, + ScheduleFuturesSweepResponse, + SetIntradayMarginSettingResponse, +) -def get_futures_balance_summary(self, **kwargs) -> Dict[str, Any]: +def get_futures_balance_summary(self, **kwargs) -> GetFuturesBalanceSummaryResponse: """ **Get Futures Balance Summary** _______________________________ @@ -23,10 +34,10 @@ def get_futures_balance_summary(self, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/cfm/balance_summary" - return self.get(endpoint, **kwargs) + return GetFuturesBalanceSummaryResponse(self.get(endpoint, **kwargs)) -def list_futures_positions(self, **kwargs) -> Dict[str, Any]: +def list_futures_positions(self, **kwargs) -> ListFuturesPositionsResponse: """ **List Futures Positions** __________________________ @@ -46,10 +57,10 @@ def list_futures_positions(self, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/cfm/positions" - return self.get(endpoint, **kwargs) + return ListFuturesPositionsResponse(self.get(endpoint, **kwargs)) -def get_futures_position(self, product_id: str, **kwargs) -> Dict[str, Any]: +def get_futures_position(self, product_id: str, **kwargs) -> GetFuturesPositionResponse: """ **Get Futures Position** _________________________ @@ -69,10 +80,12 @@ def get_futures_position(self, product_id: str, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/cfm/positions/{product_id}" - return self.get(endpoint, **kwargs) + return GetFuturesPositionResponse(self.get(endpoint, **kwargs)) -def schedule_futures_sweep(self, usd_amount: str, **kwargs) -> Dict[str, Any]: +def schedule_futures_sweep( + self, usd_amount: str, **kwargs +) -> ScheduleFuturesSweepResponse: """ **Schedule Futures Sweep** __________________________ @@ -94,10 +107,10 @@ def schedule_futures_sweep(self, usd_amount: str, **kwargs) -> Dict[str, Any]: data = {"usd_amount": usd_amount} - return self.post(endpoint, data=data, **kwargs) + return ScheduleFuturesSweepResponse(self.post(endpoint, data=data, **kwargs)) -def list_futures_sweeps(self, **kwargs) -> Dict[str, Any]: +def list_futures_sweeps(self, **kwargs) -> ListFuturesSweepsResponse: """ **List Futures Sweeps** _______________________ @@ -117,10 +130,10 @@ def list_futures_sweeps(self, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/cfm/sweeps" - return self.get(endpoint, **kwargs) + return ListFuturesSweepsResponse(self.get(endpoint, **kwargs)) -def cancel_pending_futures_sweep(self, **kwargs) -> Dict[str, Any]: +def cancel_pending_futures_sweep(self, **kwargs) -> CancelPendingFuturesSweepResponse: """ **Cancel Pending Futures Sweep** ________________________________ @@ -140,10 +153,10 @@ def cancel_pending_futures_sweep(self, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/cfm/sweeps" - return self.delete(endpoint, **kwargs) + return CancelPendingFuturesSweepResponse(self.delete(endpoint, **kwargs)) -def get_intraday_margin_setting(self, **kwargs) -> Dict[str, Any]: +def get_intraday_margin_setting(self, **kwargs) -> GetIntradayMarginSettingResponse: """ **Get Intraday Margin Setting** _______________________________ @@ -163,12 +176,12 @@ def get_intraday_margin_setting(self, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/cfm/intraday/margin_setting" - return self.get(endpoint, **kwargs) + return GetIntradayMarginSettingResponse(self.get(endpoint, **kwargs)) def get_current_margin_window( self, margin_profile_type: str, **kwargs -) -> Dict[str, Any]: +) -> GetCurrentMarginWindowResponse: """ **Get Current Margin Window** ________________________________ @@ -191,10 +204,12 @@ def get_current_margin_window( params = {"margin_profile_type": margin_profile_type} - return self.get(endpoint, params=params, **kwargs) + return GetCurrentMarginWindowResponse(self.get(endpoint, params=params, **kwargs)) -def set_intraday_margin_setting(self, setting: str, **kwargs) -> Dict[str, Any]: +def set_intraday_margin_setting( + self, setting: str, **kwargs +) -> SetIntradayMarginSettingResponse: """ **Set Intraday Margin Setting** ________________________________ @@ -217,4 +232,4 @@ def set_intraday_margin_setting(self, setting: str, **kwargs) -> Dict[str, Any]: data = {"setting": setting} - return self.post(endpoint, data=data, **kwargs) + return SetIntradayMarginSettingResponse(self.post(endpoint, data=data, **kwargs)) diff --git a/coinbase/rest/market_data.py b/coinbase/rest/market_data.py index 319680b..7ced523 100644 --- a/coinbase/rest/market_data.py +++ b/coinbase/rest/market_data.py @@ -1,6 +1,10 @@ from typing import Any, Dict, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.product_types import ( + GetMarketTradesResponse, + GetProductCandlesResponse, +) def get_candles( @@ -11,7 +15,7 @@ def get_candles( granularity: str, limit: Optional[int] = None, **kwargs, -) -> Dict[str, Any]: +) -> GetProductCandlesResponse: """ **Get Product Candles** __________ @@ -33,7 +37,7 @@ def get_candles( params = {"start": start, "end": end, "granularity": granularity, "limit": limit} - return self.get(endpoint, params=params, **kwargs) + return GetProductCandlesResponse(self.get(endpoint, params=params, **kwargs)) def get_market_trades( @@ -43,7 +47,7 @@ def get_market_trades( start: Optional[str] = None, end: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> GetMarketTradesResponse: """ **Get Market Trades** _____________________ @@ -65,4 +69,4 @@ def get_market_trades( params = {"limit": limit, "start": start, "end": end} - return self.get(endpoint, params=params, **kwargs) + return GetMarketTradesResponse(self.get(endpoint, params=params, **kwargs)) diff --git a/coinbase/rest/orders.py b/coinbase/rest/orders.py index b9e2f57..7245215 100644 --- a/coinbase/rest/orders.py +++ b/coinbase/rest/orders.py @@ -2,6 +2,17 @@ from typing import Any, Dict, List, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.orders_types import ( + CancelOrdersResponse, + ClosePositionResponse, + CreateOrderResponse, + EditOrderPreviewResponse, + EditOrderResponse, + GetOrderResponse, + ListFillsResponse, + ListOrdersResponse, + PreviewOrderResponse, +) def generate_client_order_id() -> str: @@ -22,7 +33,7 @@ def create_order( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Create Order** ________________ @@ -56,7 +67,7 @@ def create_order( "retail_portfolio_id": retail_portfolio_id, } - return self.post(endpoint, data=data, **kwargs) + return CreateOrderResponse(self.post(endpoint, data=data, **kwargs)) # Market orders @@ -72,7 +83,7 @@ def market_order( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Market Order** ________________ @@ -124,7 +135,7 @@ def market_order_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Create Market Order Buy** ____________________ @@ -167,7 +178,7 @@ def market_order_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Create Market Order Sell** _____________________ @@ -212,7 +223,7 @@ def limit_order_ioc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit IOC Order** ________________ @@ -261,7 +272,7 @@ def limit_order_ioc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit IOC Order Buy** ________________ @@ -307,7 +318,7 @@ def limit_order_ioc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit IOC Order Sell** ________________ @@ -356,7 +367,7 @@ def limit_order_gtc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit Order GTC** ___________________ @@ -409,7 +420,7 @@ def limit_order_gtc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit Order GTC Buy** _______________________ @@ -456,7 +467,7 @@ def limit_order_gtc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit Order GTC Sell** ________________________ @@ -506,7 +517,7 @@ def limit_order_gtd( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit Order GTD** ___________________ @@ -561,7 +572,7 @@ def limit_order_gtd_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit Order GTD Buy** _______________________ @@ -610,7 +621,7 @@ def limit_order_gtd_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit Order GTD Sell** ________________________ @@ -659,7 +670,7 @@ def limit_order_fok( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit FOK Order** ________________ @@ -708,7 +719,7 @@ def limit_order_fok_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit FOK Order Buy** ________________ @@ -754,7 +765,7 @@ def limit_order_fok_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Limit FOK Order Sell** ________________ @@ -804,7 +815,7 @@ def stop_limit_order_gtc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Stop-Limit Order GTC** ________________________ @@ -859,7 +870,7 @@ def stop_limit_order_gtc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Stop-Limit Order GTC Buy** ____________________________ @@ -908,7 +919,7 @@ def stop_limit_order_gtc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Stop-Limit Order GTC Sell** _____________________________ @@ -960,7 +971,7 @@ def stop_limit_order_gtd( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Stop-Limit Order GTD** ________________________ @@ -1017,7 +1028,7 @@ def stop_limit_order_gtd_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Stop-Limit Order GTD Buy** ____________________________ @@ -1068,7 +1079,7 @@ def stop_limit_order_gtd_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Stop-Limit Order GTD Sell** _____________________________ @@ -1119,7 +1130,7 @@ def trigger_bracket_order_gtc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Trigger Bracket Order GTC** ________________________ @@ -1172,7 +1183,7 @@ def trigger_bracket_order_gtc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Trigger Bracket Order GTC Buy** ____________________________ @@ -1219,7 +1230,7 @@ def trigger_bracket_order_gtc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Trigger Bracket Order GTC Sell** _____________________________ @@ -1269,7 +1280,7 @@ def trigger_bracket_order_gtd( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Trigger Bracket Order GTD** ________________________ @@ -1324,7 +1335,7 @@ def trigger_bracket_order_gtd_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Trigger Bracket Order GTD Buy** ____________________________ @@ -1373,7 +1384,7 @@ def trigger_bracket_order_gtd_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> CreateOrderResponse: """ **Trigger Bracket Order GTD Sell** _____________________________ @@ -1409,7 +1420,7 @@ def trigger_bracket_order_gtd_sell( ) -def get_order(self, order_id: str, **kwargs) -> Dict[str, Any]: +def get_order(self, order_id: str, **kwargs) -> GetOrderResponse: """ **Get Order** _____________ @@ -1429,7 +1440,7 @@ def get_order(self, order_id: str, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/orders/historical/{order_id}" - return self.get(endpoint, **kwargs) + return GetOrderResponse(self.get(endpoint, **kwargs)) def list_orders( @@ -1451,7 +1462,7 @@ def list_orders( time_in_forces: Optional[str] = None, sort_by: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> ListOrdersResponse: """ **List Orders** _______________ @@ -1489,7 +1500,7 @@ def list_orders( "sort_by": sort_by, } - return self.get(endpoint, params=params, **kwargs) + return ListOrdersResponse(self.get(endpoint, params=params, **kwargs)) def get_fills( @@ -1504,7 +1515,7 @@ def get_fills( cursor: Optional[str] = None, sort_by: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> ListFillsResponse: """ **List Fills** ______________ @@ -1535,7 +1546,7 @@ def get_fills( "sort_by": sort_by, } - return self.get(endpoint, params=params, **kwargs) + return ListFillsResponse(self.get(endpoint, params=params, **kwargs)) def edit_order( @@ -1544,7 +1555,7 @@ def edit_order( size: Optional[str] = None, price: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> EditOrderResponse: """ **Edit Order** ______________ @@ -1569,7 +1580,7 @@ def edit_order( "price": price, } - return self.post(endpoint, data=data, **kwargs) + return EditOrderResponse(self.post(endpoint, data=data, **kwargs)) def preview_edit_order( @@ -1578,7 +1589,7 @@ def preview_edit_order( size: Optional[str] = None, price: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> EditOrderPreviewResponse: """ **Preview Edit Order** ______________________ @@ -1603,10 +1614,10 @@ def preview_edit_order( "price": price, } - return self.post(endpoint, data=data, **kwargs) + return EditOrderPreviewResponse(self.post(endpoint, data=data, **kwargs)) -def cancel_orders(self, order_ids: List[str], **kwargs) -> Dict[str, Any]: +def cancel_orders(self, order_ids: List[str], **kwargs) -> CancelOrdersResponse: """ **Cancel Orders** _________________ @@ -1629,7 +1640,7 @@ def cancel_orders(self, order_ids: List[str], **kwargs) -> Dict[str, Any]: "order_ids": order_ids, } - return self.post(endpoint, data=data, **kwargs) + return CancelOrdersResponse(self.post(endpoint, data=data, **kwargs)) def preview_order( @@ -1641,7 +1652,7 @@ def preview_order( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Order** _________________ @@ -1670,7 +1681,7 @@ def preview_order( "retail_portfolio_id": retail_portfolio_id, } - return self.post(endpoint, data=data, **kwargs) + return PreviewOrderResponse(self.post(endpoint, data=data, **kwargs)) # Preview market orders @@ -1684,7 +1695,7 @@ def preview_market_order( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Market Order** ________________________ @@ -1731,7 +1742,7 @@ def preview_market_order_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Market Buy Order** ____________________________ @@ -1770,7 +1781,7 @@ def preview_market_order_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Market Sell Order** _____________________________ @@ -1811,7 +1822,7 @@ def preview_limit_order_ioc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order IOC** ___________________________ @@ -1854,7 +1865,7 @@ def preview_limit_order_ioc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order IOC Buy** ___________________________ @@ -1894,7 +1905,7 @@ def preview_limit_order_ioc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order IOC Sell** ___________________________ @@ -1937,7 +1948,7 @@ def preview_limit_order_gtc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order GTC** ___________________________ @@ -1985,7 +1996,7 @@ def preview_limit_order_gtc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order GTC Buy** _______________________________ @@ -2027,7 +2038,7 @@ def preview_limit_order_gtc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order GTC Sell** ________________________________ @@ -2072,7 +2083,7 @@ def preview_limit_order_gtd( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order GTD** ___________________________ @@ -2122,7 +2133,7 @@ def preview_limit_order_gtd_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order GTD Buy** _______________________________ @@ -2166,7 +2177,7 @@ def preview_limit_order_gtd_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order GTD Sell** ________________________________ @@ -2209,7 +2220,7 @@ def preview_limit_order_fok( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order FOK** ___________________________ @@ -2252,7 +2263,7 @@ def preview_limit_order_fok_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order FOK Buy** ___________________________ @@ -2292,7 +2303,7 @@ def preview_limit_order_fok_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Limit Order FOK Sell** ___________________________ @@ -2336,7 +2347,7 @@ def preview_stop_limit_order_gtc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Stop-Limit Order GTC** ________________________________ @@ -2386,7 +2397,7 @@ def preview_stop_limit_order_gtc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Stop-Limit Order GTC Buy** ____________________________________ @@ -2430,7 +2441,7 @@ def preview_stop_limit_order_gtc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Stop-Limit Order GTC Sell** _____________________________________ @@ -2477,7 +2488,7 @@ def preview_stop_limit_order_gtd( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Stop-Limit Order GTD** ________________________________ @@ -2529,7 +2540,7 @@ def preview_stop_limit_order_gtd_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Stop-Limit Order GTD Buy** ____________________________________ @@ -2575,7 +2586,7 @@ def preview_stop_limit_order_gtd_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Stop-Limit Order GTD Sell** _____________________________________ @@ -2621,7 +2632,7 @@ def preview_trigger_bracket_order_gtc( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Trigger Bracket Order GTC** ________________________________ @@ -2669,7 +2680,7 @@ def preview_trigger_bracket_order_gtc_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Trigger Bracket Order GTC Buy** ____________________________________ @@ -2711,7 +2722,7 @@ def preview_trigger_bracket_order_gtc_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Trigger Bracket Order GTC Sell** _____________________________________ @@ -2756,7 +2767,7 @@ def preview_trigger_bracket_order_gtd( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Trigger Bracket Order GTD** ________________________________ @@ -2806,7 +2817,7 @@ def preview_trigger_bracket_order_gtd_buy( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Trigger Bracket Order GTD Buy** ____________________________________ @@ -2850,7 +2861,7 @@ def preview_trigger_bracket_order_gtd_sell( margin_type: Optional[str] = None, retail_portfolio_id: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> PreviewOrderResponse: """ **Preview Trigger Bracket Order GTD Sell** _____________________________________ @@ -2885,7 +2896,7 @@ def preview_trigger_bracket_order_gtd_sell( def close_position( self, client_order_id: str, product_id: str, size: Optional[str] = None, **kwargs -) -> Dict[str, Any]: +) -> ClosePositionResponse: """ **Close Position** _________________ @@ -2910,4 +2921,4 @@ def close_position( data = {"client_order_id": client_order_id, "product_id": product_id, "size": size} - return self.post(endpoint, data=data, **kwargs) + return ClosePositionResponse(self.post(endpoint, data=data, **kwargs)) diff --git a/coinbase/rest/payments.py b/coinbase/rest/payments.py index f4b8b95..ea31047 100644 --- a/coinbase/rest/payments.py +++ b/coinbase/rest/payments.py @@ -1,9 +1,13 @@ from typing import Any, Dict from coinbase.constants import API_PREFIX +from coinbase.rest.types.payments_types import ( + GetPaymentMethodResponse, + ListPaymentMethodsResponse, +) -def list_payment_methods(self, **kwargs) -> Dict[str, Any]: +def list_payment_methods(self, **kwargs) -> ListPaymentMethodsResponse: """ **List Payment Methods** _________________ @@ -22,10 +26,12 @@ def list_payment_methods(self, **kwargs) -> Dict[str, Any]: endpoint = f"{API_PREFIX}/payment_methods" - return self.get(endpoint, **kwargs) + return ListPaymentMethodsResponse(self.get(endpoint, **kwargs)) -def get_payment_method(self, payment_method_id: str, **kwargs) -> Dict[str, Any]: +def get_payment_method( + self, payment_method_id: str, **kwargs +) -> GetPaymentMethodResponse: """ **Get Payment Method** _________________ @@ -44,4 +50,4 @@ def get_payment_method(self, payment_method_id: str, **kwargs) -> Dict[str, Any] endpoint = f"{API_PREFIX}/payment_methods/{payment_method_id}" - return self.get(endpoint, **kwargs) + return GetPaymentMethodResponse(self.get(endpoint, **kwargs)) diff --git a/coinbase/rest/perpetuals.py b/coinbase/rest/perpetuals.py index bb1c907..5ba1c5c 100644 --- a/coinbase/rest/perpetuals.py +++ b/coinbase/rest/perpetuals.py @@ -1,11 +1,17 @@ -from typing import Any, Dict, Optional - from coinbase.constants import API_PREFIX +from coinbase.rest.types.perpetuals_types import ( + AllocatePortfolioResponse, + GetPerpetualsPortfolioSummaryResponse, + GetPerpetualsPositionResponse, + GetPortfolioBalancesResponse, + ListPerpetualsPositionsResponse, + OptInOutMultiAssetCollateralResponse, +) def allocate_portfolio( self, portfolio_uuid: str, symbol: str, amount: str, currency: str, **kwargs -) -> Dict[str, Any]: +) -> AllocatePortfolioResponse: """ **Allocate Portfolio** ________________ @@ -33,10 +39,12 @@ def allocate_portfolio( "currency": currency, } - return self.post(endpoint, data=data, **kwargs) + return AllocatePortfolioResponse(self.post(endpoint, data=data, **kwargs)) -def get_perps_portfolio_summary(self, portfolio_uuid: str, **kwargs) -> Dict[str, Any]: +def get_perps_portfolio_summary( + self, portfolio_uuid: str, **kwargs +) -> GetPerpetualsPortfolioSummaryResponse: """ **Get Perpetuals Portfolio Summary** ________________ @@ -56,10 +64,12 @@ def get_perps_portfolio_summary(self, portfolio_uuid: str, **kwargs) -> Dict[str """ endpoint = f"{API_PREFIX}/intx/portfolio/{portfolio_uuid}" - return self.get(endpoint, **kwargs) + return GetPerpetualsPortfolioSummaryResponse(self.get(endpoint, **kwargs)) -def list_perps_positions(self, portfolio_uuid: str, **kwargs) -> Dict[str, Any]: +def list_perps_positions( + self, portfolio_uuid: str, **kwargs +) -> ListPerpetualsPositionsResponse: """ **List Perpetuals Positions** ________________ @@ -79,12 +89,12 @@ def list_perps_positions(self, portfolio_uuid: str, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/intx/positions/{portfolio_uuid}" - return self.get(endpoint, **kwargs) + return ListPerpetualsPositionsResponse(self.get(endpoint, **kwargs)) def get_perps_position( self, portfolio_uuid: str, symbol: str, **kwargs -) -> Dict[str, Any]: +) -> GetPerpetualsPositionResponse: """ **Get Perpetuals Position** ________________ @@ -104,10 +114,12 @@ def get_perps_position( """ endpoint = f"{API_PREFIX}/intx/positions/{portfolio_uuid}/{symbol}" - return self.get(endpoint, **kwargs) + return GetPerpetualsPositionResponse(self.get(endpoint, **kwargs)) -def get_perps_portfolio_balances(self, portfolio_uuid: str, **kwargs) -> Dict[str, Any]: +def get_perps_portfolio_balances( + self, portfolio_uuid: str, **kwargs +) -> GetPortfolioBalancesResponse: """ **Get Portfolio Balances** ________________ @@ -127,12 +139,12 @@ def get_perps_portfolio_balances(self, portfolio_uuid: str, **kwargs) -> Dict[st """ endpoint = f"{API_PREFIX}/intx/balances/{portfolio_uuid}" - return self.get(endpoint, **kwargs) + return GetPortfolioBalancesResponse(self.get(endpoint, **kwargs)) def opt_in_or_out_multi_asset_collateral( self, portfolio_uuid: str, multi_asset_collateral_enabled: bool, **kwargs -) -> Dict[str, Any]: +) -> OptInOutMultiAssetCollateralResponse: """ **Opt In or Out of Multi Asset Collateral** ________________ @@ -158,4 +170,6 @@ def opt_in_or_out_multi_asset_collateral( "multi_asset_collateral_enabled": multi_asset_collateral_enabled, } - return self.post(endpoint, data=data, **kwargs) + return OptInOutMultiAssetCollateralResponse( + self.post(endpoint, data=data, **kwargs) + ) diff --git a/coinbase/rest/portfolios.py b/coinbase/rest/portfolios.py index e53f734..09c56ef 100644 --- a/coinbase/rest/portfolios.py +++ b/coinbase/rest/portfolios.py @@ -1,11 +1,19 @@ from typing import Any, Dict, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.portfolios_types import ( + CreatePortfolioResponse, + DeletePortfolioResponse, + EditPortfolioResponse, + GetPortfolioBreakdownResponse, + ListPortfoliosResponse, + MovePortfolioFundsResponse, +) def get_portfolios( self, portfolio_type: Optional[str] = None, **kwargs -) -> Dict[str, Any]: +) -> ListPortfoliosResponse: """ **List Portfolios** ___________________ @@ -27,10 +35,10 @@ def get_portfolios( params = {"portfolio_type": portfolio_type} - return self.get(endpoint, params=params, **kwargs) + return ListPortfoliosResponse(self.get(endpoint, params=params, **kwargs)) -def create_portfolio(self, name: str, **kwargs) -> Dict[str, Any]: +def create_portfolio(self, name: str, **kwargs) -> CreatePortfolioResponse: """ **Create Portfolio** ____________________ @@ -54,12 +62,12 @@ def create_portfolio(self, name: str, **kwargs) -> Dict[str, Any]: "name": name, } - return self.post(endpoint, data=data, **kwargs) + return CreatePortfolioResponse(self.post(endpoint, data=data, **kwargs)) def get_portfolio_breakdown( self, portfolio_uuid: str, currency: Optional[str] = None, **kwargs -) -> Dict[str, Any]: +) -> GetPortfolioBreakdownResponse: """ **Get Portfolio Breakdown** ___________________________ @@ -80,7 +88,7 @@ def get_portfolio_breakdown( endpoint = f"{API_PREFIX}/portfolios/{portfolio_uuid}" params = {"currency": currency} - return self.get(endpoint, params=params, **kwargs) + return GetPortfolioBreakdownResponse(self.get(endpoint, params=params, **kwargs)) def move_portfolio_funds( @@ -90,7 +98,7 @@ def move_portfolio_funds( source_portfolio_uuid: str, target_portfolio_uuid: str, **kwargs, -) -> Dict[str, Any]: +) -> MovePortfolioFundsResponse: """ **Move Portfolio Funds** ________________________ @@ -119,10 +127,12 @@ def move_portfolio_funds( "target_portfolio_uuid": target_portfolio_uuid, } - return self.post(endpoint, data=data, **kwargs) + return MovePortfolioFundsResponse(self.post(endpoint, data=data, **kwargs)) -def edit_portfolio(self, portfolio_uuid: str, name: str, **kwargs) -> Dict[str, Any]: +def edit_portfolio( + self, portfolio_uuid: str, name: str, **kwargs +) -> EditPortfolioResponse: """ **Edit Portfolio** __________________ @@ -146,10 +156,10 @@ def edit_portfolio(self, portfolio_uuid: str, name: str, **kwargs) -> Dict[str, "name": name, } - return self.put(endpoint, data=data, **kwargs) + return EditPortfolioResponse(self.put(endpoint, data=data, **kwargs)) -def delete_portfolio(self, portfolio_uuid: str, **kwargs) -> Dict[str, Any]: +def delete_portfolio(self, portfolio_uuid: str, **kwargs) -> DeletePortfolioResponse: """ **Delete Portfolio** ____________________ @@ -169,4 +179,4 @@ def delete_portfolio(self, portfolio_uuid: str, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/portfolios/{portfolio_uuid}" - return self.delete(endpoint, **kwargs) + return DeletePortfolioResponse(self.delete(endpoint, **kwargs)) diff --git a/coinbase/rest/products.py b/coinbase/rest/products.py index b2a43d8..0a0c7b6 100644 --- a/coinbase/rest/products.py +++ b/coinbase/rest/products.py @@ -1,6 +1,12 @@ from typing import Any, Dict, List, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.product_types import ( + GetBestBidAskResponse, + GetProductBookResponse, + GetProductResponse, + ListProductsResponse, +) def get_products( @@ -14,7 +20,7 @@ def get_products( get_tradability_status: Optional[bool] = False, get_all_products: Optional[bool] = False, **kwargs, -) -> Dict[str, Any]: +) -> ListProductsResponse: """ **List Products** _________________ @@ -45,12 +51,12 @@ def get_products( "get_all_products": get_all_products, } - return self.get(endpoint, params=params, **kwargs) + return ListProductsResponse(self.get(endpoint, params=params, **kwargs)) def get_product( self, product_id: str, get_tradability_status: Optional[bool] = False, **kwargs -) -> Dict[str, Any]: +) -> GetProductResponse: """ **Get Product** _______________ @@ -74,7 +80,7 @@ def get_product( "get_tradability_status": get_tradability_status, } - return self.get(endpoint, params=params, **kwargs) + return GetProductResponse(self.get(endpoint, params=params, **kwargs)) def get_product_book( @@ -83,7 +89,7 @@ def get_product_book( limit: Optional[int] = None, aggregation_price_increment: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> GetProductBookResponse: """ **Get Product Book** ____________________ @@ -109,12 +115,12 @@ def get_product_book( "aggregation_price_increment": aggregation_price_increment, } - return self.get(endpoint, params=params, **kwargs) + return GetProductBookResponse(self.get(endpoint, params=params, **kwargs)) def get_best_bid_ask( self, product_ids: Optional[List[str]] = None, **kwargs -) -> Dict[str, Any]: +) -> GetBestBidAskResponse: """ **Get Best Bid/Ask** ____________________ @@ -138,4 +144,4 @@ def get_best_bid_ask( "product_ids": product_ids, } - return self.get(endpoint, params=params, **kwargs) + return GetBestBidAskResponse(self.get(endpoint, params=params, **kwargs)) diff --git a/coinbase/rest/public.py b/coinbase/rest/public.py index ab8f9c4..0a62996 100644 --- a/coinbase/rest/public.py +++ b/coinbase/rest/public.py @@ -1,9 +1,17 @@ from typing import Any, Dict, List, Optional from coinbase.constants import API_PREFIX +from coinbase.rest.types.public_types import ( + GetPublicMarketTradesResponse, + GetPublicProductBookResponse, + GetPublicProductCandlesResponse, + GetPublicProductResponse, + GetServerTimeResponse, + ListPublicProductsResponse, +) -def get_unix_time(self, **kwargs) -> Dict[str, Any]: +def get_unix_time(self, **kwargs) -> GetServerTimeResponse: """ **Get Server Time** _________________ @@ -22,7 +30,7 @@ def get_unix_time(self, **kwargs) -> Dict[str, Any]: endpoint = f"{API_PREFIX}/time" - return self.get(endpoint, public=True, **kwargs) + return GetServerTimeResponse(self.get(endpoint, public=True, **kwargs)) def get_public_product_book( @@ -31,7 +39,7 @@ def get_public_product_book( limit: Optional[int] = None, aggregation_price_increment: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> GetPublicProductBookResponse: """ **Get Public Product Book** _________________ @@ -62,7 +70,9 @@ def get_public_product_book( "aggregation_price_increment": aggregation_price_increment, } - return self.get(endpoint, params=params, public=True, **kwargs) + return GetPublicProductBookResponse( + self.get(endpoint, params=params, public=True, **kwargs) + ) def get_public_products( @@ -75,7 +85,7 @@ def get_public_products( expiring_contract_status: Optional[str] = None, get_all_products: bool = False, **kwargs, -) -> Dict[str, Any]: +) -> ListPublicProductsResponse: """ **List Public Products** _________________ @@ -111,10 +121,12 @@ def get_public_products( "get_all_products": get_all_products, } - return self.get(endpoint, params=params, public=True, **kwargs) + return ListPublicProductsResponse( + self.get(endpoint, params=params, public=True, **kwargs) + ) -def get_public_product(self, product_id: str, **kwargs) -> Dict[str, Any]: +def get_public_product(self, product_id: str, **kwargs) -> GetPublicProductResponse: """ **Public Get Product** _______________ @@ -140,7 +152,7 @@ def get_public_product(self, product_id: str, **kwargs) -> Dict[str, Any]: """ endpoint = f"{API_PREFIX}/market/products/{product_id}" - return self.get(endpoint, public=True, **kwargs) + return GetPublicProductResponse(self.get(endpoint, public=True, **kwargs)) def get_public_candles( @@ -151,7 +163,7 @@ def get_public_candles( granularity: str, limit: Optional[int] = None, **kwargs, -) -> Dict[str, Any]: +) -> GetPublicProductCandlesResponse: """ **Get Public Product Candles** __________ @@ -179,7 +191,9 @@ def get_public_candles( params = {"start": start, "end": end, "granularity": granularity, "limit": limit} - return self.get(endpoint, params=params, public=True, **kwargs) + return GetPublicProductCandlesResponse( + self.get(endpoint, params=params, public=True, **kwargs) + ) def get_public_market_trades( @@ -189,7 +203,7 @@ def get_public_market_trades( start: Optional[str] = None, end: Optional[str] = None, **kwargs, -) -> Dict[str, Any]: +) -> GetPublicMarketTradesResponse: """ **Get Public Market Trades** _____________________ @@ -217,4 +231,6 @@ def get_public_market_trades( params = {"limit": limit, "start": start, "end": end} - return self.get(endpoint, params=params, public=True, **kwargs) + return GetPublicMarketTradesResponse( + self.get(endpoint, params=params, public=True, **kwargs) + ) diff --git a/coinbase/rest/types/__init__.py b/coinbase/rest/types/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/coinbase/rest/types/accounts_types.py b/coinbase/rest/types/accounts_types.py new file mode 100644 index 0000000..ad4485b --- /dev/null +++ b/coinbase/rest/types/accounts_types.py @@ -0,0 +1,28 @@ +from typing import List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import Account + + +# Get Account +class GetAccountResponse(BaseResponse): + def __init__(self, response: dict): + if "account" in response: + self.account: Optional[Account] = Account(**(response.pop("account"))) + super().__init__(**response) + + +# List Accounts +class ListAccountsResponse(BaseResponse): + def __init__(self, response: dict): + if "accounts" in response: + self.accounts: Optional[List[Account]] = [ + Account(**account) for account in response.pop("accounts") + ] + if "has_next" in response: + self.has_next: Optional[bool] = response.pop("has_next") + if "cursor" in response: + self.cursor: Optional[str] = response.pop("cursor") + if "size" in response: + self.size: Optional[int] = response.pop("size") + super().__init__(**response) diff --git a/coinbase/rest/types/base_response.py b/coinbase/rest/types/base_response.py new file mode 100644 index 0000000..7242782 --- /dev/null +++ b/coinbase/rest/types/base_response.py @@ -0,0 +1,25 @@ +from typing import Any + +common_fields = { + "x-ratelimit-remaining": "rate_limit_remaining", + "x-ratelimit-reset": "rate_limit_reset", + "x-ratelimit-limit": "rate_limit_limit", +} + + +class BaseResponse: + def __init__(self, **kwargs): + for field in list(kwargs.keys()): + attr_name = field.replace("-", "_") + + if field in kwargs: + setattr(self, attr_name, kwargs.pop(field)) + + for key in list(kwargs.keys()): + setattr(self, key, kwargs.pop(key)) + + def __getitem__(self, key: str) -> Any: + return self.__dict__.get(key) + + def __repr__(self): + return str(self.__dict__) diff --git a/coinbase/rest/types/common_types.py b/coinbase/rest/types/common_types.py new file mode 100644 index 0000000..f8da529 --- /dev/null +++ b/coinbase/rest/types/common_types.py @@ -0,0 +1,876 @@ +from enum import Enum +from typing import Any, Dict, List, Optional + +from coinbase.rest.types.base_response import BaseResponse + + +class ProductVenue(Enum): + UNKNOWN = "UNKNOWN_VENUE_TYPE" + CBE = "CBE" + FCM = "FCM" + INTX = "INTX" + + +class StopDirection(Enum): + UP = "UP" + DOWN = "DOWN" + + +class MarginType(Enum): + CROSS = "CROSS" + ISOLATED = "ISOLATED" + + +class OrderPlacementSource(Enum): + UNKNOWN = "UNKNOWN_PLACEMENT_SOURCE" + RETAIL_SIMPLE = "RETAIL_SIMPLE" + RETAIL_ADVANCED = "RETAIL_ADVANCED" + + +class ProductType(Enum): + UNKNOWN = "UNKNOWN_PRODUCT_TYPE" + SPOT = "SPOT" + FUTURE = "FUTURE" + + +class OrderSide(Enum): + BUY = "BUY" + SELL = "SELL" + + +class PortfolioType(Enum): + UNDEFINED = "UNDEFINED" + DEFAULT = "DEFAULT" + CONSUMER = "CONSUMER" + INTX = "INTX" + + +class IntradayMarginSetting(Enum): + UNSPECIFIED = "INTRADAY_MARGIN_SETTING_UNSPECIFIED" + STANDARD = "INTRADAY_MARGIN_SETTING_STANDARD" + INTRADAY = "INTRADAY_MARGIN_SETTING_INTRADAY" + + +class Account(BaseResponse): + def __init__(self, **kwargs): + if "uuid" in kwargs: + self.uuid: Optional[str] = kwargs.pop("uuid") + if "name" in kwargs: + self.name: Optional[str] = kwargs.pop("name") + if "currency" in kwargs: + self.currency: Optional[str] = kwargs.pop("currency") + if "available_balance" in kwargs: + self.available_balance: Optional[Dict[str, Any]] = kwargs.pop( + "available_balance" + ) + if "default" in kwargs: + self.default: Optional[bool] = kwargs.pop("default") + if "active" in kwargs: + self.active: Optional[bool] = kwargs.pop("active") + if "created_at" in kwargs: + self.created_at: Optional[str] = kwargs.pop("created_at") + if "updated_at" in kwargs: + self.updated_at: Optional[str] = kwargs.pop("updated_at") + if "deleted_at" in kwargs: + self.deleted_at: Optional[str] = kwargs.pop("deleted_at") + if "type" in kwargs: + self.type: Optional[Dict[str, Any]] = kwargs.pop("type") + if "ready" in kwargs: + self.ready: Optional[bool] = kwargs.pop("ready") + if "hold" in kwargs: + self.hold: Optional[Dict[str, Any]] = kwargs.pop("hold") + if "retail_portfolio_id" in kwargs: + self.retail_portfolio_id: Optional[str] = kwargs.pop("retail_portfolio_id") + super().__init__(**kwargs) + + +class RatConvertTrade(BaseResponse): + def __init__(self, **kwargs): + if "id" in kwargs: + self.id: Optional[str] = kwargs.pop("id") + if "status" in kwargs: + self.status: Optional[Dict[str, Any]] = kwargs.pop("status") + if "user_entered_amount" in kwargs: + self.user_entered_amount: Optional[Dict[str, Any]] = kwargs.pop( + "user_entered_amount" + ) + if "amount" in kwargs: + self.amount: Optional[Dict[str, Any]] = kwargs.pop("amount") + if "subtotal" in kwargs: + self.subtotal: Optional[Dict[str, Any]] = kwargs.pop("subtotal") + if "total" in kwargs: + self.total: Optional[Dict[str, Any]] = kwargs.pop("total") + if "fees" in kwargs: + self.fees: Optional[Dict[str, Any]] = kwargs.pop("fees") + if "total_fee" in kwargs: + self.total_fee: Optional[Dict[str, Any]] = kwargs.pop("total_fee") + if "source" in kwargs: + self.source: Optional[Dict[str, Any]] = kwargs.pop("source") + if "target" in kwargs: + self.target: Optional[Dict[str, Any]] = kwargs.pop("target") + if "unit_price" in kwargs: + self.unit_price: Optional[Dict[str, Any]] = kwargs.pop("unit_price") + if "user_warnings" in kwargs: + self.user_warnings: Optional[Dict[str, Any]] = kwargs.pop("user_warnings") + if "user_reference" in kwargs: + self.user_reference: Optional[str] = kwargs.pop("user_reference") + if "source_curency" in kwargs: + self.source_curency: Optional[str] = kwargs.pop("source_curency") + if "cancellation_reason" in kwargs: + self.cancellation_reason: Optional[Dict[str, Any]] = kwargs.pop( + "cancellation_reason" + ) + if "source_id" in kwargs: + self.source_id: Optional[str] = kwargs.pop("source_id") + if "target_id" in kwargs: + self.target_id: Optional[str] = kwargs.pop("target_id") + if "subscription_info" in kwargs: + self.subscription_info: Optional[Dict[str, Any]] = kwargs.pop( + "subscription_info" + ) + if "exchange_rate" in kwargs: + self.exchange_rate: Optional[Dict[str, Any]] = kwargs.pop("exchange_rate") + if "tax_details" in kwargs: + self.tax_details: Optional[Dict[str, Any]] = kwargs.pop("tax_details") + if "trade_incentive_info" in kwargs: + self.trade_incentive_info: Optional[Dict[str, Any]] = kwargs.pop( + "trade_incentive_info" + ) + if "total_fee_without_tax" in kwargs: + self.total_fee_without_tax: Optional[Dict[str, Any]] = kwargs.pop( + "total_fee_without_tax" + ) + if "fiat_denoted_total" in kwargs: + self.fiat_denoted_total: Optional[Dict[str, Any]] = kwargs.pop( + "fiat_denoted_total" + ) + super().__init__(**kwargs) + + +class FCMBalanceSummary(BaseResponse): + def __init__(self, **kwargs): + if "futures_buying_power" in kwargs: + self.futures_buying_power: Optional[Dict[str, Any]] = kwargs.pop( + "futures_buying_power" + ) + if "total_usd_balance" in kwargs: + self.total_usd_balance: Optional[Dict[str, Any]] = kwargs.pop( + "total_usd_balance" + ) + if "cbi_usd_balance" in kwargs: + self.cbi_usd_balance: Optional[Dict[str, Any]] = kwargs.pop( + "cbi_usd_balance" + ) + if "cfm_usd_balance" in kwargs: + self.cfm_usd_balance: Optional[Dict[str, Any]] = kwargs.pop( + "cfm_usd_balance" + ) + if "total_open_orders_hold_amount" in kwargs: + self.total_open_orders_hold_amount: Optional[Dict[str, Any]] = kwargs.pop( + "total_open_orders_hold_amount" + ) + if "unrealized_pnl" in kwargs: + self.unrealized_pnl: Optional[Dict[str, Any]] = kwargs.pop("unrealized_pnl") + if "daily_realized_pnl" in kwargs: + self.daily_realized_pnl: Optional[Dict[str, Any]] = kwargs.pop( + "daily_realized_pnl" + ) + if "initial_margin" in kwargs: + self.initial_margin: Optional[Dict[str, Any]] = kwargs.pop("initial_margin") + if "available_margin" in kwargs: + self.available_margin: Optional[Dict[str, Any]] = kwargs.pop( + "available_margin" + ) + if "liquidation_threshold" in kwargs: + self.liquidation_threshold: Optional[Dict[str, Any]] = kwargs.pop( + "liquidation_threshold" + ) + if "liquidation_buffer_amount" in kwargs: + self.liquidation_buffer_amount: Optional[Dict[str, Any]] = kwargs.pop( + "liquidation_buffer_amount" + ) + if "liquidation_buffer_percentage" in kwargs: + self.liquidation_buffer_percentage: Optional[str] = kwargs.pop( + "liquidation_buffer_percentage" + ) + if "intraday_margin_window_measure" in kwargs: + self.intraday_margin_window_measure: Optional[Dict[str, Any]] = kwargs.pop( + "intraday_margin_window_measure" + ) + if "overnight_margin_window_measure" in kwargs: + self.overnight_margin_window_measure: Optional[Dict[str, Any]] = kwargs.pop( + "overnight_margin_window_measure" + ) + super().__init__(**kwargs) + + +class FCMPosition(BaseResponse): + def __init__(self, **kwargs): + if "product_id" in kwargs: + self.product_id: Optional[str] = kwargs.pop("product_id") + if "expiration_time" in kwargs: + self.expiration_time: Optional[Dict[str, Any]] = kwargs.pop( + "expiration_time" + ) + if "side" in kwargs: + self.side: Optional[Dict[str, Any]] = kwargs.pop("side") + if "number_of_contracts" in kwargs: + self.number_of_contracts: Optional[str] = kwargs.pop("number_of_contracts") + if "current_price" in kwargs: + self.current_price: Optional[str] = kwargs.pop("current_price") + if "avg_entry_price" in kwargs: + self.avg_entry_price: Optional[str] = kwargs.pop("avg_entry_price") + if "unrealized_pnl" in kwargs: + self.unrealized_pnl: Optional[str] = kwargs.pop("unrealized_pnl") + if "daily_realized_pnl" in kwargs: + self.daily_realized_pnl: Optional[str] = kwargs.pop("daily_realized_pnl") + super().__init__(**kwargs) + + +class FCMSweep(BaseResponse): + def __init__(self, **kwargs): + if "id" in kwargs: + self.id: str = kwargs.pop("id") + if "requested_amount" in kwargs: + self.requested_amount: Dict[str, Any] = kwargs.pop("requested_amount") + if "should_sweep_all" in kwargs: + self.should_sweep_all: bool = kwargs.pop("should_sweep_all") + if "status" in kwargs: + self.status: Dict[str, Any] = kwargs.pop("status") + if "schedule_time" in kwargs: + self.schedule_time: Dict[str, Any] = kwargs.pop("schedule_time") + + super().__init__(**kwargs) + + +class CancelOrderObject(BaseResponse): + def __init__(self, **kwargs): + if "success" in kwargs: + self.success: bool = kwargs.pop("success") + if "failure_reason" in kwargs: + self.failure_reason: Dict[str, Any] = kwargs.pop("failure_reason") + if "order_id" in kwargs: + self.order_id: str = kwargs.pop("order_id") + super().__init__(**kwargs) + + +class MarketMarketIoc(BaseResponse): + def __init__(self, **kwargs): + if "quote_size" in kwargs: + self.quote_size: str = kwargs.pop("quote_size") + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + super().__init__(**kwargs) + + +class SorLimitIoc(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + super().__init__(**kwargs) + + +class LimitLimitGtc(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + if "post_only" in kwargs: + self.post_only: bool = kwargs.pop("post_only") + super().__init__(**kwargs) + + +class LimitLimitGtd(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + if "end_time" in kwargs: + self.end_time: str = kwargs.pop("end_time") + if "post_only" in kwargs: + self.post_only: bool = kwargs.pop("post_only") + super().__init__(**kwargs) + + +class LimitLimitFok(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + super().__init__(**kwargs) + + +class StopLimitStopLimitGtc(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + if "stop_price" in kwargs: + self.stop_price: str = kwargs.pop("stop_price") + if "stop_direction" in kwargs: + self.stop_direction: StopDirection = kwargs.pop("stop_direction") + super().__init__(**kwargs) + + +class StopLimitStopLimitGtd(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + if "stop_price" in kwargs: + self.stop_price: str = kwargs.pop("stop_price") + if "end_time" in kwargs: + self.end_time: str = kwargs.pop("end_time") + if "stop_direction" in kwargs: + self.stop_direction: StopDirection = kwargs.pop("stop_direction") + + super().__init__(**kwargs) + + +class TriggerBracketGtc(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + if "stop_trigger_price" in kwargs: + self.stop_trigger_price: str = kwargs.pop("stop_trigger_price") + super().__init__(**kwargs) + + +class TriggerBracketGtd(BaseResponse): + def __init__(self, **kwargs): + if "base_size" in kwargs: + self.base_size: str = kwargs.pop("base_size") + if "limit_price" in kwargs: + self.limit_price: str = kwargs.pop("limit_price") + if "stop_trigger_price" in kwargs: + self.stop_trigger_price: str = kwargs.pop("stop_trigger_price") + if "end_time" in kwargs: + self.end_time: str = kwargs.pop("end_time") + + super().__init__(**kwargs) + + +class OrderConfiguration(BaseResponse): + def __init__(self, **kwargs): + if "market_market_ioc" in kwargs: + self.market_market_ioc: Optional[MarketMarketIoc] = MarketMarketIoc( + **kwargs.pop("market_market_ioc") + ) + if "sor_limit_ioc" in kwargs: + self.sor_limit_ioc: Optional[SorLimitIoc] = SorLimitIoc( + **kwargs.pop("sor_limit_ioc") + ) + if "limit_limit_gtc" in kwargs: + self.limit_limit_gtc: Optional[LimitLimitGtc] = LimitLimitGtc( + **kwargs.pop("limit_limit_gtc") + ) + if "limit_limit_gtd" in kwargs: + self.limit_limit_gtd: Optional[LimitLimitGtd] = LimitLimitGtd( + **kwargs.pop("limit_limit_gtd") + ) + if "limit_limit_fok" in kwargs: + self.limit_limit_fok: Optional[LimitLimitFok] = LimitLimitFok( + **kwargs.pop("limit_limit_fok") + ) + if "stop_limit_stop_limit_gtc" in kwargs: + self.stop_limit_stop_limit_gtc: Optional[ + StopLimitStopLimitGtc + ] = StopLimitStopLimitGtc(**kwargs.pop("stop_limit_stop_limit_gtc")) + if "stop_limit_stop_limit_gtd" in kwargs: + self.stop_limit_stop_limit_gtd: Optional[ + StopLimitStopLimitGtd + ] = StopLimitStopLimitGtd(**kwargs.pop("stop_limit_stop_limit_gtd")) + if "trigger_bracket_gtc" in kwargs: + self.trigger_bracket_gtc: Optional[TriggerBracketGtc] = TriggerBracketGtc( + **kwargs.pop("trigger_bracket_gtc") + ) + if "trigger_bracket_gtd" in kwargs: + self.trigger_bracket_gtd: Optional[TriggerBracketGtd] = TriggerBracketGtd( + **kwargs.pop("trigger_bracket_gtd") + ) + super().__init__(**kwargs) + + +class Order(BaseResponse): + def __init__(self, **kwargs): + if "order_id" in kwargs: + self.order_id: str = kwargs.pop("order_id") + if "product_id" in kwargs: + self.product_id: str = kwargs.pop("product_id") + if "user_id" in kwargs: + self.user_id: str = kwargs.pop("user_id") + if "order_configuration" in kwargs: + self.order_configuration: OrderConfiguration = OrderConfiguration( + **kwargs.pop("order_configuration") + ) + if "side" in kwargs: + self.side: OrderSide = kwargs.pop("side") + if "client_order_id" in kwargs: + self.client_order_id: str = kwargs.pop("client_order_id") + if "status" in kwargs: + self.status: Dict[str, Any] = kwargs.pop("status") + if "time_in_force" in kwargs: + self.time_in_force: Optional[Dict[str, Any]] = kwargs.pop("time_in_force") + if "created_time" in kwargs: + self.created_time: Dict[str, Any] = kwargs.pop("created_time") + if "completion_percentage" in kwargs: + self.completion_percentage: str = kwargs.pop("completion_percentage") + if "filled_size" in kwargs: + self.filled_size: Optional[str] = kwargs.pop("filled_size") + if "average_filled_price" in kwargs: + self.average_filled_price: str = kwargs.pop("average_filled_price") + if "fee" in kwargs: + self.fee: Optional[str] = kwargs.pop("fee") + if "number_of_fills" in kwargs: + self.number_of_fills: str = kwargs.pop("number_of_fills") + if "filled_value" in kwargs: + self.filled_value: Optional[str] = kwargs.pop("filled_value") + if "pending_cancel" in kwargs: + self.pending_cancel: bool = kwargs.pop("pending_cancel") + if "size_in_quote" in kwargs: + self.size_in_quote: bool = kwargs.pop("size_in_quote") + if "total_fees" in kwargs: + self.total_fees: str = kwargs.pop("total_fees") + if "size_inclusive_of_fees" in kwargs: + self.size_inclusive_of_fees: bool = kwargs.pop("size_inclusive_of_fees") + if "total_value_after_fees" in kwargs: + self.total_value_after_fees: str = kwargs.pop("total_value_after_fees") + if "trigger_status" in kwargs: + self.trigger_status: Optional[Dict[str, Any]] = kwargs.pop("trigger_status") + if "order_type" in kwargs: + self.order_type: Optional[Dict[str, Any]] = kwargs.pop("order_type") + if "reject_reason" in kwargs: + self.reject_reason: Optional[Dict[str, Any]] = kwargs.pop("reject_reason") + if "settled" in kwargs: + self.settled: Optional[bool] = kwargs.pop("settled") + if "product_type" in kwargs: + self.product_type: Optional[ProductType] = kwargs.pop("product_type") + if "reject_message" in kwargs: + self.reject_message: Optional[str] = kwargs.pop("reject_message") + if "cancel_message" in kwargs: + self.cancel_message: Optional[str] = kwargs.pop("cancel_message") + if "order_placement_source" in kwargs: + self.order_placement_source: Optional[OrderPlacementSource] = kwargs.pop( + "order_placement_source" + ) + if "outstanding_hold_amount" in kwargs: + self.outstanding_hold_amount: Optional[str] = kwargs.pop( + "outstanding_hold_amount" + ) + if "is_liquidation" in kwargs: + self.is_liquidation: Optional[bool] = kwargs.pop("is_liquidation") + if "last_fill_time" in kwargs: + self.last_fill_time: Optional[Dict[str, Any]] = kwargs.pop("last_fill_time") + if "edit_history" in kwargs: + self.edit_history: Optional[List[Dict[str, Any]]] = kwargs.pop( + "edit_history" + ) + if "leverage" in kwargs: + self.leverage: Optional[str] = kwargs.pop("leverage") + if "margin_type" in kwargs: + self.margin_type: Optional[MarginType] = kwargs.pop("margin_type") + if "retail_portfolio_id" in kwargs: + self.retail_portfolio_id: Optional[str] = kwargs.pop("retail_portfolio_id") + if "originating_order_id" in kwargs: + self.originating_order_id: Optional[str] = kwargs.pop( + "originating_order_id" + ) + if "attached_order_id" in kwargs: + self.attached_order_id: Optional[str] = kwargs.pop("attached_order_id") + # NOT LIVE YET + # if "attached_order_configuration" in kwargs: + # self.attached_order_configuration: Optional[ + # OrderConfiguration + # ] = OrderConfiguration(**kwargs.pop("attached_order_configuration")) + super().__init__(**kwargs) + + +class PaymentMethod(BaseResponse): + def __init__(self, **kwargs): + if "id" in kwargs: + self.id: Optional[str] = kwargs.pop("id") + if "type" in kwargs: + self.type: Optional[str] = kwargs.pop("type") + if "name" in kwargs: + self.name: Optional[str] = kwargs.pop("name") + if "currency" in kwargs: + self.currency: Optional[str] = kwargs.pop("currency") + if "verified" in kwargs: + self.verified: Optional[bool] = kwargs.pop("verified") + if "allow_buy" in kwargs: + self.allow_buy: Optional[bool] = kwargs.pop("allow_buy") + if "allow_sell" in kwargs: + self.allow_sell: Optional[bool] = kwargs.pop("allow_sell") + if "allow_deposit" in kwargs: + self.allow_deposit: Optional[bool] = kwargs.pop("allow_deposit") + if "allow_withdraw" in kwargs: + self.allow_withdraw: Optional[bool] = kwargs.pop("allow_withdraw") + if "created_at" in kwargs: + self.created_at: Optional[str] = kwargs.pop("created_at") + if "updated_at" in kwargs: + self.updated_at: Optional[str] = kwargs.pop("updated_at") + super().__init__(**kwargs) + + +class PerpetualPortfolio(BaseResponse): + def __init__(self, **kwargs): + if "portfolio_uuid" in kwargs: + self.portfolio_uuid: Optional[str] = kwargs.pop("portfolio_uuid") + if "collateral" in kwargs: + self.collateral: Optional[str] = kwargs.pop("collateral") + if "position_notional" in kwargs: + self.position_notional: Optional[str] = kwargs.pop("position_notional") + if "open_position_notional" in kwargs: + self.open_position_notional: Optional[str] = kwargs.pop( + "open_position_notional" + ) + if "pending_fees" in kwargs: + self.pending_fees: Optional[str] = kwargs.pop("pending_fees") + if "borrow" in kwargs: + self.borrow: Optional[str] = kwargs.pop("borrow") + if "accrued_interest" in kwargs: + self.accrued_interest: Optional[str] = kwargs.pop("accrued_interest") + if "rolling_debt" in kwargs: + self.rolling_debt: Optional[str] = kwargs.pop("rolling_debt") + if "portfolio_initial_margin" in kwargs: + self.portfolio_initial_margin: Optional[str] = kwargs.pop( + "portfolio_initial_margin" + ) + if "portfolio_im_notional" in kwargs: + self.portfolio_im_notional: Optional[Dict[str, Any]] = kwargs.pop( + "portfolio_im_notional" + ) + if "liquidation_percentage" in kwargs: + self.liquidation_percentage: Optional[str] = kwargs.pop( + "liquidation_percentage" + ) + if "liquidation_buffer" in kwargs: + self.liquidation_buffer: Optional[str] = kwargs.pop("liquidation_buffer") + if "margin_type" in kwargs: + self.margin_type: Optional[Dict[str, Any]] = kwargs.pop("margin_type") + if "margin_flags" in kwargs: + self.margin_flags: Optional[Dict[str, Any]] = kwargs.pop("margin_flags") + if "liquidation_status" in kwargs: + self.liquidation_status: Optional[Dict[str, Any]] = kwargs.pop( + "liquidation_status" + ) + if "unrealized_pnl" in kwargs: + self.unrealized_pnl: Optional[Dict[str, Any]] = kwargs.pop("unrealized_pnl") + if "total_balance" in kwargs: + self.total_balance: Optional[Dict[str, Any]] = kwargs.pop("total_balance") + super().__init__(**kwargs) + + +class PortfolioSummary(BaseResponse): + def __init__(self, **kwargs): + if "unrealized_pnl" in kwargs: + self.unrealized_pnl: Optional[Dict[str, Any]] = kwargs.pop("unrealized_pnl") + if "buying_power" in kwargs: + self.buying_power: Optional[Dict[str, Any]] = kwargs.pop("buying_power") + if "total_balance" in kwargs: + self.total_balance: Optional[Dict[str, Any]] = kwargs.pop("total_balance") + if "max_withdrawal_amount" in kwargs: + self.max_withdrawal_amount: Optional[Dict[str, Any]] = kwargs.pop( + "max_withdrawal_amount" + ) + super().__init__(**kwargs) + + +class Position(BaseResponse): + def __init__(self, **kwargs): + if "product_id" in kwargs: + self.product_id: Optional[str] = kwargs.pop("product_id") + if "product_uuid" in kwargs: + self.product_uuid: Optional[str] = kwargs.pop("product_uuid") + if "portfolio_uuid" in kwargs: + self.portfolio_uuid: Optional[str] = kwargs.pop("portfolio_uuid") + if "symbol" in kwargs: + self.symbol: Optional[str] = kwargs.pop("symbol") + if "vwap" in kwargs: + self.vwap: Optional[Dict[str, Any]] = kwargs.pop("vwap") + if "entry_vwap" in kwargs: + self.entry_vwap: Optional[Dict[str, Any]] = kwargs.pop("entry_vwap") + if "position_side" in kwargs: + self.position_side: Optional[Dict[str, Any]] = kwargs.pop("position_side") + if "margin_type" in kwargs: + self.margin_type: Optional[Dict[str, Any]] = kwargs.pop("margin_type") + if "net_size" in kwargs: + self.net_size: Optional[str] = kwargs.pop("net_size") + if "buy_order_size" in kwargs: + self.buy_order_size: Optional[str] = kwargs.pop("buy_order_size") + if "sell_order_size" in kwargs: + self.sell_order_size: Optional[str] = kwargs.pop("sell_order_size") + if "im_contribution" in kwargs: + self.im_contribution: Optional[str] = kwargs.pop("im_contribution") + if "unrealized_pnl" in kwargs: + self.unrealized_pnl: Optional[Dict[str, Any]] = kwargs.pop("unrealized_pnl") + if "mark_price" in kwargs: + self.mark_price: Optional[Dict[str, Any]] = kwargs.pop("mark_price") + if "liquidation_price" in kwargs: + self.liquidation_price: Optional[Dict[str, Any]] = kwargs.pop( + "liquidation_price" + ) + if "leverage" in kwargs: + self.leverage: Optional[str] = kwargs.pop("leverage") + if "im_notional" in kwargs: + self.im_notional: Optional[Dict[str, Any]] = kwargs.pop("im_notional") + if "mm_notional" in kwargs: + self.mm_notional: Optional[Dict[str, Any]] = kwargs.pop("mm_notional") + if "position_notional" in kwargs: + self.position_notional: Optional[Dict[str, Any]] = kwargs.pop( + "position_notional" + ) + if "aggregated_pnl" in kwargs: + self.aggregated_pnl: Optional[Dict[str, Any]] = kwargs.pop("aggregated_pnl") + + super().__init__(**kwargs) + + +class PositionSummary(BaseResponse): + def __init__(self, **kwargs): + if "aggregated_pnl" in kwargs: + self.aggregated_pnl: Optional[Dict[str, Any]] = kwargs.pop("aggregated_pnl") + super().__init__(**kwargs) + + +class Balance(BaseResponse): + def __init__(self, **kwargs): + if "asset" in kwargs: + self.asset: Dict[str, Any] = kwargs.pop("asset") + if "quantity" in kwargs: + self.quantity: str = kwargs.pop("quantity") + if "hold" in kwargs: + self.hold: str = kwargs.pop("hold") + if "transfer_hold" in kwargs: + self.transfer_hold: str = kwargs.pop("transfer_hold") + if "collateral_value" in kwargs: + self.collateral_value: str = kwargs.pop("collateral_value") + if "collateral_weight" in kwargs: + self.collateral_weight: str = kwargs.pop("collateral_weight") + if "max_withdraw_amount" in kwargs: + self.max_withdraw_amount: str = kwargs.pop("max_withdraw_amount") + if "loan" in kwargs: + self.loan: str = kwargs.pop("loan") + if "loan_collateral_requirement_usd" in kwargs: + self.loan_collateral_requirement_usd: str = kwargs.pop( + "loan_collateral_requirement_usd" + ) + if "pledged_quantity" in kwargs: + self.pledged_quantity: str = kwargs.pop("pledged_quantity") + super().__init__(**kwargs) + + +class PortfolioBalance(BaseResponse): + def __init__(self, **kwargs): + if "portfolio_uuid" in kwargs: + self.portfolio_uuid: Optional[str] = kwargs.pop("portfolio_uuid") + if "balances" in kwargs: + self.balances: Optional[List[Balance]] = [ + Balance(**balance) for balance in kwargs.pop("balances") + ] + if "is_margin_limit_reached" in kwargs: + self.is_margin_limit_reached: Optional[bool] = kwargs.pop( + "is_margin_limit_reached" + ) + super().__init__(**kwargs) + + +class Portfolio(BaseResponse): + def __init__(self, **kwargs): + if "name" in kwargs: + self.name: Optional[str] = kwargs.pop("name") + if "uuid" in kwargs: + self.uuid: Optional[str] = kwargs.pop("uuid") + if "type" in kwargs: + self.type: Optional[str] = kwargs.pop("type") + super().__init__(**kwargs) + + +class PortfolioBreakdown(BaseResponse): + def __init__(self, **kwargs): + if "portfolio" in kwargs: + self.portfolio: Optional[Portfolio] = Portfolio(**kwargs.pop("portfolio")) + if "portfolio_balances" in kwargs: + self.portfolio_balances: Optional[Dict[str, Any]] = kwargs.pop( + "portfolio_balances" + ) + if "spot_positions" in kwargs: + self.spot_positions: Optional[List[Dict[str, Any]]] = kwargs.pop( + "spot_positions" + ) + if "perp_positions" in kwargs: + self.perp_positions: Optional[List[Dict[str, Any]]] = kwargs.pop( + "perp_positions" + ) + if "futures_positions" in kwargs: + self.futures_positions: Optional[List[Dict[str, Any]]] = kwargs.pop( + "futures_positions" + ) + super().__init__(**kwargs) + + +class PriceBook(BaseResponse): + def __init__(self, **kwargs): + if "product_id" in kwargs: + self.product_id: str = kwargs.pop("product_id") + if "bids" in kwargs: + self.bids: List[Dict[str, Any]] = kwargs.pop("bids") + if "asks" in kwargs: + self.asks: List[Dict[str, Any]] = kwargs.pop("asks") + if "time" in kwargs: + self.time: Optional[Dict[str, Any]] = kwargs.pop("time") + super().__init__(**kwargs) + + +class Product(BaseResponse): + def __init__(self, **kwargs): + if "product_id" in kwargs: + self.product_id: str = kwargs.pop("product_id") + if "price" in kwargs: + self.price: str = kwargs.pop("price") + if "price_percentage_change_24h" in kwargs: + self.price_percentage_change_24h: str = kwargs.pop( + "price_percentage_change_24h" + ) + if "volume_24h" in kwargs: + self.volume_24h: str = kwargs.pop("volume_24h") + if "volume_percentage_change_24h" in kwargs: + self.volume_percentage_change_24h: str = kwargs.pop( + "volume_percentage_change_24h" + ) + if "base_increment" in kwargs: + self.base_increment: str = kwargs.pop("base_increment") + if "quote_increment" in kwargs: + self.quote_increment: str = kwargs.pop("quote_increment") + if "quote_min_size" in kwargs: + self.quote_min_size: str = kwargs.pop("quote_min_size") + if "quote_max_size" in kwargs: + self.quote_max_size: str = kwargs.pop("quote_max_size") + if "base_min_size" in kwargs: + self.base_min_size: str = kwargs.pop("base_min_size") + if "base_max_size" in kwargs: + self.base_max_size: str = kwargs.pop("base_max_size") + if "base_name" in kwargs: + self.base_name: str = kwargs.pop("base_name") + if "quote_name" in kwargs: + self.quote_name: str = kwargs.pop("quote_name") + if "watched" in kwargs: + self.watched: bool = kwargs.pop("watched") + if "is_disabled" in kwargs: + self.is_disabled: bool = kwargs.pop("is_disabled") + if "new" in kwargs: + self.new: bool = kwargs.pop("new") + if "status" in kwargs: + self.status: str = kwargs.pop("status") + if "cancel_only" in kwargs: + self.cancel_only: bool = kwargs.pop("cancel_only") + if "limit_only" in kwargs: + self.limit_only: bool = kwargs.pop("limit_only") + if "post_only" in kwargs: + self.post_only: bool = kwargs.pop("post_only") + if "trading_disabled" in kwargs: + self.trading_disabled: bool = kwargs.pop("trading_disabled") + if "auction_mode" in kwargs: + self.auction_mode: bool = kwargs.pop("auction_mode") + if "product_type" in kwargs: + self.product_type: Optional[ProductType] = kwargs.pop("product_type") + if "quote_currency_id" in kwargs: + self.quote_currency_id: Optional[str] = kwargs.pop("quote_currency_id") + if "base_currency_id" in kwargs: + self.base_currency_id: Optional[str] = kwargs.pop("base_currency_id") + if "fcm_trading_session_details" in kwargs: + self.fcm_trading_session_details: Optional[Dict[str, Any]] = kwargs.pop( + "fcm_trading_session_details" + ) + if "mid_market_price" in kwargs: + self.mid_market_price: Optional[str] = kwargs.pop("mid_market_price") + if "alias" in kwargs: + self.alias: Optional[str] = kwargs.pop("alias") + if "alias_to" in kwargs: + self.alias_to: Optional[List[str]] = kwargs.pop("alias_to") + if "base_display_symbol" in kwargs: + self.base_display_symbol: str = kwargs.pop("base_display_symbol") + if "quote_display_symbol" in kwargs: + self.quote_display_symbol: Optional[str] = kwargs.pop( + "quote_display_symbol" + ) + if "view_only" in kwargs: + self.view_only: Optional[bool] = kwargs.pop("view_only") + if "price_increment" in kwargs: + self.price_increment: Optional[str] = kwargs.pop("price_increment") + if "display_name" in kwargs: + self.display_name: Optional[str] = kwargs.pop("display_name") + if "product_venue" in kwargs: + self.product_venue: Optional[ProductVenue] = kwargs.pop("product_venue") + if "approximate_quote_24h_volume" in kwargs: + self.approximate_quote_24h_volume: Optional[str] = kwargs.pop( + "approximate_quote_24h_volume" + ) + if "future_product_details" in kwargs: + self.future_product_details: Optional[Dict[str, Any]] = kwargs.pop( + "future_product_details" + ) + super().__init__(**kwargs) + + +class Products(BaseResponse): + def __init__(self, **kwargs): + if "products" in kwargs: + self.products: Optional[List[Product]] = [ + Product(**product) for product in kwargs.pop("products") + ] + if "num_products" in kwargs: + self.num_products: Optional[int] = kwargs.pop("num_products") + super().__init__(**kwargs) + + +class Candle(BaseResponse): + def __init__(self, **kwargs): + if "start" in kwargs: + self.start: Optional[str] = kwargs.pop("start") + if "low" in kwargs: + self.low: Optional[str] = kwargs.pop("low") + if "high" in kwargs: + self.high: Optional[str] = kwargs.pop("high") + if "open" in kwargs: + self.open: Optional[str] = kwargs.pop("open") + if "close" in kwargs: + self.close: Optional[str] = kwargs.pop("close") + if "volume" in kwargs: + self.volume: Optional[str] = kwargs.pop("volume") + super().__init__(**kwargs) + + +class Candles(BaseResponse): + def __init__(self, **kwargs): + if "candles" in kwargs: + self.candles: Optional[List[Candle]] = [ + Candle(**candle) for candle in kwargs.pop("candles") + ] + super().__init__(**kwargs) + + +class HistoricalMarketTrade(BaseResponse): + def __init__(self, **kwargs): + if "trade_id" in kwargs: + self.trade_id: Optional[str] = kwargs.pop("trade_id") + if "product_id" in kwargs: + self.product_id: Optional[str] = kwargs.pop("product_id") + if "price" in kwargs: + self.price: Optional[str] = kwargs.pop("price") + if "size" in kwargs: + self.size: Optional[str] = kwargs.pop("size") + if "time" in kwargs: + self.time: Optional[str] = kwargs.pop("time") + if "side" in kwargs: + self.side: Optional[OrderSide] = kwargs.pop("side") + super().__init__(**kwargs) diff --git a/coinbase/rest/types/convert_types.py b/coinbase/rest/types/convert_types.py new file mode 100644 index 0000000..f31f32e --- /dev/null +++ b/coinbase/rest/types/convert_types.py @@ -0,0 +1,34 @@ +from typing import Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import RatConvertTrade + + +# Create Convert Quote +class CreateConvertQuoteResponse(BaseResponse): + def __init__(self, response: dict): + if "trade" in response: + self.trade: Optional[RatConvertTrade] = RatConvertTrade( + **response.pop("trade") + ) + super().__init__(**response) + + +# Get Convert Trade +class GetConvertTradeResponse(BaseResponse): + def __init__(self, response: dict): + if "trade" in response: + self.trade: Optional[RatConvertTrade] = RatConvertTrade( + **response.pop("trade") + ) + super().__init__(**response) + + +# Commit Convert Trade +class CommitConvertTradeResponse(BaseResponse): + def __init__(self, response: dict): + if "trade" in response: + self.trade: Optional[RatConvertTrade] = RatConvertTrade( + **response.pop("trade") + ) + super().__init__(**response) diff --git a/coinbase/rest/types/data_api_types.py b/coinbase/rest/types/data_api_types.py new file mode 100644 index 0000000..90e2a4a --- /dev/null +++ b/coinbase/rest/types/data_api_types.py @@ -0,0 +1,22 @@ +from typing import Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import PortfolioType + + +# Get API Key Permissions +class GetAPIKeyPermissionsResponse(BaseResponse): + def __init__(self, response: dict): + if "can_view" in response: + self.can_view: Optional[bool] = response.pop("can_view") + if "can_trade" in response: + self.can_trade: Optional[bool] = response.pop("can_trade") + if "can_transfer" in response: + self.can_transfer: Optional[bool] = response.pop("can_transfer") + if "portfolio_uuid" in response: + self.portfolio_uuid: Optional[str] = response.pop("portfolio_uuid") + if "portfolio_type" in response: + self.portfolio_type: Optional[PortfolioType] = response.pop( + "portfolio_type" + ) + super().__init__(**response) diff --git a/coinbase/rest/types/fees_types.py b/coinbase/rest/types/fees_types.py new file mode 100644 index 0000000..b449c4a --- /dev/null +++ b/coinbase/rest/types/fees_types.py @@ -0,0 +1,39 @@ +from typing import Any, Dict, Optional + +from coinbase.rest.types.base_response import BaseResponse + + +# Get Transaction Summary +class GetTransactionSummaryResponse(BaseResponse): + def __init__(self, response: dict): + if "total_volume" in response: + self.total_volume: int = response.pop("total_volume", 0.0) + if "total_fees" in response: + self.total_fees: int = response.pop("total_fees", 0.0) + if "fee_tier" in response: + self.fee_tier: Dict[str, Any] = response.pop("fee_tier") + if "margin_rate" in response: + self.margin_rate: Optional[Dict[str, Any]] = response.pop("margin_rate") + if "goods_and_services_tax" in response: + self.goods_and_services_tax: Optional[Dict[str, Any]] = response.pop( + "goods_and_services_tax" + ) + if "advanced_trade_only_volumes" in response: + self.advanced_trade_only_volumes: Optional[int] = response.pop( + "advanced_trade_only_volumes" + ) + if "advanced_trade_only_fees" in response: + self.advanced_trade_only_fees: Optional[int] = response.pop( + "advanced_trade_only_fees" + ) + if "coinbase_pro_volume" in response: # deprecated + self.coinbase_pro_volume: Optional[int] = response.pop( + "coinbase_pro_volume" + ) + if "coinbase_pro_fees" in response: # deprecated + self.coinbase_pro_fees: Optional[int] = response.pop("coinbase_pro_fees") + if "total_balance" in response: + self.total_balance: Optional[str] = response.pop("total_balance") + if "has_promo_fee" in response: + self.has_promo_fee: Optional[bool] = response.pop("has_promo_fee") + super().__init__(**response) diff --git a/coinbase/rest/types/futures_types.py b/coinbase/rest/types/futures_types.py new file mode 100644 index 0000000..688636a --- /dev/null +++ b/coinbase/rest/types/futures_types.py @@ -0,0 +1,95 @@ +from typing import Any, Dict, List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import ( + FCMBalanceSummary, + FCMPosition, + FCMSweep, + IntradayMarginSetting, +) + + +# Get Futures Balance Summary +class GetFuturesBalanceSummaryResponse(BaseResponse): + def __init__(self, response: dict): + if "balance_summary" in response: + self.balance_summary: Optional[FCMBalanceSummary] = FCMBalanceSummary( + **response.pop("balance_summary") + ) + super().__init__(**response) + + +# List Futures Positions +class ListFuturesPositionsResponse(BaseResponse): + def __init__(self, response: dict): + if "positions" in response: + self.positions: Optional[List[FCMPosition]] = [ + FCMPosition(**position) for position in response.pop("positions") + ] + super().__init__(**response) + + +# Get Futures Position +class GetFuturesPositionResponse(BaseResponse): + def __init__(self, response: dict): + if "position" in response: + self.position: Optional[FCMPosition] = FCMPosition( + **response.pop("position") + ) + super().__init__(**response) + + +# Schedule Futures Sweep +class ScheduleFuturesSweepResponse(BaseResponse): + def __init__(self, response: dict): + if "success" in response: + self.success: Optional[bool] = response.pop("success") + super().__init__(**response) + + +# List Futures Sweeps +class ListFuturesSweepsResponse(BaseResponse): + def __init__(self, response: dict): + if "sweeps" in response: + self.sweeps: List[FCMSweep] = [ + FCMSweep(**sweep) for sweep in response.pop("sweeps") + ] + super().__init__(**response) + + +# Cancel Pending Futures Sweep +class CancelPendingFuturesSweepResponse(BaseResponse): + def __init__(self, response: dict): + if "success" in response: + self.success: Optional[bool] = response.pop("success") + super().__init__(**response) + + +# Get Intraday Margin Setting +class GetIntradayMarginSettingResponse(BaseResponse): + def __init__(self, response: dict): + if "setting" in response: + self.setting: Optional[IntradayMarginSetting] = response.pop("setting") + super().__init__(**response) + + +# Get Current Margin Window +class GetCurrentMarginWindowResponse(BaseResponse): + def __init__(self, response: dict): + if "margin_window" in response: + self.margin_window: Optional[Dict[str, Any]] = response.pop("margin_window") + if "is_intraday_margin_killswitch_enabled" in response: + self.is_intraday_margin_killswitch_enabled: Optional[bool] = response.pop( + "is_intraday_margin_killswitch_enabled" + ) + if "is_intraday_margin_enrollment_killswitch_enabled" in response: + self.is_intraday_margin_enrollment_killswitch_enabled: Optional[ + bool + ] = response.pop("is_intraday_margin_enrollment_killswitch_enabled") + super().__init__(**response) + + +# Set Intraday Margin Setting +class SetIntradayMarginSettingResponse(BaseResponse): + def __init__(self, response: dict): + super().__init__(**response) diff --git a/coinbase/rest/types/orders_types.py b/coinbase/rest/types/orders_types.py new file mode 100644 index 0000000..f6cefd1 --- /dev/null +++ b/coinbase/rest/types/orders_types.py @@ -0,0 +1,184 @@ +from typing import Any, Dict, List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import ( + CancelOrderObject, + Order, + OrderConfiguration, +) + + +# Create Order +class CreateOrderResponse(BaseResponse): + def __init__(self, response: dict): + if "success" in response: + self.success: bool = response.pop("success") + if "failure_reason" in response: + self.failure_reason: Optional[Dict[str, Any]] = response.pop( + "failure_reason" + ) + if "order_id" in response: + self.order_id: Optional[str] = response.pop("order_id") + + if "success_response" in response: + self.response: Optional[Dict[str, Any]] = response.pop("success_response") + elif "error_response" in response: + self.response: Optional[Dict[str, Any]] = response.pop("error_response") + + if "order_configuration" in response: + self.order_configuration: Optional[OrderConfiguration] = OrderConfiguration( + **response.pop("order_configuration") + ) + super().__init__(**response) + + +# Cancel Orders +class CancelOrdersResponse(BaseResponse): + def __init__(self, response: dict): + if "results" in response: + self.results: Optional[List[CancelOrderObject]] = [ + CancelOrderObject(**result) for result in response.pop("results") + ] + super().__init__(**response) + + +# Edit Order +class EditOrderResponse(BaseResponse): + def __init__(self, response: dict): + if "success" in response: + self.success: bool = response.pop("success") + + if "success_response" in response: + self.response: Optional[Dict[str, Any]] = response.pop("success_response") + elif "error_response" in response: + self.response: Optional[Dict[str, Any]] = response.pop("error_response") + + if "errors" in response: + self.errors: Optional[List[Dict[str, Any]]] = response.pop("errors") + super().__init__(**response) + + +# Edit Order Preview +class EditOrderPreviewResponse(BaseResponse): + def __init__(self, response: dict): + if "errors" in response: + self.errors: List[Dict[str, Any]] = response.pop("errors") + if "slippage" in response: + self.slippage: Optional[str] = response.pop("slippage") + if "order_total" in response: + self.order_total: Optional[str] = response.pop("order_total") + if "commission_total" in response: + self.commission_total: Optional[str] = response.pop("commission_total") + if "quote_size" in response: + self.quote_size: Optional[str] = response.pop("quote_size") + if "base_size" in response: + self.base_size: Optional[str] = response.pop("base_size") + if "best_bid" in response: + self.best_bid: Optional[str] = response.pop("best_bid") + if "average_filled_price" in response: + self.average_filled_price: Optional[str] = response.pop( + "average_filled_price" + ) + super().__init__(**response) + + +# List Orders +class ListOrdersResponse(BaseResponse): + def __init__(self, response: dict): + if "orders" in response: + self.orders: List[Order] = [ + Order(**order) for order in response.pop("orders") + ] + if "sequence" in response: + self.sequence: Optional[int] = response.pop("sequence") + if "has_next" in response: + self.has_next: bool = response.pop("has_next") + if "cursor" in response: + self.cursor: Optional[str] = response.pop("cursor") + super().__init__(**response) + + +# List Fills +class ListFillsResponse(BaseResponse): + def __init__(self, response: dict): + if "fills" in response: + self.fills: Optional[List[Dict[str, Any]]] = response.pop("fills") + if "cursor" in response: + self.cursor: Optional[str] = response.pop("cursor") + super().__init__(**response) + + +# Get Order +class GetOrderResponse(BaseResponse): + def __init__(self, response: dict): + if "order" in response: + self.order: Optional[Order] = Order(**response.pop("order")) + super().__init__(**response) + + +# Preview Order +class PreviewOrderResponse(BaseResponse): + def __init__(self, response: dict): + if "order_total" in response: + self.order_total: str = response.pop("order_total") + if "commission_total" in response: + self.commission_total: str = response.pop("commission_total") + if "errs" in response: + self.errs: List[Dict[str, Any]] = response.pop("errs") + if "warning" in response: + self.warning: List[Dict[str, Any]] = response.pop("warning") + if "quote_size" in response: + self.quote_size: str = response.pop("quote_size") + if "base_size" in response: + self.base_size: str = response.pop("base_size") + if "best_bid" in response: + self.best_bid: str = response.pop("best_bid") + if "best_ask" in response: + self.best_ask: str = response.pop("best_ask") + if "is_max" in response: + self.is_max: bool = response.pop("is_max") + if "order_margin_total" in response: + self.order_margin_total: Optional[str] = response.pop("order_margin_total") + if "leverage" in response: + self.leverage: Optional[str] = response.pop("leverage") + if "long_leverage" in response: + self.long_leverage: Optional[str] = response.pop("long_leverage") + if "short_leverage" in response: + self.short_leverage: Optional[str] = response.pop("short_leverage") + if "slippage" in response: + self.slippage: Optional[str] = response.pop("slippage") + if "preview_id" in response: + self.preview_id: Optional[str] = response.pop("preview_id") + if "current_liquidation_buffer" in response: + self.current_liquidation_buffer: Optional[str] = response.pop( + "current_liquidation_buffer" + ) + if "projected_liquidation_buffer" in response: + self.projected_liquidation_buffer: Optional[str] = response.pop( + "projected_liquidation_buffer" + ) + if "max_leverage" in response: + self.max_leverage: Optional[str] = response.pop("max_leverage") + if "pnl_configuration" in response: + self.pnl_configuration: Optional[Dict[str, Any]] = response.pop( + "pnl_configuration" + ) + super().__init__(**response) + + +# Close Position +class ClosePositionResponse(BaseResponse): + def __init__(self, response: dict): + if "success" in response: + self.success: bool = response.pop("success") + + if "success_response" in response: + self.response: Optional[Dict[str, Any]] = response.pop("success_response") + elif "error_response" in response: + self.response: Optional[Dict[str, Any]] = response.pop("error_response") + + if "order_configuration" in response: + self.order_configuration: Optional[OrderConfiguration] = OrderConfiguration( + **response.pop("order_configuration") + ) + super().__init__(**response) diff --git a/coinbase/rest/types/payments_types.py b/coinbase/rest/types/payments_types.py new file mode 100644 index 0000000..acff98c --- /dev/null +++ b/coinbase/rest/types/payments_types.py @@ -0,0 +1,25 @@ +from typing import List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import PaymentMethod + + +# List Payment Methods +class ListPaymentMethodsResponse(BaseResponse): + def __init__(self, response: dict): + if "payment_methods" in response: + self.payment_methods: Optional[List[PaymentMethod]] = [ + PaymentMethod(**method) for method in response.pop("payment_methods") + ] + + super().__init__(**response) + + +# Get Payment Method +class GetPaymentMethodResponse(BaseResponse): + def __init__(self, response: dict): + if "payment_method" in response: + self.payment_method: Optional[PaymentMethod] = PaymentMethod( + **response.pop("payment_method") + ) + super().__init__(**response) diff --git a/coinbase/rest/types/perpetuals_types.py b/coinbase/rest/types/perpetuals_types.py new file mode 100644 index 0000000..40e5919 --- /dev/null +++ b/coinbase/rest/types/perpetuals_types.py @@ -0,0 +1,74 @@ +from typing import List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import ( + PerpetualPortfolio, + PortfolioBalance, + PortfolioSummary, + Position, + PositionSummary, +) + + +# Allocate Portfolio +class AllocatePortfolioResponse(BaseResponse): + def __init__(self, response: dict): + super().__init__(**response) + + +# Get Perpetuals Portfolio Summary +class GetPerpetualsPortfolioSummaryResponse(BaseResponse): + def __init__(self, response: dict): + if "portfolios" in response: + self.portfolios: Optional[List[PerpetualPortfolio]] = [ + PerpetualPortfolio(**portfolio) + for portfolio in response.pop("portfolios") + ] + if "summary" in response: + self.summary: Optional[PortfolioSummary] = PortfolioSummary( + **response.pop("summary") + ) + super().__init__(**response) + + +# List Perpetuals Positions +class ListPerpetualsPositionsResponse(BaseResponse): + def __init__(self, response: dict): + if "positions" in response: + self.positions: Optional[List[Position]] = [ + Position(**pos) for pos in response.pop("positions") + ] + if "summary" in response: + self.summary: Optional[PositionSummary] = PositionSummary( + **response.pop("summary") + ) + super().__init__(**response) + + +# Get Perpetuals Position +class GetPerpetualsPositionResponse(BaseResponse): + def __init__(self, response: dict): + if "position" in response: + self.position: Optional[Position] = Position(**response.pop("position")) + super().__init__(**response) + + +# Get Portfolio Balances +class GetPortfolioBalancesResponse(BaseResponse): + def __init__(self, response: dict): + if "portfolio_balances" in response: + self.portfolio_balances: Optional[List[PortfolioBalance]] = [ + PortfolioBalance(**balance) + for balance in response.pop("portfolio_balances") + ] + super().__init__(**response) + + +# Opt In or Out of Multi Asset Collateral +class OptInOutMultiAssetCollateralResponse(BaseResponse): + def __init__(self, response: dict): + if "cross_collateral_enabled" in response: + self.cross_collateral_enabled: Optional[bool] = response.pop( + "cross_collateral_enabled" + ) + super().__init__(**response) diff --git a/coinbase/rest/types/portfolios_types.py b/coinbase/rest/types/portfolios_types.py new file mode 100644 index 0000000..8ea5231 --- /dev/null +++ b/coinbase/rest/types/portfolios_types.py @@ -0,0 +1,60 @@ +from typing import List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import Portfolio, PortfolioBreakdown + + +# List Portfolios +class ListPortfoliosResponse(BaseResponse): + def __init__(self, response: dict): + if "portfolios" in response: + self.portfolios: Optional[List[Portfolio]] = [ + Portfolio(**portfolio) for portfolio in response.pop("portfolios") + ] + super().__init__(**response) + + +# Create Portfolio +class CreatePortfolioResponse(BaseResponse): + def __init__(self, response: dict): + if "portfolio" in response: + self.portfolio: Optional[Portfolio] = Portfolio(**response.pop("portfolio")) + super().__init__(**response) + + +# Move Portfolio Funds +class MovePortfolioFundsResponse(BaseResponse): + def __init__(self, response: dict): + if "source_portfolio_uuid" in response: + self.source_portfolio_uuid: Optional[str] = response.pop( + "source_portfolio_uuid" + ) + if "target_portfolio_uuid" in response: + self.target_portfolio_uuid: Optional[str] = response.pop( + "target_portfolio_uuid" + ) + super().__init__(**response) + + +# Get Portfolio Breakdown +class GetPortfolioBreakdownResponse(BaseResponse): + def __init__(self, response: dict): + if "breakdown" in response: + self.breakdown: Optional[PortfolioBreakdown] = PortfolioBreakdown( + **response.pop("breakdown") + ) + super().__init__(**response) + + +# Delete Portfolio +class DeletePortfolioResponse(BaseResponse): + def __init__(self, response: dict): + super().__init__(**response) + + +# Edit Portfolio +class EditPortfolioResponse(BaseResponse): + def __init__(self, response: dict): + if "portfolio" in response: + self.portfolio: Optional[Portfolio] = Portfolio(**response.pop("portfolio")) + super().__init__(**response) diff --git a/coinbase/rest/types/product_types.py b/coinbase/rest/types/product_types.py new file mode 100644 index 0000000..9da9e45 --- /dev/null +++ b/coinbase/rest/types/product_types.py @@ -0,0 +1,157 @@ +from typing import Any, Dict, List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import ( + Candle, + HistoricalMarketTrade, + PriceBook, + Product, + ProductType, + ProductVenue, +) + + +# Get Best Bid/Ask +class GetBestBidAskResponse(BaseResponse): + def __init__(self, response: dict): + if "pricebooks" in response: + self.pricebooks: Optional[List[PriceBook]] = [ + PriceBook(**pricebook) for pricebook in response.pop("pricebooks") + ] + super().__init__(**response) + + +# Get Product Book +class GetProductBookResponse(BaseResponse): + def __init__(self, response: dict): + if "pricebook" in response: + self.pricebook: PriceBook = PriceBook(**response.pop("pricebook")) + super().__init__(**response) + + +# List Products +class ListProductsResponse(BaseResponse): + def __init__(self, response: dict): + if "products" in response: + self.products: Optional[List[Product]] = [ + Product(**product) for product in response.pop("products") + ] + if "num_products" in response: + self.num_products: Optional[int] = response.pop("num_products") + super().__init__(**response) + + +# Get Product +class GetProductResponse(BaseResponse): + def __init__(self, response: dict): + if "product_id" in response: + self.product_id: str = response.pop("product_id") + if "price" in response: + self.price: str = response.pop("price") + if "price_percentage_change_24h" in response: + self.price_percentage_change_24h: str = response.pop( + "price_percentage_change_24h" + ) + if "volume_24h" in response: + self.volume_24h: str = response.pop("volume_24h") + if "volume_percentage_change_24h" in response: + self.volume_percentage_change_24h: str = response.pop( + "volume_percentage_change_24h" + ) + if "base_increment" in response: + self.base_increment: str = response.pop("base_increment") + if "quote_increment" in response: + self.quote_increment: str = response.pop("quote_increment") + if "quote_min_size" in response: + self.quote_min_size: str = response.pop("quote_min_size") + if "quote_max_size" in response: + self.quote_max_size: str = response.pop("quote_max_size") + if "base_min_size" in response: + self.base_min_size: str = response.pop("base_min_size") + if "base_max_size" in response: + self.base_max_size: str = response.pop("base_max_size") + if "base_name" in response: + self.base_name: str = response.pop("base_name") + if "quote_name" in response: + self.quote_name: str = response.pop("quote_name") + if "watched" in response: + self.watched: bool = response.pop("watched") + if "is_disabled" in response: + self.is_disabled: bool = response.pop("is_disabled") + if "new" in response: + self.new: bool = response.pop("new") + if "status" in response: + self.status: str = response.pop("status") + if "cancel_only" in response: + self.cancel_only: bool = response.pop("cancel_only") + if "limit_only" in response: + self.limit_only: bool = response.pop("limit_only") + if "post_only" in response: + self.post_only: bool = response.pop("post_only") + if "trading_disabled" in response: + self.trading_disabled: bool = response.pop("trading_disabled") + if "auction_mode" in response: + self.auction_mode: bool = response.pop("auction_mode") + if "product_type" in response: + self.product_type: Optional[ProductType] = response.pop("product_type") + if "quote_currency_id" in response: + self.quote_currency_id: Optional[str] = response.pop("quote_currency_id") + if "base_currency_id" in response: + self.base_currency_id: Optional[str] = response.pop("base_currency_id") + if "fcm_trading_session_details" in response: + self.fcm_trading_session_details: Optional[Dict[str, Any]] = response.pop( + "fcm_trading_session_details" + ) + if "mid_market_price" in response: + self.mid_market_price: Optional[str] = response.pop("mid_market_price") + if "alias" in response: + self.alias: Optional[str] = response.pop("alias") + if "alias_to" in response: + self.alias_to: Optional[List[str]] = response.pop("alias_to") + if "base_display_symbol" in response: + self.base_display_symbol: str = response.pop("base_display_symbol") + if "quote_display_symbol" in response: + self.quote_display_symbol: Optional[str] = response.pop( + "quote_display_symbol" + ) + if "view_only" in response: + self.view_only: Optional[bool] = response.pop("view_only") + if "price_increment" in response: + self.price_increment: Optional[str] = response.pop("price_increment") + if "display_name" in response: + self.display_name: Optional[str] = response.pop("display_name") + if "product_venue" in response: + self.product_venue: Optional[ProductVenue] = response.pop("product_venue") + if "approximate_quote_24h_volume" in response: + self.approximate_quote_24h_volume: Optional[str] = response.pop( + "approximate_quote_24h_volume" + ) + if "future_product_details" in response: + self.future_product_details: Optional[Dict[str, Any]] = response.pop( + "future_product_details" + ) + super().__init__(**response) + + +# Get Product Candles +class GetProductCandlesResponse(BaseResponse): + def __init__(self, response: dict): + if "candles" in response: + self.candles: Optional[List[Candle]] = [ + Candle(**candle) for candle in response.pop("candles") + ] + super().__init__(**response) + + +# Get Market Trades +class GetMarketTradesResponse(BaseResponse): + def __init__(self, response: dict): + if "trades" in response: + self.trades: Optional[List[HistoricalMarketTrade]] = [ + HistoricalMarketTrade(**trade) for trade in response.pop("trades") + ] + if "best_bid" in response: + self.best_bid: Optional[str] = response.pop("best_bid") + if "best_ask" in response: + self.best_ask: Optional[str] = response.pop("best_ask") + super().__init__(**response) diff --git a/coinbase/rest/types/public_types.py b/coinbase/rest/types/public_types.py new file mode 100644 index 0000000..90bf5bf --- /dev/null +++ b/coinbase/rest/types/public_types.py @@ -0,0 +1,159 @@ +from typing import Any, Dict, List, Optional + +from coinbase.rest.types.base_response import BaseResponse +from coinbase.rest.types.common_types import ( + Candle, + HistoricalMarketTrade, + PriceBook, + Product, + ProductType, + ProductVenue, +) + + +# Get Server Time Response +class GetServerTimeResponse(BaseResponse): + def __init__(self, response: dict): + if "iso" in response: + self.iso: Optional[str] = response.pop("iso") + if "epochSeconds" in response: + self.epoch_seconds: Optional[int] = response.pop("epochSeconds") + if "epochMillis" in response: + self.epoch_millis: Optional[int] = response.pop("epochMillis") + super().__init__(**response) + + +# Get Public Product Book Response +class GetPublicProductBookResponse(BaseResponse): + def __init__(self, response: dict): + if "pricebook" in response: + self.pricebook: PriceBook = PriceBook(**response.pop("pricebook")) + super().__init__(**response) + + +# List Public Products Response +class ListPublicProductsResponse(BaseResponse): + def __init__(self, response: dict): + if "products" in response: + self.products: Optional[List[Product]] = [ + Product(**product) for product in response.pop("products") + ] + if "num_products" in response: + self.num_products: Optional[int] = response.pop("num_products") + super().__init__(**response) + + +# Get Public Product Response +class GetPublicProductResponse(BaseResponse): + def __init__(self, response: dict): + if "product_id" in response: + self.product_id: str = response.pop("product_id") + if "price" in response: + self.price: str = response.pop("price") + if "price_percentage_change_24h" in response: + self.price_percentage_change_24h: str = response.pop( + "price_percentage_change_24h" + ) + if "volume_24h" in response: + self.volume_24h: str = response.pop("volume_24h") + if "volume_percentage_change_24h" in response: + self.volume_percentage_change_24h: str = response.pop( + "volume_percentage_change_24h" + ) + if "base_increment" in response: + self.base_increment: str = response.pop("base_increment") + if "quote_increment" in response: + self.quote_increment: str = response.pop("quote_increment") + if "quote_min_size" in response: + self.quote_min_size: str = response.pop("quote_min_size") + if "quote_max_size" in response: + self.quote_max_size: str = response.pop("quote_max_size") + if "base_min_size" in response: + self.base_min_size: str = response.pop("base_min_size") + if "base_max_size" in response: + self.base_max_size: str = response.pop("base_max_size") + if "base_name" in response: + self.base_name: str = response.pop("base_name") + if "quote_name" in response: + self.quote_name: str = response.pop("quote_name") + if "watched" in response: + self.watched: bool = response.pop("watched") + if "is_disabled" in response: + self.is_disabled: bool = response.pop("is_disabled") + if "new" in response: + self.new: bool = response.pop("new") + if "status" in response: + self.status: str = response.pop("status") + if "cancel_only" in response: + self.cancel_only: bool = response.pop("cancel_only") + if "limit_only" in response: + self.limit_only: bool = response.pop("limit_only") + if "post_only" in response: + self.post_only: bool = response.pop("post_only") + if "trading_disabled" in response: + self.trading_disabled: bool = response.pop("trading_disabled") + if "auction_mode" in response: + self.auction_mode: bool = response.pop("auction_mode") + if "product_type" in response: + self.product_type: Optional[ProductType] = response.pop("product_type") + if "quote_currency_id" in response: + self.quote_currency_id: Optional[str] = response.pop("quote_currency_id") + if "base_currency_id" in response: + self.base_currency_id: Optional[str] = response.pop("base_currency_id") + if "fcm_trading_session_details" in response: + self.fcm_trading_session_details: Optional[Dict[str, Any]] = response.pop( + "fcm_trading_session_details" + ) + if "mid_market_price" in response: + self.mid_market_price: Optional[str] = response.pop("mid_market_price") + if "alias" in response: + self.alias: Optional[str] = response.pop("alias") + if "alias_to" in response: + self.alias_to: Optional[List[str]] = response.pop("alias_to") + if "base_display_symbol" in response: + self.base_display_symbol: str = response.pop("base_display_symbol") + if "quote_display_symbol" in response: + self.quote_display_symbol: Optional[str] = response.pop( + "quote_display_symbol" + ) + if "view_only" in response: + self.view_only: Optional[bool] = response.pop("view_only") + if "price_increment" in response: + self.price_increment: Optional[str] = response.pop("price_increment") + if "display_name" in response: + self.display_name: Optional[str] = response.pop("display_name") + if "product_venue" in response: + self.product_venue: Optional[ProductVenue] = response.pop("product_venue") + if "approximate_quote_24h_volume" in response: + self.approximate_quote_24h_volume: Optional[str] = response.pop( + "approximate_quote_24h_volume" + ) + if "future_product_details" in response: + self.future_product_details: Optional[Dict[str, Any]] = response.pop( + "future_product_details" + ) + super().__init__(**response) + + +# Get Public Product Candles Response +class GetPublicProductCandlesResponse(BaseResponse): + def __init__(self, response: dict): + if "candles" in response: + self.candles: Optional[List[Candle]] = [ + Candle(**candle) for candle in response.pop("candles") + ] + super().__init__(**response) + + +# Get Public Market Trades Response +class GetPublicMarketTradesResponse(BaseResponse): + def __init__(self, response: dict): + if "trades" in response: + self.trades: Optional[List[HistoricalMarketTrade]] = [ + HistoricalMarketTrade(**trade) for trade in response.pop("trades") + ] + if "best_bid" in response: + self.best_bid: Optional[str] = response.pop("best_bid") + if "best_ask" in response: + self.best_ask: Optional[str] = response.pop("best_ask") + super().__init__(**response) diff --git a/tests/rest/serialize.py b/tests/rest/serialize.py new file mode 100644 index 0000000..3d09454 --- /dev/null +++ b/tests/rest/serialize.py @@ -0,0 +1,7 @@ +def object_to_dict(obj): + if isinstance(obj, list): + return [object_to_dict(item) for item in obj] + elif hasattr(obj, "__dict__"): + return {key: object_to_dict(value) for key, value in obj.__dict__.items()} + else: + return obj diff --git a/tests/rest/test_accounts.py b/tests/rest/test_accounts.py index 86e3f4b..0ebe317 100644 --- a/tests/rest/test_accounts.py +++ b/tests/rest/test_accounts.py @@ -3,6 +3,8 @@ from requests_mock import Mocker from coinbase.rest import RESTClient +from coinbase.rest.types.accounts_types import ListAccountsResponse +from tests.rest.serialize import object_to_dict from ..constants import TEST_API_KEY, TEST_API_SECRET @@ -11,7 +13,10 @@ class AccountsTest(unittest.TestCase): def test_get_accounts(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) - expected_response = {"accounts": [{"uuid": "account1"}, {"name": "account2"}]} + expected_response = { + "accounts": [{"uuid": "account1"}, {"name": "account2"}], + "has_next": False, + } with Mocker() as m: m.request( @@ -22,14 +27,18 @@ def test_get_accounts(self): accounts = client.get_accounts( limit=2, cursor="abcd", retail_portfolio_id="portfolio1" ) - captured_request = m.request_history[0] - self.assertEqual( captured_request.query, "limit=2&cursor=abcd&retail_portfolio_id=portfolio1", ) - self.assertEqual(accounts, expected_response) + actual_response_dict = object_to_dict(accounts) + expected_response_dict = object_to_dict( + ListAccountsResponse(expected_response) + ) + print(actual_response_dict) + print(expected_response_dict) + self.assertEqual(actual_response_dict, expected_response_dict) def test_get_account(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -47,4 +56,4 @@ def test_get_account(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(account, expected_response) + self.assertEqual(account.__dict__, expected_response) diff --git a/tests/rest/test_convert.py b/tests/rest/test_convert.py index b0e006c..233f3ff 100644 --- a/tests/rest/test_convert.py +++ b/tests/rest/test_convert.py @@ -43,7 +43,7 @@ def test_create_convert_quote(self): }, }, ) - self.assertEqual(quote, expected_response) + self.assertEqual(quote.__dict__, expected_response) def test_get_convert_trade(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -64,7 +64,7 @@ def test_get_convert_trade(self): captured_request.query, "from_account=from_account&to_account=to_account", ) - self.assertEqual(trade, expected_response) + self.assertEqual(trade.__dict__, expected_response) def test_commit_convert_trade(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -87,4 +87,4 @@ def test_commit_convert_trade(self): captured_json, {"from_account": "from_account", "to_account": "to_account"}, ) - self.assertEqual(trade, expected_response) + self.assertEqual(trade.__dict__, expected_response) diff --git a/tests/rest/test_data_api.py b/tests/rest/test_data_api.py index 3003335..0de96b5 100644 --- a/tests/rest/test_data_api.py +++ b/tests/rest/test_data_api.py @@ -26,4 +26,4 @@ def test_get_api_key_permissions(self): ) key_permissions = client.get_api_key_permissions() - self.assertEqual(key_permissions, expected_response) + self.assertEqual(key_permissions.__dict__, expected_response) diff --git a/tests/rest/test_fees.py b/tests/rest/test_fees.py index 808aa72..736e077 100644 --- a/tests/rest/test_fees.py +++ b/tests/rest/test_fees.py @@ -29,4 +29,4 @@ def test_get_transaction_summary(self): captured_request.query, "product_type=product_type&contract_expiry_type=contract_expiry_type&product_venue=product_venue", ) - self.assertEqual(summary, expected_response) + self.assertEqual(summary.__dict__, expected_response) diff --git a/tests/rest/test_futures.py b/tests/rest/test_futures.py index 970bcce..956be2f 100644 --- a/tests/rest/test_futures.py +++ b/tests/rest/test_futures.py @@ -24,7 +24,7 @@ def test_get_futures_balance_summary(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(balance_summary, expected_response) + self.assertEqual(balance_summary.__dict__, expected_response) def test_list_futures_positions(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -42,7 +42,7 @@ def test_list_futures_positions(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(positions, expected_response) + self.assertEqual(positions.__dict__, expected_response) def test_get_futures_position(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -60,7 +60,7 @@ def test_get_futures_position(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(position, expected_response) + self.assertEqual(position.__dict__, expected_response) def test_schedule_futures_sweep(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -80,7 +80,7 @@ def test_schedule_futures_sweep(self): self.assertEqual(captured_request.query, "") self.assertEqual(captured_json, {"usd_amount": "5"}) - self.assertEqual(response, expected_response) + self.assertEqual(response.__dict__, expected_response) def test_list_futures_sweeps(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -98,7 +98,7 @@ def test_list_futures_sweeps(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(sweeps, expected_response) + self.assertEqual(sweeps.__dict__, expected_response) def test_cancel_pending_futures_sweep(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -116,7 +116,7 @@ def test_cancel_pending_futures_sweep(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(delete, expected_response) + self.assertEqual(delete.__dict__, expected_response) def test_get_intraday_margin_setting(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -134,7 +134,7 @@ def test_get_intraday_margin_setting(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(intraday_margin_setting, expected_response) + self.assertEqual(intraday_margin_setting.__dict__, expected_response) def test_get_current_margin_window(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -154,7 +154,7 @@ def test_get_current_margin_window(self): self.assertEqual( captured_request.query, "margin_profile_type=margin_profile_type_1" ) - self.assertEqual(margin_window, expected_response) + self.assertEqual(margin_window.__dict__, expected_response) def test_set_intraday_margin_setting(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -181,4 +181,4 @@ def test_set_intraday_margin_setting(self): }, ) - self.assertEqual(setting, expected_response) + self.assertEqual(setting.__dict__, expected_response) diff --git a/tests/rest/test_market_data.py b/tests/rest/test_market_data.py index c0d2b99..5e9a692 100644 --- a/tests/rest/test_market_data.py +++ b/tests/rest/test_market_data.py @@ -29,7 +29,7 @@ def test_get_candles(self): captured_request.query, "start=1640995200&end=1641081600&granularity=five_minute&limit=2", ) - self.assertEqual(candles, expected_response) + self.assertEqual(candles.__dict__, expected_response) def test_get_market_trades(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -51,4 +51,4 @@ def test_get_market_trades(self): self.assertEqual( captured_request.query, "limit=10&start=1640995200&end=1641081600" ) - self.assertEqual(trades, expected_response) + self.assertEqual(trades.__dict__, expected_response) diff --git a/tests/rest/test_orders.py b/tests/rest/test_orders.py index 92e8877..0a09096 100644 --- a/tests/rest/test_orders.py +++ b/tests/rest/test_orders.py @@ -3,8 +3,10 @@ from requests_mock import Mocker from coinbase.rest import RESTClient +from coinbase.rest.types.orders_types import ListOrdersResponse from ..constants import TEST_API_KEY, TEST_API_SECRET +from .serialize import object_to_dict class OrdersTest(unittest.TestCase): @@ -49,7 +51,7 @@ def test_create_order(self): "retail_portfolio_id": "portfolio_id_1", }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_market_order(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -69,7 +71,6 @@ def test_market_order(self): captured_request = m.request_history[0] captured_json = captured_request.json() - self.assertEqual(captured_request.query, "") self.assertEqual( captured_json, @@ -80,7 +81,7 @@ def test_market_order(self): "order_configuration": {"market_market_ioc": {"quote_size": "1"}}, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_market_order_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -109,7 +110,7 @@ def test_market_order_buy(self): "order_configuration": {"market_market_ioc": {"quote_size": "1"}}, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_market_order_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -138,7 +139,7 @@ def test_market_order_sell(self): "order_configuration": {"market_market_ioc": {"base_size": "1"}}, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_ioc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -170,7 +171,7 @@ def test_limit_order_ioc(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_ioc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -202,7 +203,7 @@ def test_limit_order_ioc_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_ioc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -234,7 +235,7 @@ def test_limit_order_ioc_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_gtc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -275,7 +276,7 @@ def test_limit_order_gtc(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_gtc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -315,7 +316,7 @@ def test_limit_order_gtc_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_gtc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -355,7 +356,7 @@ def test_limit_order_gtc_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_gtd(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -397,7 +398,7 @@ def test_limit_order_gtd(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_gtd_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -434,7 +435,7 @@ def test_limit_order_gtd_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_gtd_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -471,7 +472,7 @@ def test_limit_order_gtd_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_fok(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -503,7 +504,7 @@ def test_limit_order_fok(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_fok_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -535,7 +536,7 @@ def test_limit_order_fok_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_limit_order_fok_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -567,7 +568,7 @@ def test_limit_order_fok_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_stop_limit_order_gtc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -610,7 +611,7 @@ def test_stop_limit_order_gtc(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_stop_limit_order_gtc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -652,7 +653,7 @@ def test_stop_limit_order_gtc_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_stop_limit_order_gtc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -694,7 +695,7 @@ def test_stop_limit_order_gtc_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_stop_limit_order_gtd(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -739,7 +740,7 @@ def test_stop_limit_order_gtd(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_stop_limit_order_gtd_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -783,7 +784,7 @@ def test_stop_limit_order_gtd_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_stop_limit_order_gtd_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -827,7 +828,7 @@ def test_stop_limit_order_gtd_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_trigger_bracket_order_gtc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -868,7 +869,7 @@ def test_trigger_bracket_order_gtc(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_trigger_bracket_order_gtc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -904,7 +905,7 @@ def test_trigger_bracket_order_gtc_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_trigger_bracket_order_gtc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -940,7 +941,7 @@ def test_trigger_bracket_order_gtc_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_trigger_bracket_order_gtd(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -983,7 +984,7 @@ def test_trigger_bracket_order_gtd(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_trigger_bracket_order_gtd_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1025,7 +1026,7 @@ def test_trigger_bracket_order_gtd_buy(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_trigger_bracket_order_gtd_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1067,7 +1068,7 @@ def test_trigger_bracket_order_gtd_sell(self): }, }, ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_get_order(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1085,7 +1086,7 @@ def test_get_order(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_list_orders(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1111,7 +1112,11 @@ def test_list_orders(self): captured_request.query, "product_ids=product_id_1&product_ids=product_id_2&order_status=open&limit=2&product_type=spot", ) - self.assertEqual(orders, expected_response) + actual_response_dict = object_to_dict(orders) + expected_response_dict = object_to_dict( + ListOrdersResponse(expected_response) + ) + self.assertEqual(actual_response_dict, expected_response_dict) def test_get_fills(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1138,7 +1143,7 @@ def test_get_fills(self): captured_request.query, "order_ids=1234&product_ids=product_id_1&retail_portfolio_id=portfolio_id_1&limit=2&cursor=abc", ) - self.assertEqual(orders, expected_response) + self.assertEqual(orders.__dict__, expected_response) def test_edit_order(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1160,7 +1165,7 @@ def test_edit_order(self): self.assertEqual( captured_json, {"order_id": "order_id_1", "size": "100", "price": "50"} ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_preview_edit_order(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1182,7 +1187,7 @@ def test_preview_edit_order(self): self.assertEqual( captured_json, {"order_id": "order_id_1", "size": "100", "price": "50"} ) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_cancel_orders(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1202,7 +1207,7 @@ def test_cancel_orders(self): self.assertEqual(captured_request.query, "") self.assertEqual(captured_json, {"order_ids": ["order_id_1", "order_id_2"]}) - self.assertEqual(order, expected_response) + self.assertEqual(order.__dict__, expected_response) def test_preview_order(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1242,7 +1247,7 @@ def test_preview_order(self): "retail_portfolio_id": "portfolio_id_1", }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_market_order(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1270,7 +1275,7 @@ def test_preview_market_order(self): "order_configuration": {"market_market_ioc": {"quote_size": "1"}}, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_market_order_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1298,7 +1303,7 @@ def test_preview_market_order_buy(self): "order_configuration": {"market_market_ioc": {"quote_size": "1"}}, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_market_order_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1326,7 +1331,7 @@ def test_preview_market_order_sell(self): "order_configuration": {"market_market_ioc": {"base_size": "1"}}, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_ioc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1355,7 +1360,7 @@ def test_preview_limit_order_ioc(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_ioc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1384,7 +1389,7 @@ def test_preview_limit_order_ioc_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_ioc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1413,7 +1418,7 @@ def test_preview_limit_order_ioc_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_gtc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1452,7 +1457,7 @@ def test_preview_limit_order_gtc(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_gtc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1490,7 +1495,7 @@ def test_preview_limit_order_gtc_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_gtc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1528,7 +1533,7 @@ def test_preview_limit_order_gtc_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_gtd(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1568,7 +1573,7 @@ def test_preview_limit_order_gtd(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_gtd_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1604,7 +1609,7 @@ def test_preview_limit_order_gtd_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_gtd_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1640,7 +1645,7 @@ def test_preview_limit_order_gtd_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_fok(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1669,7 +1674,7 @@ def test_preview_limit_order_fok(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_fok_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1698,7 +1703,7 @@ def test_preview_limit_order_fok_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_limit_order_fok_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1727,7 +1732,7 @@ def test_preview_limit_order_fok_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_stop_limit_order_gtc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1768,7 +1773,7 @@ def test_preview_stop_limit_order_gtc(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_stop_limit_order_gtc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1808,7 +1813,7 @@ def test_preview_stop_limit_order_gtc_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_stop_limit_order_gtc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1848,7 +1853,7 @@ def test_preview_stop_limit_order_gtc_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_stop_limit_order_gtd(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1891,7 +1896,7 @@ def test_preview_stop_limit_order_gtd(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_stop_limit_order_gtd_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1933,7 +1938,7 @@ def test_preview_stop_limit_order_gtd_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_stop_limit_order_gtd_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -1975,7 +1980,7 @@ def test_preview_stop_limit_order_gtd_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_trigger_bracket_order_gtc(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -2014,7 +2019,7 @@ def test_preview_trigger_bracket_order_gtc(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_trigger_bracket_order_gtc_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -2049,7 +2054,7 @@ def test_preview_trigger_bracket_order_gtc_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_trigger_bracket_gtc_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -2084,7 +2089,7 @@ def test_preview_trigger_bracket_gtc_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_trigger_bracket_order_gtd(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -2125,7 +2130,7 @@ def test_preview_trigger_bracket_order_gtd(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_trigger_bracket_order_gtd_buy(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -2165,7 +2170,7 @@ def test_preview_trigger_bracket_order_gtd_buy(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_preview_trigger_bracket_gtd_sell(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -2201,7 +2206,7 @@ def test_preview_trigger_bracket_gtd_sell(self): }, }, ) - self.assertEqual(preview, expected_response) + self.assertEqual(preview.__dict__, expected_response) def test_close_position(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -2233,4 +2238,4 @@ def test_close_position(self): "size": "100", }, ) - self.assertEqual(closedOrder, expected_response) + self.assertEqual(closedOrder.__dict__, expected_response) diff --git a/tests/rest/test_payments.py b/tests/rest/test_payments.py index df7ce6c..caba6cd 100644 --- a/tests/rest/test_payments.py +++ b/tests/rest/test_payments.py @@ -24,7 +24,7 @@ def test_list_payment_methods(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(payments, expected_response) + self.assertEqual(payments.__dict__, expected_response) def test_get_payment_method(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -42,4 +42,4 @@ def test_get_payment_method(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(payment, expected_response) + self.assertEqual(payment.__dict__, expected_response) diff --git a/tests/rest/test_perpetuals.py b/tests/rest/test_perpetuals.py index 3343ee0..651dc77 100644 --- a/tests/rest/test_perpetuals.py +++ b/tests/rest/test_perpetuals.py @@ -39,7 +39,7 @@ def test_allocate_portfolio(self): "currency": "USD", }, ) - self.assertEqual(response, expected_response) + self.assertEqual(response.__dict__, expected_response) def test_get_perps_portfolio_summary(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -57,7 +57,7 @@ def test_get_perps_portfolio_summary(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(portfolios, expected_response) + self.assertEqual(portfolios.__dict__, expected_response) def test_list_perps_positions(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -75,7 +75,7 @@ def test_list_perps_positions(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(portfolios, expected_response) + self.assertEqual(portfolios.__dict__, expected_response) def test_get_perps_position(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -95,7 +95,7 @@ def test_get_perps_position(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(portfolios, expected_response) + self.assertEqual(portfolios.__dict__, expected_response) def test_get_perps_portfolio_balances(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -113,7 +113,7 @@ def test_get_perps_portfolio_balances(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(portfolios, expected_response) + self.assertEqual(portfolios.__dict__, expected_response) def test_opt_in_or_out_multi_asset_collateral(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -142,4 +142,4 @@ def test_opt_in_or_out_multi_asset_collateral(self): "multi_asset_collateral_enabled": True, }, ) - self.assertEqual(response, expected_response) + self.assertEqual(response.__dict__, expected_response) diff --git a/tests/rest/test_portfolios.py b/tests/rest/test_portfolios.py index 404dcd0..9dccfa6 100644 --- a/tests/rest/test_portfolios.py +++ b/tests/rest/test_portfolios.py @@ -24,7 +24,7 @@ def test_get_portfolios(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "portfolio_type=default") - self.assertEqual(portfolios, expected_response) + self.assertEqual(portfolios.__dict__, expected_response) def test_create_portfolio(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -44,7 +44,7 @@ def test_create_portfolio(self): self.assertEqual(captured_request.query, "") self.assertEqual(captured_json, {"name": "Test Portfolio"}) - self.assertEqual(portfolio, expected_response) + self.assertEqual(portfolio.__dict__, expected_response) def test_get_portfolio_breakdown(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -62,7 +62,7 @@ def test_get_portfolio_breakdown(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "currency=usd") - self.assertEqual(breakdown, expected_response) + self.assertEqual(breakdown.__dict__, expected_response) def test_move_portfolio_funds(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -89,7 +89,7 @@ def test_move_portfolio_funds(self): "target_portfolio_uuid": "5678", }, ) - self.assertEqual(move, expected_response) + self.assertEqual(move.__dict__, expected_response) def test_edit_portfolio(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -109,7 +109,7 @@ def test_edit_portfolio(self): self.assertEqual(captured_request.query, "") self.assertEqual(captured_json, {"name": "Test Portfolio"}) - self.assertEqual(edit, expected_response) + self.assertEqual(edit.__dict__, expected_response) def test_delete_portfolio(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -127,4 +127,4 @@ def test_delete_portfolio(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(delete, expected_response) + self.assertEqual(delete.__dict__, expected_response) diff --git a/tests/rest/test_products.py b/tests/rest/test_products.py index 2368c34..eeb2dd7 100644 --- a/tests/rest/test_products.py +++ b/tests/rest/test_products.py @@ -27,7 +27,7 @@ def test_get_products(self): captured_request.query, "limit=2&product_type=spot&get_tradability_status=false&get_all_products=false", ) - self.assertEqual(products, expected_response) + self.assertEqual(products.__dict__, expected_response) def test_get_product(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -45,7 +45,7 @@ def test_get_product(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "get_tradability_status=false") - self.assertEqual(product, expected_response) + self.assertEqual(product.__dict__, expected_response) def test_get_product_book(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -63,7 +63,7 @@ def test_get_product_book(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "product_id=product_1&limit=10") - self.assertEqual(book, expected_response) + self.assertEqual(book.__dict__, expected_response) def test_get_best_bid_ask(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -83,4 +83,4 @@ def test_get_best_bid_ask(self): self.assertEqual( captured_request.query, "product_ids=product_1&product_ids=product_2" ) - self.assertEqual(bid_ask, expected_response) + self.assertEqual(bid_ask.__dict__, expected_response) diff --git a/tests/rest/test_public.py b/tests/rest/test_public.py index 1c15e47..e2c91ad 100644 --- a/tests/rest/test_public.py +++ b/tests/rest/test_public.py @@ -25,7 +25,7 @@ def test_authenticated_request(self): captured_headers = captured_request.headers self.assertEqual(captured_request.query, "") - self.assertEqual(time, expected_response) + self.assertEqual(time.__dict__, expected_response) self.assertIn("Authorization", captured_headers) def test_unauthenticated_request(self): @@ -45,7 +45,7 @@ def test_unauthenticated_request(self): captured_headers = captured_request.headers self.assertEqual(captured_request.query, "") - self.assertEqual(time, expected_response) + self.assertEqual(time.__dict__, expected_response) self.assertNotIn("Authorization", captured_headers) def test_get_time(self): @@ -64,7 +64,7 @@ def test_get_time(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(time, expected_response) + self.assertEqual(time.__dict__, expected_response) def test_get_public_product_book(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -82,7 +82,7 @@ def test_get_public_product_book(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "product_id=product_1&limit=10") - self.assertEqual(book, expected_response) + self.assertEqual(book.__dict__, expected_response) def test_get_public_products(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -103,7 +103,7 @@ def test_get_public_products(self): captured_request.query, "limit=2&product_type=spot&get_all_products=false", ) - self.assertEqual(products, expected_response) + self.assertEqual(products.__dict__, expected_response) def test_get_public_product(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -121,7 +121,7 @@ def test_get_public_product(self): captured_request = m.request_history[0] self.assertEqual(captured_request.query, "") - self.assertEqual(product, expected_response) + self.assertEqual(product.__dict__, expected_response) def test_get_public_candles(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -144,7 +144,7 @@ def test_get_public_candles(self): captured_request.query, "start=1640995200&end=1641081600&granularity=five_minute&limit=2", ) - self.assertEqual(candles, expected_response) + self.assertEqual(candles.__dict__, expected_response) def test_get_public_market_trades(self): client = RESTClient(TEST_API_KEY, TEST_API_SECRET) @@ -166,4 +166,4 @@ def test_get_public_market_trades(self): self.assertEqual( captured_request.query, "limit=10&start=1640995200&end=1641081600" ) - self.assertEqual(trades, expected_response) + self.assertEqual(trades.__dict__, expected_response)