deltadefi 0.0.11__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of deltadefi might be problematic. Click here for more details.
- deltadefi/__init__.py +1 -1
- deltadefi/api.py +3 -3
- deltadefi/api_resources/auth.py +3 -4
- deltadefi/clients/__init__.py +1 -0
- deltadefi/clients/accounts.py +22 -7
- deltadefi/clients/client.py +14 -6
- deltadefi/clients/markets.py +2 -25
- deltadefi/clients/websocket.py +355 -0
- deltadefi/error.py +2 -2
- deltadefi/models/models.py +3 -3
- deltadefi/responses/accounts.py +18 -6
- deltadefi/responses/responses.py +4 -4
- {deltadefi-0.0.11.dist-info → deltadefi-0.1.0.dist-info}/METADATA +19 -19
- deltadefi-0.1.0.dist-info/RECORD +22 -0
- {deltadefi-0.0.11.dist-info → deltadefi-0.1.0.dist-info}/WHEEL +1 -1
- deltadefi/clients/app.py +0 -23
- deltadefi/lib/__init__.py +0 -0
- deltadefi/lib/utils.py +0 -46
- deltadefi-0.0.11.dist-info/RECORD +0 -24
deltadefi/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# flake8: noqa
|
|
2
|
-
from .clients import ApiClient
|
|
2
|
+
from .clients import ApiClient, WebSocketClient
|
deltadefi/api.py
CHANGED
|
@@ -6,7 +6,7 @@ from deltadefi.error import ClientError, ServerError
|
|
|
6
6
|
from deltadefi.lib.utils import clean_none_value, encoded_string
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class API
|
|
9
|
+
class API:
|
|
10
10
|
def __init__(self, base_url=None, api_key=None, timeout=None, **kwargs):
|
|
11
11
|
self.base_url = base_url
|
|
12
12
|
self.api_key = api_key
|
|
@@ -73,10 +73,10 @@ class API(object):
|
|
|
73
73
|
if 400 <= status_code < 500:
|
|
74
74
|
try:
|
|
75
75
|
err = json.loads(response.text)
|
|
76
|
-
except json.JSONDecodeError:
|
|
76
|
+
except json.JSONDecodeError as e:
|
|
77
77
|
raise ClientError(
|
|
78
78
|
status_code, None, response.text, response.headers, None
|
|
79
|
-
)
|
|
79
|
+
) from e
|
|
80
80
|
error_data = None
|
|
81
81
|
if "data" in err:
|
|
82
82
|
error_data = err["data"]
|
deltadefi/api_resources/auth.py
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
@dataclass
|
|
6
5
|
class AuthHeaders:
|
|
7
6
|
jwt: str
|
|
8
|
-
|
|
7
|
+
api_key: str
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
class ApiHeaders:
|
|
12
11
|
__annotations__ = {
|
|
13
12
|
"Content-Type": str,
|
|
14
|
-
"Authorization":
|
|
15
|
-
"X-API-KEY":
|
|
13
|
+
"Authorization": str | None,
|
|
14
|
+
"X-API-KEY": str | None,
|
|
16
15
|
}
|
deltadefi/clients/__init__.py
CHANGED
deltadefi/clients/accounts.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#
|
|
2
|
-
from typing import List
|
|
3
2
|
|
|
4
3
|
from sidan_gin import Asset, UTxO
|
|
5
4
|
|
|
@@ -12,7 +11,6 @@ from deltadefi.responses import (
|
|
|
12
11
|
CreateNewAPIKeyResponse,
|
|
13
12
|
GetAccountBalanceResponse,
|
|
14
13
|
GetDepositRecordsResponse,
|
|
15
|
-
GetOrderRecordResponse,
|
|
16
14
|
GetWithdrawalRecordsResponse,
|
|
17
15
|
SubmitDepositTransactionResponse,
|
|
18
16
|
SubmitWithdrawalTransactionResponse,
|
|
@@ -20,6 +18,8 @@ from deltadefi.responses import (
|
|
|
20
18
|
from deltadefi.responses.accounts import (
|
|
21
19
|
BuildTransferalTransactionResponse,
|
|
22
20
|
GetOperationKeyResponse,
|
|
21
|
+
GetOrderRecordResponse,
|
|
22
|
+
GetOrderRecordsResponse,
|
|
23
23
|
SubmitTransferalTransactionResponse,
|
|
24
24
|
)
|
|
25
25
|
|
|
@@ -78,7 +78,7 @@ class Accounts(API):
|
|
|
78
78
|
|
|
79
79
|
def get_order_records(
|
|
80
80
|
self, status: OrderStatusType, **kwargs
|
|
81
|
-
) ->
|
|
81
|
+
) -> GetOrderRecordsResponse:
|
|
82
82
|
"""
|
|
83
83
|
Get order records.
|
|
84
84
|
|
|
@@ -89,7 +89,7 @@ class Accounts(API):
|
|
|
89
89
|
page: Optional; The page number for pagination. Defaults to 1.
|
|
90
90
|
|
|
91
91
|
Returns:
|
|
92
|
-
A
|
|
92
|
+
A GetOrderRecordsResponse object containing the order records.
|
|
93
93
|
"""
|
|
94
94
|
check_required_parameter(status, "status")
|
|
95
95
|
payload = {"status": status, **kwargs}
|
|
@@ -97,6 +97,21 @@ class Accounts(API):
|
|
|
97
97
|
url_path = "/order-records"
|
|
98
98
|
return self.send_request("GET", self.group_url_path + url_path, payload)
|
|
99
99
|
|
|
100
|
+
def get_order_record(self, order_id: str, **kwargs) -> GetOrderRecordResponse:
|
|
101
|
+
"""
|
|
102
|
+
Get a single order record by order ID.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
order_id: The ID of the order to retrieve.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
A GetOrderRecordResponse object containing the order record.
|
|
109
|
+
"""
|
|
110
|
+
check_required_parameter(order_id, "order_id")
|
|
111
|
+
|
|
112
|
+
url_path = f"/order/{order_id}"
|
|
113
|
+
return self.send_request("GET", self.group_url_path + url_path, kwargs)
|
|
114
|
+
|
|
100
115
|
def get_account_balance(self, **kwargs) -> GetAccountBalanceResponse:
|
|
101
116
|
"""
|
|
102
117
|
Get account balance.
|
|
@@ -108,7 +123,7 @@ class Accounts(API):
|
|
|
108
123
|
return self.send_request("GET", self.group_url_path + url_path, kwargs)
|
|
109
124
|
|
|
110
125
|
def build_deposit_transaction(
|
|
111
|
-
self, deposit_amount:
|
|
126
|
+
self, deposit_amount: list[Asset], input_utxos: list[UTxO], **kwargs
|
|
112
127
|
) -> BuildDepositTransactionResponse:
|
|
113
128
|
"""
|
|
114
129
|
Build a deposit transaction.
|
|
@@ -133,7 +148,7 @@ class Accounts(API):
|
|
|
133
148
|
return self.send_request("POST", self.group_url_path + url_path, payload)
|
|
134
149
|
|
|
135
150
|
def build_withdrawal_transaction(
|
|
136
|
-
self, withdrawal_amount:
|
|
151
|
+
self, withdrawal_amount: list[Asset], **kwargs
|
|
137
152
|
) -> BuildWithdrawalTransactionResponse:
|
|
138
153
|
"""
|
|
139
154
|
Build a withdrawal transaction.
|
|
@@ -152,7 +167,7 @@ class Accounts(API):
|
|
|
152
167
|
return self.send_request("POST", self.group_url_path + url_path, payload)
|
|
153
168
|
|
|
154
169
|
def build_transferal_transaction(
|
|
155
|
-
self, transferal_amount:
|
|
170
|
+
self, transferal_amount: list[Asset], to_address: str, **kwargs
|
|
156
171
|
) -> BuildTransferalTransactionResponse:
|
|
157
172
|
"""
|
|
158
173
|
Build a transferal transaction.
|
deltadefi/clients/client.py
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
# flake8: noqa: E501
|
|
2
1
|
from sidan_gin import Wallet, decrypt_with_cipher
|
|
3
2
|
|
|
4
3
|
from deltadefi.clients.accounts import Accounts
|
|
5
|
-
from deltadefi.clients.app import App
|
|
6
4
|
from deltadefi.clients.markets import Market
|
|
7
5
|
from deltadefi.clients.orders import Order
|
|
6
|
+
from deltadefi.clients.websocket import WebSocketClient
|
|
8
7
|
from deltadefi.models.models import OrderSide, OrderType
|
|
9
8
|
from deltadefi.responses import PostOrderResponse
|
|
10
9
|
|
|
@@ -17,9 +16,9 @@ class ApiClient:
|
|
|
17
16
|
def __init__(
|
|
18
17
|
self,
|
|
19
18
|
network: str = "preprod",
|
|
20
|
-
api_key: str = None,
|
|
21
|
-
base_url: str = None,
|
|
22
|
-
master_wallet: Wallet = None,
|
|
19
|
+
api_key: str | None = None,
|
|
20
|
+
base_url: str | None = None,
|
|
21
|
+
master_wallet: Wallet | None = None,
|
|
23
22
|
):
|
|
24
23
|
"""
|
|
25
24
|
Initialize the ApiClient.
|
|
@@ -43,10 +42,19 @@ class ApiClient:
|
|
|
43
42
|
self.master_wallet = master_wallet
|
|
44
43
|
|
|
45
44
|
self.accounts = Accounts(base_url=self.base_url, api_key=api_key)
|
|
46
|
-
self.app = App(base_url=self.base_url, api_key=api_key)
|
|
47
45
|
self.orders = Order(base_url=self.base_url, api_key=api_key)
|
|
48
46
|
self.markets = Market(base_url=self.base_url, api_key=api_key)
|
|
49
47
|
|
|
48
|
+
# Initialize WebSocket client with correct stream URL
|
|
49
|
+
if network == "mainnet":
|
|
50
|
+
ws_base_url = (
|
|
51
|
+
"wss://stream.deltadefi.io" # TODO: Update when mainnet is available
|
|
52
|
+
)
|
|
53
|
+
else:
|
|
54
|
+
ws_base_url = "wss://stream-staging.deltadefi.io"
|
|
55
|
+
|
|
56
|
+
self.websocket = WebSocketClient(base_url=ws_base_url, api_key=api_key)
|
|
57
|
+
|
|
50
58
|
def load_operation_key(self, password: str):
|
|
51
59
|
"""
|
|
52
60
|
Load the operation key from the wallet using the provided password.
|
deltadefi/clients/markets.py
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
# flake8: noqa: E501
|
|
2
|
-
|
|
3
1
|
from typing import Literal
|
|
4
2
|
|
|
5
3
|
from deltadefi.api import API
|
|
6
4
|
from deltadefi.lib.utils import check_required_parameter, check_required_parameters
|
|
7
|
-
from deltadefi.responses import
|
|
8
|
-
GetAggregatedPriceResponse,
|
|
9
|
-
GetMarketDepthResponse,
|
|
10
|
-
GetMarketPriceResponse,
|
|
11
|
-
)
|
|
5
|
+
from deltadefi.responses import GetAggregatedPriceResponse, GetMarketPriceResponse
|
|
12
6
|
|
|
13
7
|
|
|
14
8
|
class Market(API):
|
|
@@ -21,23 +15,6 @@ class Market(API):
|
|
|
21
15
|
def __init__(self, api_key=None, base_url=None, **kwargs):
|
|
22
16
|
super().__init__(api_key=api_key, base_url=base_url, **kwargs)
|
|
23
17
|
|
|
24
|
-
def get_depth(self, symbol: str, **kwargs) -> GetMarketDepthResponse:
|
|
25
|
-
"""
|
|
26
|
-
Get market depth.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
data: A GetMarketDepthRequest object containing the market pair.
|
|
30
|
-
|
|
31
|
-
Returns:
|
|
32
|
-
A GetMarketDepthResponse object containing the market depth.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
check_required_parameter(symbol, "symbol")
|
|
36
|
-
payload = {"symbol": symbol, **kwargs}
|
|
37
|
-
url_path = "/depth"
|
|
38
|
-
|
|
39
|
-
return self.send_request("GET", self.group_url_path + url_path, payload)
|
|
40
|
-
|
|
41
18
|
def get_market_price(self, symbol: str, **kwargs) -> GetMarketPriceResponse:
|
|
42
19
|
"""
|
|
43
20
|
Get market price.
|
|
@@ -78,7 +55,7 @@ class Market(API):
|
|
|
78
55
|
[end, "end"],
|
|
79
56
|
]
|
|
80
57
|
)
|
|
81
|
-
url_path = f"/
|
|
58
|
+
url_path = f"/graph/{symbol}"
|
|
82
59
|
return self.send_request(
|
|
83
60
|
"GET",
|
|
84
61
|
self.group_url_path + url_path,
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import websockets
|
|
8
|
+
|
|
9
|
+
from deltadefi.error import ClientError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WebSocketClient:
|
|
13
|
+
"""
|
|
14
|
+
WebSocket client for DeltaDeFi real-time data streams.
|
|
15
|
+
|
|
16
|
+
Supports:
|
|
17
|
+
- Recent trades
|
|
18
|
+
- Account streams
|
|
19
|
+
- Market price streams
|
|
20
|
+
- Market depth streams
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
base_url: str = "wss://stream-staging.deltadefi.io",
|
|
26
|
+
api_key: str | None = None,
|
|
27
|
+
auto_reconnect: bool = True,
|
|
28
|
+
reconnect_interval: int = 5,
|
|
29
|
+
ping_interval: int = 20,
|
|
30
|
+
ping_timeout: int = 10,
|
|
31
|
+
):
|
|
32
|
+
"""
|
|
33
|
+
Initialize the WebSocket client.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
base_url: WebSocket base URL
|
|
37
|
+
api_key: API key for authentication
|
|
38
|
+
auto_reconnect: Whether to automatically reconnect on disconnect
|
|
39
|
+
reconnect_interval: Seconds to wait before reconnection attempt
|
|
40
|
+
ping_interval: Seconds between ping frames
|
|
41
|
+
ping_timeout: Timeout for pong response
|
|
42
|
+
"""
|
|
43
|
+
self.base_url = base_url.rstrip("/")
|
|
44
|
+
self.api_key = api_key
|
|
45
|
+
self.auto_reconnect = auto_reconnect
|
|
46
|
+
self.reconnect_interval = reconnect_interval
|
|
47
|
+
self.ping_interval = ping_interval
|
|
48
|
+
self.ping_timeout = ping_timeout
|
|
49
|
+
|
|
50
|
+
self.websocket: websockets.WebSocketServerProtocol | None = None
|
|
51
|
+
self.subscriptions: dict[str, dict[str, Any]] = {}
|
|
52
|
+
self.message_handlers: dict[str, Callable] = {}
|
|
53
|
+
self.is_connected = False
|
|
54
|
+
self.should_stop = False
|
|
55
|
+
|
|
56
|
+
self.logger = logging.getLogger(__name__)
|
|
57
|
+
|
|
58
|
+
async def connect(self, endpoint_path: str = "") -> None:
|
|
59
|
+
"""
|
|
60
|
+
Establish WebSocket connection.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
endpoint_path: Specific endpoint path for the connection
|
|
64
|
+
"""
|
|
65
|
+
try:
|
|
66
|
+
# Build the full WebSocket URL
|
|
67
|
+
if endpoint_path:
|
|
68
|
+
url = f"{self.base_url}{endpoint_path}"
|
|
69
|
+
else:
|
|
70
|
+
url = f"{self.base_url}/ws"
|
|
71
|
+
|
|
72
|
+
# Add API key as query parameter if provided
|
|
73
|
+
if self.api_key:
|
|
74
|
+
separator = "&" if "?" in url else "?"
|
|
75
|
+
url = f"{url}{separator}api_key={self.api_key}"
|
|
76
|
+
|
|
77
|
+
self.websocket = await websockets.connect(
|
|
78
|
+
url,
|
|
79
|
+
ping_interval=self.ping_interval,
|
|
80
|
+
ping_timeout=self.ping_timeout,
|
|
81
|
+
)
|
|
82
|
+
self.is_connected = True
|
|
83
|
+
self.logger.info(f"WebSocket connected successfully to {url}")
|
|
84
|
+
|
|
85
|
+
# Start message listening loop
|
|
86
|
+
self._listen_task = asyncio.create_task(self._listen_messages())
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
self.logger.error(f"Failed to connect to WebSocket: {e}")
|
|
90
|
+
raise ClientError(0, "WS_CONNECTION_ERROR", str(e), {}, None) from e
|
|
91
|
+
|
|
92
|
+
async def disconnect(self) -> None:
|
|
93
|
+
"""Close WebSocket connection."""
|
|
94
|
+
self.should_stop = True
|
|
95
|
+
if self.websocket:
|
|
96
|
+
await self.websocket.close()
|
|
97
|
+
self.is_connected = False
|
|
98
|
+
self.logger.info("WebSocket disconnected")
|
|
99
|
+
|
|
100
|
+
async def _listen_messages(self) -> None:
|
|
101
|
+
"""Listen for incoming WebSocket messages."""
|
|
102
|
+
if not self.websocket:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
async for message in self.websocket:
|
|
107
|
+
if self.should_stop:
|
|
108
|
+
break
|
|
109
|
+
|
|
110
|
+
await self._handle_message(message)
|
|
111
|
+
|
|
112
|
+
except websockets.exceptions.ConnectionClosed:
|
|
113
|
+
self.is_connected = False
|
|
114
|
+
self.logger.warning("WebSocket connection closed")
|
|
115
|
+
|
|
116
|
+
if self.auto_reconnect and not self.should_stop:
|
|
117
|
+
await self._reconnect()
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
self.logger.error(f"Error in message listener: {e}")
|
|
121
|
+
|
|
122
|
+
async def _handle_message(self, message: str) -> None:
|
|
123
|
+
"""Handle incoming WebSocket message."""
|
|
124
|
+
try:
|
|
125
|
+
data = json.loads(message)
|
|
126
|
+
|
|
127
|
+
# Determine message type based on structure
|
|
128
|
+
if isinstance(data, list) and len(data) > 0 and "timestamp" in data[0]:
|
|
129
|
+
# This is a trade stream message (array format)
|
|
130
|
+
if "trade" in self.message_handlers:
|
|
131
|
+
await self.message_handlers["trade"](data)
|
|
132
|
+
else:
|
|
133
|
+
self.logger.debug("No handler for trade stream")
|
|
134
|
+
|
|
135
|
+
elif isinstance(data, dict) and "type" in data:
|
|
136
|
+
# Handle typed messages (account, price, etc.)
|
|
137
|
+
msg_type = data.get("type", "unknown").lower()
|
|
138
|
+
sub_type = data.get("sub_type", "").lower()
|
|
139
|
+
|
|
140
|
+
if msg_type == "account":
|
|
141
|
+
# Account stream message
|
|
142
|
+
if "account" in self.message_handlers:
|
|
143
|
+
await self.message_handlers["account"](data)
|
|
144
|
+
else:
|
|
145
|
+
self.logger.debug("No handler for account stream")
|
|
146
|
+
|
|
147
|
+
elif msg_type == "market" and sub_type == "market_price":
|
|
148
|
+
# Price stream message
|
|
149
|
+
if "price" in self.message_handlers:
|
|
150
|
+
await self.message_handlers["price"](data)
|
|
151
|
+
else:
|
|
152
|
+
self.logger.debug("No handler for price stream")
|
|
153
|
+
|
|
154
|
+
else:
|
|
155
|
+
self.logger.debug(
|
|
156
|
+
f"Unknown message type: {msg_type}, sub_type: {sub_type}"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
elif (
|
|
160
|
+
isinstance(data, dict)
|
|
161
|
+
and "timestamp" in data
|
|
162
|
+
and ("bids" in data or "asks" in data)
|
|
163
|
+
):
|
|
164
|
+
# This is a depth stream message
|
|
165
|
+
if "depth" in self.message_handlers:
|
|
166
|
+
await self.message_handlers["depth"](data)
|
|
167
|
+
else:
|
|
168
|
+
self.logger.debug("No handler for depth stream")
|
|
169
|
+
|
|
170
|
+
else:
|
|
171
|
+
self.logger.debug(f"Unknown message format: {data}")
|
|
172
|
+
|
|
173
|
+
except json.JSONDecodeError:
|
|
174
|
+
self.logger.error(f"Failed to parse message: {message}")
|
|
175
|
+
except Exception as e:
|
|
176
|
+
self.logger.error(f"Error handling message: {e}")
|
|
177
|
+
|
|
178
|
+
async def _reconnect(self) -> None:
|
|
179
|
+
"""Attempt to reconnect WebSocket."""
|
|
180
|
+
self.logger.info(
|
|
181
|
+
f"Attempting to reconnect in {self.reconnect_interval} seconds"
|
|
182
|
+
)
|
|
183
|
+
await asyncio.sleep(self.reconnect_interval)
|
|
184
|
+
|
|
185
|
+
try:
|
|
186
|
+
# For now, just reconnect to the first subscription if any exist
|
|
187
|
+
# In a more complex implementation, you'd want to handle multiple concurrent subscriptions
|
|
188
|
+
if self.subscriptions:
|
|
189
|
+
first_sub = next(iter(self.subscriptions.values()))
|
|
190
|
+
if first_sub.get("type") == "trade":
|
|
191
|
+
await self.connect(first_sub["endpoint"])
|
|
192
|
+
else:
|
|
193
|
+
await self.connect()
|
|
194
|
+
else:
|
|
195
|
+
await self.connect()
|
|
196
|
+
|
|
197
|
+
except Exception as e:
|
|
198
|
+
self.logger.error(f"Reconnection failed: {e}")
|
|
199
|
+
if self.auto_reconnect and not self.should_stop:
|
|
200
|
+
await self._reconnect()
|
|
201
|
+
|
|
202
|
+
async def _send_message(self, message: dict[str, Any]) -> None:
|
|
203
|
+
"""Send message to WebSocket server."""
|
|
204
|
+
if not self.websocket or not self.is_connected:
|
|
205
|
+
raise ClientError(
|
|
206
|
+
0, "WS_NOT_CONNECTED", "WebSocket not connected", {}, None
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
await self.websocket.send(json.dumps(message))
|
|
211
|
+
except Exception as e:
|
|
212
|
+
self.logger.error(f"Failed to send message: {e}")
|
|
213
|
+
raise ClientError(0, "WS_SEND_ERROR", str(e), {}, None) from e
|
|
214
|
+
|
|
215
|
+
def register_handler(self, stream_type: str, handler: Callable) -> None:
|
|
216
|
+
"""
|
|
217
|
+
Register a message handler for a specific stream type.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
stream_type: Type of stream (e.g., 'trade', 'depth', 'price', 'account')
|
|
221
|
+
handler: Async function to handle messages
|
|
222
|
+
"""
|
|
223
|
+
self.message_handlers[stream_type] = handler
|
|
224
|
+
|
|
225
|
+
async def subscribe_trades(self, symbol: str) -> None:
|
|
226
|
+
"""
|
|
227
|
+
Subscribe to recent trades for a symbol using DeltaDeFi's specific endpoint.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
symbol: Trading pair symbol (e.g., "ADAUSDM")
|
|
231
|
+
"""
|
|
232
|
+
if not self.api_key:
|
|
233
|
+
raise ClientError(
|
|
234
|
+
0, "API_KEY_REQUIRED", "API key required for trade streams", {}, None
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
# Close existing connection if any
|
|
238
|
+
if self.websocket:
|
|
239
|
+
await self.disconnect()
|
|
240
|
+
|
|
241
|
+
# Connect to the specific trades endpoint
|
|
242
|
+
endpoint_path = f"/market/recent-trades/{symbol}?limit=50"
|
|
243
|
+
await self.connect(endpoint_path)
|
|
244
|
+
|
|
245
|
+
# Store subscription info
|
|
246
|
+
self.subscriptions[f"trade_{symbol}"] = {
|
|
247
|
+
"type": "trade",
|
|
248
|
+
"symbol": symbol,
|
|
249
|
+
"endpoint": endpoint_path,
|
|
250
|
+
}
|
|
251
|
+
self.logger.info(f"Subscribed to trades for {symbol}")
|
|
252
|
+
|
|
253
|
+
async def subscribe_depth(self, symbol: str) -> None:
|
|
254
|
+
"""
|
|
255
|
+
Subscribe to market depth for a symbol using DeltaDeFi's specific endpoint.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
symbol: Trading pair symbol (e.g., "ADAUSDM")
|
|
259
|
+
"""
|
|
260
|
+
if not self.api_key:
|
|
261
|
+
raise ClientError(
|
|
262
|
+
0, "API_KEY_REQUIRED", "API key required for depth streams", {}, None
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Close existing connection if any
|
|
266
|
+
if self.websocket:
|
|
267
|
+
await self.disconnect()
|
|
268
|
+
|
|
269
|
+
# Connect to the specific depth endpoint
|
|
270
|
+
endpoint_path = f"/market/depth/{symbol}"
|
|
271
|
+
await self.connect(endpoint_path)
|
|
272
|
+
|
|
273
|
+
# Store subscription info
|
|
274
|
+
self.subscriptions[f"depth_{symbol}"] = {
|
|
275
|
+
"type": "depth",
|
|
276
|
+
"symbol": symbol,
|
|
277
|
+
"endpoint": endpoint_path,
|
|
278
|
+
}
|
|
279
|
+
self.logger.info(f"Subscribed to depth for {symbol}")
|
|
280
|
+
|
|
281
|
+
async def subscribe_price(self, symbol: str) -> None:
|
|
282
|
+
"""
|
|
283
|
+
Subscribe to price streams for a symbol using DeltaDeFi's specific endpoint.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
symbol: Trading pair symbol (e.g., "ADAUSDM")
|
|
287
|
+
"""
|
|
288
|
+
if not self.api_key:
|
|
289
|
+
raise ClientError(
|
|
290
|
+
0, "API_KEY_REQUIRED", "API key required for price streams", {}, None
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
# Close existing connection if any
|
|
294
|
+
if self.websocket:
|
|
295
|
+
await self.disconnect()
|
|
296
|
+
|
|
297
|
+
# Connect to the specific price endpoint
|
|
298
|
+
endpoint_path = f"/market/market-price/{symbol}"
|
|
299
|
+
await self.connect(endpoint_path)
|
|
300
|
+
|
|
301
|
+
# Store subscription info
|
|
302
|
+
self.subscriptions[f"price_{symbol}"] = {
|
|
303
|
+
"type": "price",
|
|
304
|
+
"symbol": symbol,
|
|
305
|
+
"endpoint": endpoint_path,
|
|
306
|
+
}
|
|
307
|
+
self.logger.info(f"Subscribed to price for {symbol}")
|
|
308
|
+
|
|
309
|
+
async def subscribe_account(self) -> None:
|
|
310
|
+
"""
|
|
311
|
+
Subscribe to account streams using DeltaDeFi's specific endpoint.
|
|
312
|
+
Provides balance updates and order status updates.
|
|
313
|
+
"""
|
|
314
|
+
if not self.api_key:
|
|
315
|
+
raise ClientError(
|
|
316
|
+
0, "API_KEY_REQUIRED", "API key required for account streams", {}, None
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
# Close existing connection if any
|
|
320
|
+
if self.websocket:
|
|
321
|
+
await self.disconnect()
|
|
322
|
+
|
|
323
|
+
# Connect to the account stream endpoint
|
|
324
|
+
endpoint_path = "/accounts/stream"
|
|
325
|
+
await self.connect(endpoint_path)
|
|
326
|
+
|
|
327
|
+
# Store subscription info
|
|
328
|
+
self.subscriptions["account"] = {"type": "account", "endpoint": endpoint_path}
|
|
329
|
+
self.logger.info("Subscribed to account streams")
|
|
330
|
+
|
|
331
|
+
async def unsubscribe(self, subscription_key: str) -> None:
|
|
332
|
+
"""
|
|
333
|
+
Unsubscribe from a stream.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
subscription_key: Key of the subscription to cancel
|
|
337
|
+
"""
|
|
338
|
+
if subscription_key not in self.subscriptions:
|
|
339
|
+
return
|
|
340
|
+
|
|
341
|
+
sub_data = self.subscriptions[subscription_key]
|
|
342
|
+
message = {
|
|
343
|
+
"method": "UNSUBSCRIBE",
|
|
344
|
+
"params": sub_data["params"],
|
|
345
|
+
"id": sub_data["id"],
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
await self._send_message(message)
|
|
349
|
+
del self.subscriptions[subscription_key]
|
|
350
|
+
self.logger.info(f"Unsubscribed from {subscription_key}")
|
|
351
|
+
|
|
352
|
+
async def unsubscribe_all(self) -> None:
|
|
353
|
+
"""Unsubscribe from all streams."""
|
|
354
|
+
for sub_key in list(self.subscriptions.keys()):
|
|
355
|
+
await self.unsubscribe(sub_key)
|
deltadefi/error.py
CHANGED
|
@@ -27,7 +27,7 @@ class ParameterRequiredError(Error):
|
|
|
27
27
|
self.params = params
|
|
28
28
|
|
|
29
29
|
def __str__(self):
|
|
30
|
-
return "
|
|
30
|
+
return "{} is mandatory, but received empty.".format(", ".join(self.params))
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class ParameterValueError(Error):
|
|
@@ -35,7 +35,7 @@ class ParameterValueError(Error):
|
|
|
35
35
|
self.params = params
|
|
36
36
|
|
|
37
37
|
def __str__(self):
|
|
38
|
-
return "the enum value
|
|
38
|
+
return "the enum value {} is invalid.".format(", ".join(self.params))
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
class ParameterTypeError(Error):
|
deltadefi/models/models.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Literal
|
|
3
3
|
|
|
4
4
|
OrderStatusType = Literal["openOrder", "orderHistory", "tradingHistory"]
|
|
5
5
|
|
|
@@ -59,7 +59,7 @@ class OrderJSON:
|
|
|
59
59
|
class DepositRecord:
|
|
60
60
|
created_at: str
|
|
61
61
|
status: TransactionStatus
|
|
62
|
-
assets:
|
|
62
|
+
assets: list[AssetRecord]
|
|
63
63
|
tx_hash: str
|
|
64
64
|
|
|
65
65
|
|
|
@@ -67,7 +67,7 @@ class DepositRecord:
|
|
|
67
67
|
class WithdrawalRecord:
|
|
68
68
|
created_at: str
|
|
69
69
|
status: TransactionStatus
|
|
70
|
-
assets:
|
|
70
|
+
assets: list[AssetRecord]
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
@dataclass
|
deltadefi/responses/accounts.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TypedDict
|
|
3
3
|
|
|
4
4
|
from deltadefi.models.models import (
|
|
5
5
|
AssetBalance,
|
|
@@ -32,19 +32,31 @@ class SubmitDepositTransactionResponse(TypedDict):
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
@dataclass
|
|
35
|
-
class GetDepositRecordsResponse(
|
|
35
|
+
class GetDepositRecordsResponse(list[DepositRecord]):
|
|
36
36
|
pass
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
@dataclass
|
|
40
|
-
class GetWithdrawalRecordsResponse(
|
|
40
|
+
class GetWithdrawalRecordsResponse(list[WithdrawalRecord]):
|
|
41
41
|
pass
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
@dataclass
|
|
45
|
+
class OrderRecordsData(TypedDict):
|
|
46
|
+
orders: list[OrderJSON]
|
|
47
|
+
order_filling_records: list[OrderFillingRecordJSON]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class GetOrderRecordsResponse(TypedDict):
|
|
52
|
+
data: list[OrderRecordsData]
|
|
53
|
+
total_count: int
|
|
54
|
+
total_page: int
|
|
55
|
+
|
|
56
|
+
|
|
44
57
|
@dataclass
|
|
45
58
|
class GetOrderRecordResponse(TypedDict):
|
|
46
|
-
|
|
47
|
-
order_filling_records: List[OrderFillingRecordJSON]
|
|
59
|
+
order_json: OrderJSON
|
|
48
60
|
|
|
49
61
|
|
|
50
62
|
@dataclass
|
|
@@ -76,5 +88,5 @@ class GetAccountInfoResponse(TypedDict):
|
|
|
76
88
|
|
|
77
89
|
|
|
78
90
|
@dataclass
|
|
79
|
-
class GetAccountBalanceResponse(
|
|
91
|
+
class GetAccountBalanceResponse(list[AssetBalance]):
|
|
80
92
|
pass
|
deltadefi/responses/responses.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TypedDict
|
|
3
3
|
|
|
4
4
|
from deltadefi.models import OrderJSON
|
|
5
5
|
|
|
@@ -17,8 +17,8 @@ class MarketDepth(TypedDict):
|
|
|
17
17
|
|
|
18
18
|
@dataclass
|
|
19
19
|
class GetMarketDepthResponse(TypedDict):
|
|
20
|
-
bids:
|
|
21
|
-
asks:
|
|
20
|
+
bids: list[MarketDepth]
|
|
21
|
+
asks: list[MarketDepth]
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@dataclass
|
|
@@ -38,7 +38,7 @@ class Trade(TypedDict):
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
@dataclass
|
|
41
|
-
class GetAggregatedPriceResponse(
|
|
41
|
+
class GetAggregatedPriceResponse(list[Trade]):
|
|
42
42
|
pass
|
|
43
43
|
|
|
44
44
|
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: deltadefi
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: Python SDK for DeltaDeFi protocol.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Requires-Python: >3.11,<4.0.0
|
|
5
|
+
Author-email: HinsonSIDAN <wongkahinhinson@gmail.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Keywords: cardano,defi,sdk,trading
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
9
|
Classifier: Intended Audience :: Developers
|
|
11
10
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
11
|
Classifier: Natural Language :: English
|
|
13
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Classifier:
|
|
17
|
-
|
|
18
|
-
Requires-
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: <4.0.0,>3.11
|
|
19
|
+
Requires-Dist: certifi>=2024.8.30
|
|
20
|
+
Requires-Dist: charset-normalizer>=3.4.0
|
|
21
|
+
Requires-Dist: idna>=3.10
|
|
22
|
+
Requires-Dist: pycardano>=0.12.3
|
|
23
|
+
Requires-Dist: python-dotenv>=0.9.9
|
|
24
|
+
Requires-Dist: requests>=2.25.0
|
|
25
|
+
Requires-Dist: sidan-gin>=0.1.6
|
|
26
|
+
Requires-Dist: urllib3>=2.2.3
|
|
27
|
+
Requires-Dist: websockets>=12.0
|
|
27
28
|
Description-Content-Type: text/markdown
|
|
28
29
|
|
|
29
30
|
# DeltaDeFi Python SDK
|
|
@@ -119,4 +120,3 @@ DELTADEFI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx make test
|
|
|
119
120
|
## License
|
|
120
121
|
|
|
121
122
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
|
|
122
|
-
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
deltadefi/__init__.py,sha256=pKZHfRdXT3f3kncxAKamtk5V3EDQB8Ocy8xBmjhsJ4A,63
|
|
2
|
+
deltadefi/api.py,sha256=g5N7O_xzrl5hsQuw-ZhJ9lQi5rKzgr3_-C9FViRlOuw,2724
|
|
3
|
+
deltadefi/error.py,sha256=zDMx5ukb5zs0AOeGAHjXiIMDZ0LbEcaGyVi45WFJfmI,1658
|
|
4
|
+
deltadefi/api_resources/__init__.py,sha256=_SGHTpaQTIBvh9Rm868IT5pXpvvGBPqz3bxkY6YapZ4,61
|
|
5
|
+
deltadefi/api_resources/auth.py,sha256=4QCEI4P4UlQPQYctqY9Oat4hn7lsI95QihHTD_0PZKg,245
|
|
6
|
+
deltadefi/api_resources/validation.py,sha256=vz-hovpLy9SMOIFGcBHC8vWZH8CJRlQP8rcbbTSM-PM,1375
|
|
7
|
+
deltadefi/clients/__init__.py,sha256=4hyPuk6_bcJGXUElOvkgZ7ARlQ6QwKLp-nFgCXTbFVI,76
|
|
8
|
+
deltadefi/clients/accounts.py,sha256=3bOHKYIBJYsOgb97rw57u9aJV9VyHb1U8l_rGXBOwp4,8411
|
|
9
|
+
deltadefi/clients/client.py,sha256=2hLOsxqBc8eu_6ovuYLRoK2popdI1_t3pGcEP8Keu9A,4619
|
|
10
|
+
deltadefi/clients/markets.py,sha256=JQUj3duj1dLEA36NW4Rk44_ALAMLrlK37ylxnu5kTCc,1989
|
|
11
|
+
deltadefi/clients/orders.py,sha256=gnh8AcXWI1QQK9riJtsu_1BqzuOml5OGf4bFP6yfy9g,3890
|
|
12
|
+
deltadefi/clients/websocket.py,sha256=0454RunoE9eHqmQ0wrywEwxqrie1qEXq2ObxyKXopck,12424
|
|
13
|
+
deltadefi/constants/__init__.py,sha256=7LkrzfLTJsCCUl5IgZYrl-AbY_cf1fftcLklgnBYDTs,40
|
|
14
|
+
deltadefi/constants/constants.py,sha256=4bkY4kfNcsgoCe1xU8n2We7w-vxZXyzVw5rQvAsx4j8,168
|
|
15
|
+
deltadefi/models/__init__.py,sha256=oDJj6Y4gXN6C7Oz_t2fq8hej-D0G9OqfXjL4Jaeq8z8,37
|
|
16
|
+
deltadefi/models/models.py,sha256=kiRpCdzUh3WmyuFOaxlZ1rjsQ2cxLWjVFBCqsHXMtBc,1633
|
|
17
|
+
deltadefi/responses/__init__.py,sha256=JKSIUQu6qI_XhbAR2mVMCKNvR6x_vFZdyLGOuQTVrVY,64
|
|
18
|
+
deltadefi/responses/accounts.py,sha256=o-It4vyNsiDeCmHa-XQl77KuCVtJi7qlPdn059fgwcI,1590
|
|
19
|
+
deltadefi/responses/responses.py,sha256=Kz5PtDnx_AgKrV7NhZqrSMnS1wPlLbu13J2BKNzN0ME,1012
|
|
20
|
+
deltadefi-0.1.0.dist-info/METADATA,sha256=lkvqD6KUiekc--8-QROKHZ7G7HKCah8cwJfanmMJjo4,3075
|
|
21
|
+
deltadefi-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
22
|
+
deltadefi-0.1.0.dist-info/RECORD,,
|
deltadefi/clients/app.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
from deltadefi.api import API
|
|
2
|
-
from deltadefi.responses import GetTermsAndConditionResponse
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class App(API):
|
|
6
|
-
"""
|
|
7
|
-
App client for interacting with the DeltaDeFi API.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
group_url_path = "/app"
|
|
11
|
-
|
|
12
|
-
def __init__(self, api_key=None, base_url=None, **kwargs):
|
|
13
|
-
super().__init__(api_key=api_key, base_url=base_url, **kwargs)
|
|
14
|
-
|
|
15
|
-
def get_terms_and_condition(self, **kwargs) -> GetTermsAndConditionResponse:
|
|
16
|
-
"""
|
|
17
|
-
Get terms and conditions.
|
|
18
|
-
|
|
19
|
-
Returns:
|
|
20
|
-
A GetTermsAndConditionResponse object containing the terms and conditions.
|
|
21
|
-
"""
|
|
22
|
-
url_path = "/terms-and-conditions"
|
|
23
|
-
return self.send_request("GET", self.group_url_path + url_path, kwargs)
|
deltadefi/lib/__init__.py
DELETED
|
File without changes
|
deltadefi/lib/utils.py
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
from urllib.parse import urlencode
|
|
2
|
-
|
|
3
|
-
from deltadefi.error import (
|
|
4
|
-
ParameterRequiredError,
|
|
5
|
-
ParameterTypeError,
|
|
6
|
-
ParameterValueError,
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def clean_none_value(d) -> dict:
|
|
11
|
-
out = {}
|
|
12
|
-
for k in d.keys():
|
|
13
|
-
if d[k] is not None:
|
|
14
|
-
out[k] = d[k]
|
|
15
|
-
return out
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def check_required_parameter(value, name):
|
|
19
|
-
if not value and value != 0:
|
|
20
|
-
raise ParameterRequiredError([name])
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def check_required_parameters(params):
|
|
24
|
-
"""Validate multiple parameters
|
|
25
|
-
params = [
|
|
26
|
-
['btcusdt', 'symbol'],
|
|
27
|
-
[10, 'price']
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
"""
|
|
31
|
-
for p in params:
|
|
32
|
-
check_required_parameter(p[0], p[1])
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def check_enum_parameter(value, enum_class):
|
|
36
|
-
if value not in set(item.value for item in enum_class):
|
|
37
|
-
raise ParameterValueError([value])
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def check_type_parameter(value, name, data_type):
|
|
41
|
-
if value is not None and not isinstance(value, data_type):
|
|
42
|
-
raise ParameterTypeError([name, data_type])
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def encoded_string(query):
|
|
46
|
-
return urlencode(query, True).replace("%40", "@")
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
deltadefi/__init__.py,sha256=_dbB-toNXZvwZxj5DnEY0nW5noDnDpF4QsJNEwGO_IA,46
|
|
2
|
-
deltadefi/api.py,sha256=XSdOFwq9s2HFxKxiv7ljaCgUhwXVAkkq19dPSRhwlek,2720
|
|
3
|
-
deltadefi/api_resources/__init__.py,sha256=_SGHTpaQTIBvh9Rm868IT5pXpvvGBPqz3bxkY6YapZ4,61
|
|
4
|
-
deltadefi/api_resources/auth.py,sha256=Mpl4Dbh_d_gGhwLo2CtBSKxZ21DC74x-qjVhlczZCDE,278
|
|
5
|
-
deltadefi/api_resources/validation.py,sha256=vz-hovpLy9SMOIFGcBHC8vWZH8CJRlQP8rcbbTSM-PM,1375
|
|
6
|
-
deltadefi/clients/__init__.py,sha256=GEEsW2Sl-fPq0ilDsNyztoCDO7JSed14uMN2gOurIOI,37
|
|
7
|
-
deltadefi/clients/accounts.py,sha256=L1170nEd67YXadKDi0uGybuqgx9Xx6X3caO7CXL_t3U,7912
|
|
8
|
-
deltadefi/clients/app.py,sha256=TOgRlP83p91r7oS4ez8Gfm8soQzFHrJAmOHZJoGZ4SM,712
|
|
9
|
-
deltadefi/clients/client.py,sha256=khtgJYE4m6VFPLylVUe5a52SWu6kzdtHdse7XXy0LoE,4284
|
|
10
|
-
deltadefi/clients/markets.py,sha256=v8hK06oXC73qS3IjvWDempHq_-9T6OW2pckIcDR7P2M,2580
|
|
11
|
-
deltadefi/clients/orders.py,sha256=gnh8AcXWI1QQK9riJtsu_1BqzuOml5OGf4bFP6yfy9g,3890
|
|
12
|
-
deltadefi/constants/__init__.py,sha256=7LkrzfLTJsCCUl5IgZYrl-AbY_cf1fftcLklgnBYDTs,40
|
|
13
|
-
deltadefi/constants/constants.py,sha256=4bkY4kfNcsgoCe1xU8n2We7w-vxZXyzVw5rQvAsx4j8,168
|
|
14
|
-
deltadefi/error.py,sha256=Pq55p7FQbVn1GTih7NQBI7ZcVUUrlkaFKn-SwZUxBA8,1650
|
|
15
|
-
deltadefi/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
deltadefi/lib/utils.py,sha256=zuQFAKQphbGxDdPzBURw4A2n3AkRSbzmjMLHPLm9Ed4,1035
|
|
17
|
-
deltadefi/models/__init__.py,sha256=oDJj6Y4gXN6C7Oz_t2fq8hej-D0G9OqfXjL4Jaeq8z8,37
|
|
18
|
-
deltadefi/models/models.py,sha256=Fgk3W6Ps1tibnE3cJTaBt5OPfVKl70nIDxDFsu1m5bk,1639
|
|
19
|
-
deltadefi/responses/__init__.py,sha256=JKSIUQu6qI_XhbAR2mVMCKNvR6x_vFZdyLGOuQTVrVY,64
|
|
20
|
-
deltadefi/responses/accounts.py,sha256=pUs3_M-kMprN_kCn0wda1Ox3hvoF1irE2zdCRKeP6ZU,1393
|
|
21
|
-
deltadefi/responses/responses.py,sha256=JZrnBWZZGM_yyulrcgYNdJyw-8bOhlsmMTK3xZbuBKM,1018
|
|
22
|
-
deltadefi-0.0.11.dist-info/METADATA,sha256=TdzbY7KZ2C2r3jiFfmEi9SvfPfbfCbWg3JCbJ9LPQmU,3027
|
|
23
|
-
deltadefi-0.0.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
24
|
-
deltadefi-0.0.11.dist-info/RECORD,,
|