Skip to content

Commit 7172e8e

Browse files
authored
Merge pull request #124 from okxapi/dev/BROK-653
Dev/brok 653
2 parents 1fb02f4 + 883901f commit 7172e8e

File tree

7 files changed

+1015
-43
lines changed

7 files changed

+1015
-43
lines changed

okx/websocket/WsPrivateAsync.py

Lines changed: 125 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import asyncio
22
import json
33
import logging
4+
import warnings
45

56
from okx.websocket import WsUtils
67
from okx.websocket.WebSocketFactory import WebSocketFactory
@@ -9,7 +10,7 @@
910

1011

1112
class WsPrivateAsync:
12-
def __init__(self, apiKey, passphrase, secretKey, url, useServerTime):
13+
def __init__(self, apiKey, passphrase, secretKey, url, useServerTime=None, debug=False):
1314
self.url = url
1415
self.subscriptions = set()
1516
self.callback = None
@@ -18,15 +19,25 @@ def __init__(self, apiKey, passphrase, secretKey, url, useServerTime):
1819
self.apiKey = apiKey
1920
self.passphrase = passphrase
2021
self.secretKey = secretKey
21-
self.useServerTime = useServerTime
22+
self.useServerTime = False
2223
self.websocket = None
24+
self.debug = debug
25+
26+
# Set log level
27+
if debug:
28+
logger.setLevel(logging.DEBUG)
29+
30+
# Deprecation warning for useServerTime parameter
31+
if useServerTime is not None:
32+
warnings.warn("useServerTime parameter is deprecated. Please remove it.", DeprecationWarning)
2333

2434
async def connect(self):
2535
self.websocket = await self.factory.connect()
2636

2737
async def consume(self):
2838
async for message in self.websocket:
29-
logger.debug("Received message: {%s}", message)
39+
if self.debug:
40+
logger.debug("Received message: {%s}", message)
3041
if self.callback:
3142
self.callback(message)
3243

@@ -43,6 +54,8 @@ async def subscribe(self, params: list, callback, id: str = None):
4354
if id is not None:
4455
payload_dict["id"] = id
4556
payload = json.dumps(payload_dict)
57+
if self.debug:
58+
logger.debug(f"subscribe: {payload}")
4659
await self.websocket.send(payload)
4760
# await self.consume()
4861

@@ -53,6 +66,8 @@ async def login(self):
5366
passphrase=self.passphrase,
5467
secretKey=self.secretKey
5568
)
69+
if self.debug:
70+
logger.debug(f"login: {loginPayload}")
5671
await self.websocket.send(loginPayload)
5772
return True
5873

@@ -65,16 +80,119 @@ async def unsubscribe(self, params: list, callback, id: str = None):
6580
if id is not None:
6681
payload_dict["id"] = id
6782
payload = json.dumps(payload_dict)
68-
logger.info(f"unsubscribe: {payload}")
83+
if self.debug:
84+
logger.debug(f"unsubscribe: {payload}")
85+
else:
86+
logger.info(f"unsubscribe: {payload}")
87+
await self.websocket.send(payload)
88+
89+
async def send(self, op: str, args: list, callback=None, id: str = None):
90+
"""
91+
Generic send method
92+
:param op: Operation type
93+
:param args: Parameter list
94+
:param callback: Callback function
95+
:param id: Optional request ID
96+
"""
97+
if callback:
98+
self.callback = callback
99+
payload_dict = {
100+
"op": op,
101+
"args": args
102+
}
103+
if id is not None:
104+
payload_dict["id"] = id
105+
payload = json.dumps(payload_dict)
106+
if self.debug:
107+
logger.debug(f"send: {payload}")
69108
await self.websocket.send(payload)
70-
# for param in params:
71-
# self.subscriptions.discard(param)
109+
110+
async def place_order(self, args: list, callback=None, id: str = None):
111+
"""
112+
Place order
113+
:param args: Order parameter list
114+
:param callback: Callback function
115+
:param id: Optional request ID
116+
"""
117+
if callback:
118+
self.callback = callback
119+
await self.send("order", args, id=id)
120+
121+
async def batch_orders(self, args: list, callback=None, id: str = None):
122+
"""
123+
Batch place orders
124+
:param args: Batch order parameter list
125+
:param callback: Callback function
126+
:param id: Optional request ID
127+
"""
128+
if callback:
129+
self.callback = callback
130+
await self.send("batch-orders", args, id=id)
131+
132+
async def cancel_order(self, args: list, callback=None, id: str = None):
133+
"""
134+
Cancel order
135+
:param args: Cancel order parameter list
136+
:param callback: Callback function
137+
:param id: Optional request ID
138+
"""
139+
if callback:
140+
self.callback = callback
141+
await self.send("cancel-order", args, id=id)
142+
143+
async def batch_cancel_orders(self, args: list, callback=None, id: str = None):
144+
"""
145+
Batch cancel orders
146+
:param args: Batch cancel order parameter list
147+
:param callback: Callback function
148+
:param id: Optional request ID
149+
"""
150+
if callback:
151+
self.callback = callback
152+
await self.send("batch-cancel-orders", args, id=id)
153+
154+
async def amend_order(self, args: list, callback=None, id: str = None):
155+
"""
156+
Amend order
157+
:param args: Amend order parameter list
158+
:param callback: Callback function
159+
:param id: Optional request ID
160+
"""
161+
if callback:
162+
self.callback = callback
163+
await self.send("amend-order", args, id=id)
164+
165+
async def batch_amend_orders(self, args: list, callback=None, id: str = None):
166+
"""
167+
Batch amend orders
168+
:param args: Batch amend order parameter list
169+
:param callback: Callback function
170+
:param id: Optional request ID
171+
"""
172+
if callback:
173+
self.callback = callback
174+
await self.send("batch-amend-orders", args, id=id)
175+
176+
async def mass_cancel(self, args: list, callback=None, id: str = None):
177+
"""
178+
Mass cancel orders
179+
Note: This method is for /ws/v5/business channel, rate limit: 1 request/second
180+
:param args: Cancel parameter list, contains instType and instFamily
181+
:param callback: Callback function
182+
:param id: Optional request ID
183+
"""
184+
if callback:
185+
self.callback = callback
186+
await self.send("mass-cancel", args, id=id)
72187

73188
async def stop(self):
74189
await self.factory.close()
75190

76191
async def start(self):
77-
logger.info("Connecting to WebSocket...")
192+
if self.debug:
193+
logger.debug("Connecting to WebSocket...")
194+
else:
195+
logger.info("Connecting to WebSocket...")
78196
await self.connect()
79197
self.loop.create_task(self.consume())
80198

okx/websocket/WsPublicAsync.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,60 @@
22
import json
33
import logging
44

5+
from okx.websocket import WsUtils
56
from okx.websocket.WebSocketFactory import WebSocketFactory
67

78
logger = logging.getLogger(__name__)
89

910

1011
class WsPublicAsync:
11-
def __init__(self, url):
12+
def __init__(self, url, apiKey='', passphrase='', secretKey='', debug=False):
1213
self.url = url
1314
self.subscriptions = set()
1415
self.callback = None
1516
self.loop = asyncio.get_event_loop()
1617
self.factory = WebSocketFactory(url)
1718
self.websocket = None
19+
self.debug = debug
20+
# Credentials for business channel login
21+
self.apiKey = apiKey
22+
self.passphrase = passphrase
23+
self.secretKey = secretKey
24+
self.isLoggedIn = False
25+
26+
# Set log level
27+
if debug:
28+
logger.setLevel(logging.DEBUG)
1829

1930
async def connect(self):
2031
self.websocket = await self.factory.connect()
2132

2233
async def consume(self):
2334
async for message in self.websocket:
24-
logger.debug("Received message: {%s}", message)
35+
if self.debug:
36+
logger.debug("Received message: {%s}", message)
2537
if self.callback:
2638
self.callback(message)
2739

40+
async def login(self):
41+
"""
42+
Login method for business channel that requires authentication (e.g. /ws/v5/business)
43+
"""
44+
if not self.apiKey or not self.secretKey or not self.passphrase:
45+
raise ValueError("apiKey, secretKey and passphrase are required for login")
46+
47+
loginPayload = WsUtils.initLoginParams(
48+
useServerTime=False,
49+
apiKey=self.apiKey,
50+
passphrase=self.passphrase,
51+
secretKey=self.secretKey
52+
)
53+
if self.debug:
54+
logger.debug(f"login: {loginPayload}")
55+
await self.websocket.send(loginPayload)
56+
self.isLoggedIn = True
57+
return True
58+
2859
async def subscribe(self, params: list, callback, id: str = None):
2960
self.callback = callback
3061
payload_dict = {
@@ -34,6 +65,8 @@ async def subscribe(self, params: list, callback, id: str = None):
3465
if id is not None:
3566
payload_dict["id"] = id
3667
payload = json.dumps(payload_dict)
68+
if self.debug:
69+
logger.debug(f"subscribe: {payload}")
3770
await self.websocket.send(payload)
3871
# await self.consume()
3972

@@ -46,14 +79,41 @@ async def unsubscribe(self, params: list, callback, id: str = None):
4679
if id is not None:
4780
payload_dict["id"] = id
4881
payload = json.dumps(payload_dict)
49-
logger.info(f"unsubscribe: {payload}")
82+
if self.debug:
83+
logger.debug(f"unsubscribe: {payload}")
84+
else:
85+
logger.info(f"unsubscribe: {payload}")
86+
await self.websocket.send(payload)
87+
88+
async def send(self, op: str, args: list, callback=None, id: str = None):
89+
"""
90+
Generic send method
91+
:param op: Operation type
92+
:param args: Parameter list
93+
:param callback: Callback function
94+
:param id: Optional request ID
95+
"""
96+
if callback:
97+
self.callback = callback
98+
payload_dict = {
99+
"op": op,
100+
"args": args
101+
}
102+
if id is not None:
103+
payload_dict["id"] = id
104+
payload = json.dumps(payload_dict)
105+
if self.debug:
106+
logger.debug(f"send: {payload}")
50107
await self.websocket.send(payload)
51108

52109
async def stop(self):
53110
await self.factory.close()
54111

55112
async def start(self):
56-
logger.info("Connecting to WebSocket...")
113+
if self.debug:
114+
logger.debug("Connecting to WebSocket...")
115+
else:
116+
logger.info("Connecting to WebSocket...")
57117
await self.connect()
58118
self.loop.create_task(self.consume())
59119

0 commit comments

Comments
 (0)