Skip to content

Commit 7aad394

Browse files
committed
update packachore(deps): upgrade core dependencies to latest versions
- aiohttp: 3.12.13 → 3.12.15 (HTTP client improvements) - build: 1.2.2 → 1.3.0 (build system enhancements) - multidict: 6.6.3 → 6.6.4 (performance improvements) - pydantic: 2.0.0+ → 2.11.7 (validation framework updates) - pre-commit: 4.2.0 → 4.3.0 (code quality tooling) - pyright: 1.1.402 → 1.1.404 (type checking improvements) - pytest-asyncio: 1.0.0 → 1.1.0 (async testing enhancements) - ruff: 0.12.2 → 0.12.10 (linting and formatting improvements) All tests pass with updated dependencies. Updated pre-commit configuration to use new tool versions.ges. chore(deps): upgrade core dependencies to latest versions - aiohttp: 3.12.13 → 3.12.15 (HTTP client improvements) - build: 1.2.2 → 1.3.0 (build system enhancements) - multidict: 6.6.3 → 6.6.4 (performance improvements) - pydantic: 2.0.0+ → 2.11.7 (validation framework updates) - pre-commit: 4.2.0 → 4.3.0 (code quality tooling) - pyright: 1.1.402 → 1.1.404 (type checking improvements) - pytest-asyncio: 1.0.0 → 1.1.0 (async testing enhancements) - ruff: 0.12.2 → 0.12.10 (linting and formatting improvements) All tests pass with updated dependencies. Updated pre-commit configuration to use new tool versions.
1 parent 2c31899 commit 7aad394

File tree

20 files changed

+723
-17
lines changed

20 files changed

+723
-17
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ repos:
1212
- id: requirements-txt-fixer
1313

1414
- repo: https://github.com/astral-sh/ruff-pre-commit
15-
rev: v0.12.2
15+
rev: v0.12.10
1616
hooks:
1717
- id: ruff
1818
args: [--fix, --exit-non-zero-on-fix]
1919
- id: ruff-format
2020

2121
- repo: https://github.com/RobertCraigie/pyright-python
22-
rev: v1.1.402
22+
rev: v1.1.404
2323
hooks:
2424
- id: pyright

README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ Async Python client for WhiteBit API
66

77
* [Private http V4 API](https://github.com/whitebit-exchange/api-docs/blob/f7ca495281ade44f9f075a91c2e55d5da32a99fd/Private/http-trade-v4.md)
88
* [Public WS API](https://github.com/whitebit-exchange/api-docs/blob/master/Public/websocket.md)
9+
* Enhanced WebSocket events with `event_time` and `update_id` metadata
10+
* BookTicker WebSocket stream for real-time best bid/ask prices
11+
* Market depth subscriptions with enhanced metadata support
912
* [Public http v1](https://github.com/whitebit-exchange/api-docs/blob/main/docs/Public/http-v1.md)
1013
* [Public http v2](https://github.com/whitebit-exchange/api-docs/blob/main/docs/Public/http-v2.md)
1114
* [Public http v4](https://github.com/whitebit-exchange/api-docs/blob/main/docs/Public/http-v4.md)
15+
* Funding history endpoint for futures markets
1216
* Webhook support with examples
1317
* Rate limiting
1418
* Type hints
@@ -41,6 +45,62 @@ async def main():
4145
asyncio.run(main())
4246
```
4347

48+
### New Features in v0.3.0
49+
50+
#### BookTicker WebSocket Stream
51+
52+
```python
53+
import asyncio
54+
from aiowhitebit.clients.websocket import PublicWebSocketClient, SubscribeRequest
55+
56+
async def bookticker_example():
57+
client = PublicWebSocketClient()
58+
59+
# Subscribe to BookTicker stream
60+
response = await client.bookticker_subscribe("BTC_USDT")
61+
print(f"Subscribed: {response}")
62+
63+
# Unsubscribe from BookTicker stream
64+
response = await client.bookticker_unsubscribe("BTC_USDT")
65+
print(f"Unsubscribed: {response}")
66+
67+
await client.close()
68+
69+
asyncio.run(bookticker_example())
70+
```
71+
72+
#### Funding History for Futures Markets
73+
74+
```python
75+
import asyncio
76+
from aiowhitebit.clients.public import PublicV4Client
77+
78+
async def funding_history_example():
79+
client = PublicV4Client()
80+
81+
# Get funding rate history for BTC_USDT futures
82+
history = await client.get_funding_history("BTC_USDT")
83+
84+
for item in history.result:
85+
print(f"Time: {item.timestamp}, Rate: {item.funding_rate}")
86+
87+
asyncio.run(funding_history_example())
88+
```
89+
90+
#### Enhanced WebSocket Events with Metadata
91+
92+
All WebSocket events now include optional `event_time` and `update_id` fields for better tracking and synchronization:
93+
94+
```python
95+
# WebSocket responses now include metadata
96+
{
97+
"method": "depth_update",
98+
"params": {...},
99+
"event_time": 1640995200000, # Event timestamp
100+
"update_id": 12345 # Unique update identifier
101+
}
102+
```
103+
44104
## Documentation
45105

46106
For detailed documentation and examples, visit our [GitHub repository](https://github.com/doubledare704/aiowhitebit).

aiowhitebit/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
"""
66

77
# Version information
8-
__version__ = "0.2.5"
8+
__version__ = "0.3.0"

aiowhitebit/clients/public/v4.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Depth,
1515
Fee,
1616
FeeResponse,
17+
FundingHistoryResponse,
1718
FuturesMarkets,
1819
MaintenanceStatus,
1920
MarketActivity,
@@ -264,3 +265,30 @@ async def get_mining_pool_overview(self) -> MiningPoolOverview:
264265
- Recent blocks
265266
"""
266267
return await self._make_request(APIEndpoints.MINING_POOL, converter=lambda x: MiningPoolOverview(**x))
268+
269+
@rate_limit(limit=2000, window=10.0)
270+
async def get_funding_history(self, market: str) -> FundingHistoryResponse:
271+
"""Get funding rate history for a futures market.
272+
273+
Args:
274+
market: Market symbol (e.g., "BTC_USDT")
275+
276+
Returns:
277+
FundingHistoryResponse: List of funding rate history items containing:
278+
- Timestamp of the funding rate
279+
- Funding rate value
280+
281+
Raises:
282+
WhitebitValidationError: If the market parameter is invalid
283+
284+
Example:
285+
```python
286+
client = PublicV4Client()
287+
history = await client.get_funding_history("BTC_USDT")
288+
for item in history.result:
289+
print(f"Time: {item.timestamp}, Rate: {item.funding_rate}")
290+
```
291+
"""
292+
validate_market(market)
293+
endpoint = APIEndpoints.FUNDING_HISTORY_V4.format(market=market)
294+
return await self._make_request(endpoint, converter=lambda x: FundingHistoryResponse(**x))

aiowhitebit/clients/websocket/public.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,40 @@ async def market_depth(self, market: str, limit: int, intervals: str) -> WSRespo
233233
"""
234234
return await self.base_ws_requester(WSRequest(method="depth_request", params=[market, limit, intervals]))
235235

236+
async def bookticker_subscribe(self, market: str) -> WSResponse:
237+
"""Subscribe to BookTicker stream for a market.
238+
239+
Args:
240+
market: Market (e.g. BTC_USDT)
241+
242+
Returns:
243+
WebSocket response confirming subscription
244+
245+
Example:
246+
```python
247+
client = PublicWebSocketClient()
248+
response = await client.bookticker_subscribe("BTC_USDT")
249+
```
250+
"""
251+
return await self.base_ws_requester(WSRequest(method="bookTicker_subscribe", params=[market]))
252+
253+
async def bookticker_unsubscribe(self, market: str) -> WSResponse:
254+
"""Unsubscribe from BookTicker stream for a market.
255+
256+
Args:
257+
market: Market (e.g. BTC_USDT)
258+
259+
Returns:
260+
WebSocket response confirming unsubscription
261+
262+
Example:
263+
```python
264+
client = PublicWebSocketClient()
265+
response = await client.bookticker_unsubscribe("BTC_USDT")
266+
```
267+
"""
268+
return await self.base_ws_requester(WSRequest(method="bookTicker_unsubscribe", params=[market]))
269+
236270
async def close(self):
237271
"""Close the WebSocket connection.
238272

aiowhitebit/clients/websocket/subscriber.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,48 @@ def depth_subscribe(
151151
id=next(id_gen),
152152
).model_dump()
153153

154+
@staticmethod
155+
def bookticker_subscribe(market: str) -> dict:
156+
"""Build a BookTicker subscribe request.
157+
158+
Args:
159+
market: Market (e.g. BTC_USDT)
160+
161+
Returns:
162+
Subscribe request
163+
164+
Example:
165+
```python
166+
request = SubscribeRequest.bookticker_subscribe("BTC_USDT")
167+
```
168+
"""
169+
return WSRequest(
170+
method="bookTicker_subscribe",
171+
params=[market],
172+
id=next(id_gen),
173+
).model_dump()
174+
175+
@staticmethod
176+
def bookticker_unsubscribe(market: str) -> dict:
177+
"""Build a BookTicker unsubscribe request.
178+
179+
Args:
180+
market: Market (e.g. BTC_USDT)
181+
182+
Returns:
183+
Unsubscribe request
184+
185+
Example:
186+
```python
187+
request = SubscribeRequest.bookticker_unsubscribe("BTC_USDT")
188+
```
189+
"""
190+
return WSRequest(
191+
method="bookTicker_unsubscribe",
192+
params=[market],
193+
id=next(id_gen),
194+
).model_dump()
195+
154196

155197
def ws_subscribe_builder(
156198
sub_msg: dict,

aiowhitebit/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class APIEndpoints:
2323
DEPTH_V4 = "/api/v4/public/orderbook/depth/{market}" # Corrected URL
2424
TRADES_V4 = "/api/v4/public/trades/{market}"
2525
FEE_V4 = "/api/v4/public/fee"
26+
FUNDING_HISTORY_V4 = "/api/v4/public/funding-history/{market}"
2627

2728
# V2 endpoints
2829
MARKET_INFO_V2: Final = "/api/v2/public/markets"

aiowhitebit/models/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
# Add other specific imports from public.v4 module
3535
)
3636
from aiowhitebit.models.websocket import (
37+
BookTickerData,
38+
BookTickerResponse,
39+
DepthData,
40+
DepthUpdateResponse,
3741
WSError,
3842
# Add other specific imports from websocket module
3943
WSRequest,
@@ -48,8 +52,12 @@
4852
"BasePublicV2Response",
4953
"BaseResponse",
5054
"BaseWebSocketResponse",
55+
"BookTickerData",
56+
"BookTickerResponse",
5157
"CreateLimitOrderRequest",
5258
"CreateOrderResponse",
59+
"DepthData",
60+
"DepthUpdateResponse",
5361
"ExecutedOrdersResponse",
5462
"MarketActivity",
5563
"MarketInfo",

aiowhitebit/models/base.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Base models for the WhiteBit API."""
22

3-
from typing import Any
3+
from typing import Any, Optional
44

55
from pydantic import BaseModel
66

@@ -36,6 +36,12 @@ class BasePrivateResponse(BaseResponse):
3636

3737

3838
class BaseWebSocketResponse(BaseModel):
39-
"""Base model for WebSocket API responses."""
39+
"""Base model for WebSocket API responses.
4040
41-
pass
41+
Attributes:
42+
event_time: Timestamp of the event (optional for backward compatibility)
43+
update_id: Unique identifier for each update (optional for backward compatibility)
44+
"""
45+
46+
event_time: Optional[int] = None
47+
update_id: Optional[int] = None

aiowhitebit/models/public/v4/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
Depth,
1212
Fee,
1313
FeeResponse,
14+
FundingHistoryItem,
15+
FundingHistoryResponse,
1416
FuturesMarket,
1517
FuturesMarkets,
1618
MaintenanceStatus,
@@ -33,6 +35,8 @@
3335
"Depth",
3436
"Fee",
3537
"FeeResponse",
38+
"FundingHistoryItem",
39+
"FundingHistoryResponse",
3640
"FuturesMarket",
3741
"FuturesMarkets",
3842
"MaintenanceStatus",

0 commit comments

Comments
 (0)