Skip to content

Commit

Permalink
Release v1.8.1 (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidMkCb authored Nov 15, 2024
1 parent 2250dbd commit b162d94
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 17 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## [1.8.1] - 2024-NOV-15

### Added
- Support for converting custom REST and WebSocket response type objects to dict via new `to_dict()` function

### Fixed
- Importing from `coinbase.websocket.types`

## [1.8.0] - 2024-NOV-12

### Added
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ You are able to use any of the API hooks to make calls to the Coinbase API. For
from json import dumps

accounts = client.get_accounts()
print(dumps(accounts, indent=2))
print(dumps(accounts.to_dict(), indent=2))

order = client.market_order_buy(client_order_id="clientOrderId", product_id="BTC-USD", quote_size="1")
print(dumps(order, indent=2))
print(dumps(order.to_dict(), indent=2))
```
This code calls the `get_accounts` and `market_order_buy` endpoints.

Expand Down Expand Up @@ -270,14 +270,21 @@ The functions described above handle the asynchronous nature of WebSocket connec
We similarly provide async channel specific methods for subscribing and unsubscribing such as `ticker_async`, `ticker_unsubscribe_async`, etc.

### WebSocket Response Types
For your convenience, we have provided a custom, built-in WebSocket response type object to help interact with our WebSocket feeds more easily.
For your convenience, we have provided a custom, built-in WebSocket response type object to help interact with our WebSocket feeds more easily.
Simply import it from the same module as you do the `WSClient`:

```python
from coinbase.websocket import WSClient, WebsocketResponse
```

Assume we simply want the price feed for BTC-USD and ETH-USD.
Like we did in previous steps, we subscribe to the `ticker` channel and include 'BTC-USD' and 'ETH-USD' in the `product_ids` list.
As the data comes through, it is passed into the `on_message` function. From there, we use it to build the `WebsocketResponse` object.

Using said object, we can now extract only the desired parts. In our case, we retrieve and print only the `product_id` and `price` fields, resulting in a cleaner feed.
```python
from coinbase.websocket import WSClient, WebsocketResponse

def on_message(msg):
ws_object = WebsocketResponse(json.loads(msg))
if ws_object.channel == "ticker" :
Expand Down Expand Up @@ -366,7 +373,7 @@ from coinbase.rest import RESTClient
client = RESTClient()
public_products = client.get_public_products()
print(public_products)
print(json.dumps(public_products.to_dict(), indent=2))
```
_Full list of all public REST endpoints [here](https://docs.cdp.coinbase.com/advanced-trade/docs/rest-api-overview#public-endpoints)_

Expand Down
2 changes: 1 addition & 1 deletion coinbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.8.0"
__version__ = "1.8.1"
14 changes: 14 additions & 0 deletions coinbase/rest/types/base_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,17 @@ def __getitem__(self, key: str) -> Any:

def __repr__(self):
return str(self.__dict__)

def to_dict(self) -> dict:
dict_response = {}
for key, value in self.__dict__.items():
if isinstance(value, BaseResponse):
dict_response[key] = value.to_dict()
elif isinstance(value, list):
dict_response[key] = [
item.to_dict() if isinstance(item, BaseResponse) else item
for item in value
]
else:
dict_response[key] = value
return dict_response
Empty file.
14 changes: 14 additions & 0 deletions coinbase/websocket/types/base_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,17 @@ def __getitem__(self, key: str) -> Any:

def __repr__(self):
return str(self.__dict__)

def to_dict(self) -> dict:
dict_response = {}
for key, value in self.__dict__.items():
if isinstance(value, BaseResponse):
dict_response[key] = value.to_dict()
elif isinstance(value, list):
dict_response[key] = [
item.to_dict() if isinstance(item, BaseResponse) else item
for item in value
]
else:
dict_response[key] = value
return dict_response
9 changes: 2 additions & 7 deletions tests/rest/test_accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

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

Expand Down Expand Up @@ -32,12 +31,8 @@ def test_get_accounts(self):
captured_request.query,
"limit=2&cursor=abcd&retail_portfolio_id=portfolio1",
)
actual_response_dict = object_to_dict(accounts)
expected_response_dict = object_to_dict(
ListAccountsResponse(expected_response)
)
print(actual_response_dict)
print(expected_response_dict)
actual_response_dict = accounts.to_dict()
expected_response_dict = ListAccountsResponse(expected_response).to_dict()
self.assertEqual(actual_response_dict, expected_response_dict)

def test_get_account(self):
Expand Down
7 changes: 2 additions & 5 deletions tests/rest/test_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
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):
Expand Down Expand Up @@ -1112,10 +1111,8 @@ 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",
)
actual_response_dict = object_to_dict(orders)
expected_response_dict = object_to_dict(
ListOrdersResponse(expected_response)
)
actual_response_dict = orders.to_dict()
expected_response_dict = ListOrdersResponse(expected_response).to_dict()
self.assertEqual(actual_response_dict, expected_response_dict)

def test_get_fills(self):
Expand Down

0 comments on commit b162d94

Please sign in to comment.