deltadefi 0.0.10__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 +70 -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 +28 -6
- deltadefi/responses/responses.py +4 -4
- {deltadefi-0.0.10.dist-info → deltadefi-0.1.0.dist-info}/METADATA +39 -35
- deltadefi-0.1.0.dist-info/RECORD +22 -0
- {deltadefi-0.0.10.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.10.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,12 +11,17 @@ from deltadefi.responses import (
|
|
|
12
11
|
CreateNewAPIKeyResponse,
|
|
13
12
|
GetAccountBalanceResponse,
|
|
14
13
|
GetDepositRecordsResponse,
|
|
15
|
-
GetOrderRecordResponse,
|
|
16
14
|
GetWithdrawalRecordsResponse,
|
|
17
15
|
SubmitDepositTransactionResponse,
|
|
18
16
|
SubmitWithdrawalTransactionResponse,
|
|
19
17
|
)
|
|
20
|
-
from deltadefi.responses.accounts import
|
|
18
|
+
from deltadefi.responses.accounts import (
|
|
19
|
+
BuildTransferalTransactionResponse,
|
|
20
|
+
GetOperationKeyResponse,
|
|
21
|
+
GetOrderRecordResponse,
|
|
22
|
+
GetOrderRecordsResponse,
|
|
23
|
+
SubmitTransferalTransactionResponse,
|
|
24
|
+
)
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
class Accounts(API):
|
|
@@ -74,7 +78,7 @@ class Accounts(API):
|
|
|
74
78
|
|
|
75
79
|
def get_order_records(
|
|
76
80
|
self, status: OrderStatusType, **kwargs
|
|
77
|
-
) ->
|
|
81
|
+
) -> GetOrderRecordsResponse:
|
|
78
82
|
"""
|
|
79
83
|
Get order records.
|
|
80
84
|
|
|
@@ -85,7 +89,7 @@ class Accounts(API):
|
|
|
85
89
|
page: Optional; The page number for pagination. Defaults to 1.
|
|
86
90
|
|
|
87
91
|
Returns:
|
|
88
|
-
A
|
|
92
|
+
A GetOrderRecordsResponse object containing the order records.
|
|
89
93
|
"""
|
|
90
94
|
check_required_parameter(status, "status")
|
|
91
95
|
payload = {"status": status, **kwargs}
|
|
@@ -93,6 +97,21 @@ class Accounts(API):
|
|
|
93
97
|
url_path = "/order-records"
|
|
94
98
|
return self.send_request("GET", self.group_url_path + url_path, payload)
|
|
95
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
|
+
|
|
96
115
|
def get_account_balance(self, **kwargs) -> GetAccountBalanceResponse:
|
|
97
116
|
"""
|
|
98
117
|
Get account balance.
|
|
@@ -104,7 +123,7 @@ class Accounts(API):
|
|
|
104
123
|
return self.send_request("GET", self.group_url_path + url_path, kwargs)
|
|
105
124
|
|
|
106
125
|
def build_deposit_transaction(
|
|
107
|
-
self, deposit_amount:
|
|
126
|
+
self, deposit_amount: list[Asset], input_utxos: list[UTxO], **kwargs
|
|
108
127
|
) -> BuildDepositTransactionResponse:
|
|
109
128
|
"""
|
|
110
129
|
Build a deposit transaction.
|
|
@@ -129,7 +148,7 @@ class Accounts(API):
|
|
|
129
148
|
return self.send_request("POST", self.group_url_path + url_path, payload)
|
|
130
149
|
|
|
131
150
|
def build_withdrawal_transaction(
|
|
132
|
-
self, withdrawal_amount:
|
|
151
|
+
self, withdrawal_amount: list[Asset], **kwargs
|
|
133
152
|
) -> BuildWithdrawalTransactionResponse:
|
|
134
153
|
"""
|
|
135
154
|
Build a withdrawal transaction.
|
|
@@ -147,6 +166,31 @@ class Accounts(API):
|
|
|
147
166
|
url_path = "/withdrawal/build"
|
|
148
167
|
return self.send_request("POST", self.group_url_path + url_path, payload)
|
|
149
168
|
|
|
169
|
+
def build_transferal_transaction(
|
|
170
|
+
self, transferal_amount: list[Asset], to_address: str, **kwargs
|
|
171
|
+
) -> BuildTransferalTransactionResponse:
|
|
172
|
+
"""
|
|
173
|
+
Build a transferal transaction.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
data: A BuildTransferalTransactionRequest object containing the transferal transaction details.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
A BuildTransferalTransactionResponse object containing the built transferal transaction.
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
check_required_parameter(
|
|
183
|
+
transferal_amount, "transferal_amount", to_address, "to_address"
|
|
184
|
+
)
|
|
185
|
+
payload = {
|
|
186
|
+
"transferal_amount": transferal_amount,
|
|
187
|
+
"to_address": to_address,
|
|
188
|
+
**kwargs,
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
url_path = "/transferal/build"
|
|
192
|
+
return self.send_request("POST", self.group_url_path + url_path, payload)
|
|
193
|
+
|
|
150
194
|
def submit_deposit_transaction(
|
|
151
195
|
self, signed_tx: str, **kwargs
|
|
152
196
|
) -> SubmitDepositTransactionResponse:
|
|
@@ -184,3 +228,22 @@ class Accounts(API):
|
|
|
184
228
|
|
|
185
229
|
url_path = "/withdrawal/submit"
|
|
186
230
|
return self.send_request("POST", self.group_url_path + url_path, payload)
|
|
231
|
+
|
|
232
|
+
def submit_transferal_transaction(
|
|
233
|
+
self, signed_tx: str, **kwargs
|
|
234
|
+
) -> SubmitTransferalTransactionResponse:
|
|
235
|
+
"""
|
|
236
|
+
Submit a transferal transaction.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
data: A SubmitTransferalTransactionRequest object containing the transferal transaction details.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
A SubmitTransferalTransactionResponse object containing the submitted transferal transaction.
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
check_required_parameter(signed_tx, "signed_tx")
|
|
246
|
+
payload = {"signed_tx": signed_tx, **kwargs}
|
|
247
|
+
|
|
248
|
+
url_path = "/transferal/submit"
|
|
249
|
+
return self.send_request("POST", self.group_url_path + url_path, payload)
|
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
|
|
@@ -52,11 +64,21 @@ class BuildWithdrawalTransactionResponse(TypedDict):
|
|
|
52
64
|
tx_hex: str
|
|
53
65
|
|
|
54
66
|
|
|
67
|
+
@dataclass
|
|
68
|
+
class BuildTransferalTransactionResponse(TypedDict):
|
|
69
|
+
tx_hex: str
|
|
70
|
+
|
|
71
|
+
|
|
55
72
|
@dataclass
|
|
56
73
|
class SubmitWithdrawalTransactionResponse(TypedDict):
|
|
57
74
|
tx_hash: str
|
|
58
75
|
|
|
59
76
|
|
|
77
|
+
@dataclass
|
|
78
|
+
class SubmitTransferalTransactionResponse(TypedDict):
|
|
79
|
+
tx_hash: str
|
|
80
|
+
|
|
81
|
+
|
|
60
82
|
@dataclass
|
|
61
83
|
class GetAccountInfoResponse(TypedDict):
|
|
62
84
|
api_key: str
|
|
@@ -66,5 +88,5 @@ class GetAccountInfoResponse(TypedDict):
|
|
|
66
88
|
|
|
67
89
|
|
|
68
90
|
@dataclass
|
|
69
|
-
class GetAccountBalanceResponse(
|
|
91
|
+
class GetAccountBalanceResponse(list[AssetBalance]):
|
|
70
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
|
|
@@ -56,11 +57,8 @@ from sidan_gin import HDWallet
|
|
|
56
57
|
network="preprod",
|
|
57
58
|
api_key="your_api_key",
|
|
58
59
|
|
|
59
|
-
# Initialize HDWallet
|
|
60
|
-
wallet = HDWallet("your_wallet_mnemonic")
|
|
61
|
-
|
|
62
60
|
# Initialize ApiClient
|
|
63
|
-
api = ApiClient(network=network, api_key=api_key
|
|
61
|
+
api = ApiClient(network=network, api_key=api_key)
|
|
64
62
|
```
|
|
65
63
|
|
|
66
64
|
### Accounts
|
|
@@ -73,33 +71,40 @@ account_balance = api.accounts.get_account_balance()
|
|
|
73
71
|
print(account_balance)
|
|
74
72
|
```
|
|
75
73
|
|
|
76
|
-
###
|
|
74
|
+
### Markets
|
|
77
75
|
|
|
78
76
|
The Market client allows you to interact with market-related endpoints.
|
|
79
77
|
|
|
80
78
|
```python
|
|
81
79
|
# Get market depth
|
|
82
|
-
market_depth = api.
|
|
80
|
+
market_depth = api.markets.get_depth("ADAUSDM")
|
|
83
81
|
print(market_depth_response)
|
|
84
82
|
|
|
85
83
|
# Get market price
|
|
86
|
-
market_price_response = api.
|
|
84
|
+
market_price_response = api.markets.get_market_price("ADAUSDM")
|
|
87
85
|
print(market_price_response)
|
|
88
86
|
```
|
|
89
87
|
|
|
90
|
-
###
|
|
88
|
+
### Orders
|
|
91
89
|
|
|
92
90
|
The Order client allows you to interact with order-related endpoints.
|
|
93
91
|
|
|
94
92
|
```python
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
api_key = os.environ.get("DELTADEFI_API_KEY")
|
|
94
|
+
password = os.environ.get("TRADING_PASSWORD")
|
|
95
|
+
|
|
96
|
+
api = ApiClient(api_key=api_key)
|
|
97
|
+
api.load_operation_key(password)
|
|
98
|
+
|
|
99
|
+
res = api.post_order(
|
|
100
|
+
symbol="ADAUSDM",
|
|
101
|
+
side="sell",
|
|
102
|
+
type="limit",
|
|
103
|
+
quantity=51,
|
|
104
|
+
price=15,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
print("Order submitted successfully.", res)
|
|
103
108
|
```
|
|
104
109
|
|
|
105
110
|
## Development
|
|
@@ -115,4 +120,3 @@ DELTADEFI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx make test
|
|
|
115
120
|
## License
|
|
116
121
|
|
|
117
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>
|
|
118
|
-
|
|
@@ -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=ZuzPjobGk-bk4SPC8mqDAxChCfv5vj7y96k38G84uj0,6302
|
|
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=tDjJPb_Xk0_-aEX8pNHINrhurCljEZQfI-TikCIO_D4,1227
|
|
21
|
-
deltadefi/responses/responses.py,sha256=JZrnBWZZGM_yyulrcgYNdJyw-8bOhlsmMTK3xZbuBKM,1018
|
|
22
|
-
deltadefi-0.0.10.dist-info/METADATA,sha256=s434ECRVm3WNTikx0lNU5LfkNiU8OVfev3HO7YjbRwo,3235
|
|
23
|
-
deltadefi-0.0.10.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
24
|
-
deltadefi-0.0.10.dist-info/RECORD,,
|