ccxt 4.3.17 → 4.3.19

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.
Files changed (174) hide show
  1. package/README.md +7 -5
  2. package/dist/cjs/ccxt.js +6 -1
  3. package/dist/cjs/src/abstract/woofipro.js +9 -0
  4. package/dist/cjs/src/ascendex.js +3 -4
  5. package/dist/cjs/src/base/Exchange.js +43 -3
  6. package/dist/cjs/src/base/functions/crypto.js +10 -3
  7. package/dist/cjs/src/base/functions/encode.js +6 -3
  8. package/dist/cjs/src/base/functions/number.js +8 -5
  9. package/dist/cjs/src/base/functions/rsa.js +5 -5
  10. package/dist/cjs/src/bigone.js +1 -1
  11. package/dist/cjs/src/binance.js +32 -8
  12. package/dist/cjs/src/bitfinex.js +25 -1
  13. package/dist/cjs/src/bitfinex2.js +59 -51
  14. package/dist/cjs/src/bitget.js +1 -5
  15. package/dist/cjs/src/bitmart.js +3 -3
  16. package/dist/cjs/src/bitstamp.js +1 -3
  17. package/dist/cjs/src/bybit.js +1 -0
  18. package/dist/cjs/src/coinex.js +321 -537
  19. package/dist/cjs/src/coinlist.js +1 -2
  20. package/dist/cjs/src/deribit.js +1 -1
  21. package/dist/cjs/src/hollaex.js +3 -3
  22. package/dist/cjs/src/htx.js +1 -1
  23. package/dist/cjs/src/indodax.js +1 -1
  24. package/dist/cjs/src/latoken.js +1 -1
  25. package/dist/cjs/src/mexc.js +1 -1
  26. package/dist/cjs/src/novadax.js +0 -1
  27. package/dist/cjs/src/okx.js +17 -0
  28. package/dist/cjs/src/poloniex.js +1 -2
  29. package/dist/cjs/src/pro/bitget.js +136 -192
  30. package/dist/cjs/src/pro/bybit.js +4 -2
  31. package/dist/cjs/src/pro/coinbaseinternational.js +9 -1
  32. package/dist/cjs/src/pro/okx.js +85 -0
  33. package/dist/cjs/src/pro/woofipro.js +1263 -0
  34. package/dist/cjs/src/wavesexchange.js +2 -2
  35. package/dist/cjs/src/woo.js +17 -3
  36. package/dist/cjs/src/woofipro.js +2698 -0
  37. package/js/ccxt.d.ts +8 -2
  38. package/js/ccxt.js +6 -2
  39. package/js/src/abstract/bybit.d.ts +1 -0
  40. package/js/src/abstract/okx.d.ts +1 -0
  41. package/js/src/abstract/woofipro.d.ts +122 -0
  42. package/js/src/abstract/woofipro.js +11 -0
  43. package/js/src/ace.d.ts +2 -2
  44. package/js/src/ascendex.d.ts +5 -15
  45. package/js/src/ascendex.js +3 -4
  46. package/js/src/base/Exchange.d.ts +27 -18
  47. package/js/src/base/Exchange.js +43 -3
  48. package/js/src/base/functions/crypto.d.ts +1 -1
  49. package/js/src/base/functions/crypto.js +10 -3
  50. package/js/src/base/functions/encode.d.ts +1 -1
  51. package/js/src/base/functions/encode.js +6 -3
  52. package/js/src/base/functions/number.d.ts +1 -1
  53. package/js/src/base/functions/number.js +8 -5
  54. package/js/src/base/functions/rsa.js +6 -6
  55. package/js/src/base/types.d.ts +4 -0
  56. package/js/src/bigone.d.ts +4 -14
  57. package/js/src/bigone.js +1 -1
  58. package/js/src/binance.d.ts +13 -71
  59. package/js/src/binance.js +32 -8
  60. package/js/src/binancecoinm.d.ts +2 -22
  61. package/js/src/binanceusdm.d.ts +2 -22
  62. package/js/src/bingx.d.ts +4 -14
  63. package/js/src/bit2c.d.ts +2 -2
  64. package/js/src/bitbank.d.ts +2 -2
  65. package/js/src/bitbns.d.ts +2 -2
  66. package/js/src/bitfinex.d.ts +6 -16
  67. package/js/src/bitfinex.js +25 -1
  68. package/js/src/bitfinex2.d.ts +6 -16
  69. package/js/src/bitfinex2.js +59 -51
  70. package/js/src/bitflyer.d.ts +2 -2
  71. package/js/src/bitget.d.ts +7 -17
  72. package/js/src/bitget.js +1 -5
  73. package/js/src/bithumb.d.ts +3 -3
  74. package/js/src/bitmart.d.ts +5 -14
  75. package/js/src/bitmart.js +3 -3
  76. package/js/src/bitmex.d.ts +4 -4
  77. package/js/src/bitopro.d.ts +2 -2
  78. package/js/src/bitrue.d.ts +5 -5
  79. package/js/src/bitso.d.ts +2 -2
  80. package/js/src/bitstamp.d.ts +3 -3
  81. package/js/src/bitstamp.js +1 -3
  82. package/js/src/bitteam.d.ts +2 -2
  83. package/js/src/bitvavo.d.ts +5 -5
  84. package/js/src/bl3p.d.ts +2 -2
  85. package/js/src/blockchaincom.d.ts +2 -2
  86. package/js/src/blofin.d.ts +4 -14
  87. package/js/src/btcalpha.d.ts +2 -2
  88. package/js/src/btcbox.d.ts +2 -2
  89. package/js/src/btcmarkets.d.ts +2 -2
  90. package/js/src/btcturk.d.ts +2 -2
  91. package/js/src/bybit.d.ts +8 -56
  92. package/js/src/bybit.js +1 -0
  93. package/js/src/cex.d.ts +2 -2
  94. package/js/src/coinbase.d.ts +4 -4
  95. package/js/src/coinbasepro.d.ts +3 -3
  96. package/js/src/coincheck.d.ts +2 -2
  97. package/js/src/coinex.d.ts +6 -16
  98. package/js/src/coinex.js +321 -537
  99. package/js/src/coinlist.d.ts +5 -15
  100. package/js/src/coinlist.js +1 -2
  101. package/js/src/coinmate.d.ts +2 -2
  102. package/js/src/coinmetro.d.ts +3 -3
  103. package/js/src/coinone.d.ts +2 -2
  104. package/js/src/coinsph.d.ts +2 -2
  105. package/js/src/coinspot.d.ts +2 -2
  106. package/js/src/cryptocom.d.ts +2 -2
  107. package/js/src/currencycom.d.ts +3 -3
  108. package/js/src/delta.d.ts +5 -43
  109. package/js/src/deribit.d.ts +7 -55
  110. package/js/src/deribit.js +1 -1
  111. package/js/src/digifinex.d.ts +5 -15
  112. package/js/src/exmo.d.ts +2 -2
  113. package/js/src/gate.d.ts +6 -54
  114. package/js/src/gemini.d.ts +2 -2
  115. package/js/src/hitbtc.d.ts +4 -14
  116. package/js/src/hollaex.d.ts +3 -3
  117. package/js/src/hollaex.js +3 -3
  118. package/js/src/htx.d.ts +6 -16
  119. package/js/src/htx.js +1 -1
  120. package/js/src/huobijp.d.ts +4 -4
  121. package/js/src/hyperliquid.d.ts +1 -1
  122. package/js/src/idex.d.ts +3 -3
  123. package/js/src/independentreserve.d.ts +2 -2
  124. package/js/src/indodax.d.ts +2 -2
  125. package/js/src/indodax.js +1 -1
  126. package/js/src/kraken.d.ts +4 -14
  127. package/js/src/krakenfutures.d.ts +4 -14
  128. package/js/src/kucoin.d.ts +5 -15
  129. package/js/src/kucoinfutures.d.ts +4 -14
  130. package/js/src/kuna.d.ts +2 -2
  131. package/js/src/latoken.d.ts +5 -15
  132. package/js/src/latoken.js +1 -1
  133. package/js/src/lbank.d.ts +2 -2
  134. package/js/src/luno.d.ts +2 -2
  135. package/js/src/lykke.d.ts +2 -2
  136. package/js/src/mercado.d.ts +2 -2
  137. package/js/src/mexc.d.ts +8 -28
  138. package/js/src/mexc.js +1 -1
  139. package/js/src/ndax.d.ts +2 -2
  140. package/js/src/novadax.d.ts +4 -15
  141. package/js/src/novadax.js +0 -1
  142. package/js/src/okcoin.d.ts +4 -14
  143. package/js/src/okx.d.ts +10 -68
  144. package/js/src/okx.js +17 -0
  145. package/js/src/onetrading.d.ts +2 -2
  146. package/js/src/paymium.d.ts +4 -14
  147. package/js/src/phemex.d.ts +5 -15
  148. package/js/src/poloniex.d.ts +3 -13
  149. package/js/src/poloniex.js +1 -2
  150. package/js/src/poloniexfutures.d.ts +2 -2
  151. package/js/src/pro/bitget.js +137 -193
  152. package/js/src/pro/bybit.js +4 -2
  153. package/js/src/pro/coinbaseinternational.d.ts +3 -3
  154. package/js/src/pro/coinbaseinternational.js +9 -1
  155. package/js/src/pro/okx.d.ts +4 -1
  156. package/js/src/pro/okx.js +85 -0
  157. package/js/src/pro/woofipro.d.ts +47 -0
  158. package/js/src/pro/woofipro.js +1264 -0
  159. package/js/src/probit.d.ts +3 -3
  160. package/js/src/timex.d.ts +2 -2
  161. package/js/src/tokocrypto.d.ts +3 -3
  162. package/js/src/upbit.d.ts +2 -2
  163. package/js/src/wavesexchange.d.ts +3 -3
  164. package/js/src/wavesexchange.js +2 -2
  165. package/js/src/wazirx.d.ts +2 -2
  166. package/js/src/whitebit.d.ts +3 -13
  167. package/js/src/woo.d.ts +7 -17
  168. package/js/src/woo.js +17 -3
  169. package/js/src/woofipro.d.ts +131 -0
  170. package/js/src/woofipro.js +2699 -0
  171. package/js/src/yobit.d.ts +2 -2
  172. package/js/src/zaif.d.ts +2 -2
  173. package/js/src/zonda.d.ts +4 -14
  174. package/package.json +1 -1
@@ -0,0 +1,1263 @@
1
+ 'use strict';
2
+
3
+ var woofipro$1 = require('../woofipro.js');
4
+ var errors = require('../base/errors.js');
5
+ var Cache = require('../base/ws/Cache.js');
6
+ var Precise = require('../base/Precise.js');
7
+ var crypto = require('../base/functions/crypto.js');
8
+ var ed25519 = require('../static_dependencies/noble-curves/ed25519.js');
9
+
10
+ // ----------------------------------------------------------------------------
11
+ // ----------------------------------------------------------------------------
12
+ class woofipro extends woofipro$1 {
13
+ describe() {
14
+ return this.deepExtend(super.describe(), {
15
+ 'has': {
16
+ 'ws': true,
17
+ 'watchBalance': true,
18
+ 'watchMyTrades': true,
19
+ 'watchOHLCV': true,
20
+ 'watchOrderBook': true,
21
+ 'watchOrders': true,
22
+ 'watchTicker': true,
23
+ 'watchTickers': true,
24
+ 'watchTrades': true,
25
+ 'watchPositions': true,
26
+ },
27
+ 'urls': {
28
+ 'api': {
29
+ 'ws': {
30
+ 'public': 'wss://ws-evm.orderly.org/ws/stream',
31
+ 'private': 'wss://ws-private-evm.orderly.org/v2/ws/private/stream',
32
+ },
33
+ },
34
+ 'test': {
35
+ 'ws': {
36
+ 'public': 'wss://testnet-ws-evm.orderly.org/ws/stream',
37
+ 'private': 'wss://testnet-ws-private-evm.orderly.org/v2/ws/private/stream',
38
+ },
39
+ },
40
+ },
41
+ 'requiredCredentials': {
42
+ 'apiKey': true,
43
+ 'secret': true,
44
+ 'accountId': true,
45
+ },
46
+ 'options': {
47
+ 'tradesLimit': 1000,
48
+ 'ordersLimit': 1000,
49
+ 'requestId': {},
50
+ 'watchPositions': {
51
+ 'fetchPositionsSnapshot': true,
52
+ 'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
53
+ },
54
+ },
55
+ 'streaming': {
56
+ 'ping': this.ping,
57
+ 'keepAlive': 10000,
58
+ },
59
+ 'exceptions': {
60
+ 'ws': {
61
+ 'exact': {
62
+ 'Auth is needed.': errors.AuthenticationError,
63
+ },
64
+ },
65
+ },
66
+ });
67
+ }
68
+ requestId(url) {
69
+ const options = this.safeDict(this.options, 'requestId', {});
70
+ const previousValue = this.safeInteger(options, url, 0);
71
+ const newValue = this.sum(previousValue, 1);
72
+ this.options['requestId'][url] = newValue;
73
+ return newValue;
74
+ }
75
+ async watchPublic(messageHash, message) {
76
+ // the default id
77
+ let id = 'OqdphuyCtYWxwzhxyLLjOWNdFP7sQt8RPWzmb5xY';
78
+ if (this.accountId !== undefined) {
79
+ id = this.accountId;
80
+ }
81
+ const url = this.urls['api']['ws']['public'] + '/' + id;
82
+ const requestId = this.requestId(url);
83
+ const subscribe = {
84
+ 'id': requestId,
85
+ };
86
+ const request = this.extend(subscribe, message);
87
+ return await this.watch(url, messageHash, request, messageHash, subscribe);
88
+ }
89
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
90
+ /**
91
+ * @method
92
+ * @name woofipro#watchOrderBook
93
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/orderbook
94
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
95
+ * @param {string} symbol unified symbol of the market to fetch the order book for
96
+ * @param {int} [limit] the maximum amount of order book entries to return.
97
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
98
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
99
+ */
100
+ await this.loadMarkets();
101
+ const name = 'orderbook';
102
+ const market = this.market(symbol);
103
+ const topic = market['id'] + '@' + name;
104
+ const request = {
105
+ 'event': 'subscribe',
106
+ 'topic': topic,
107
+ };
108
+ const message = this.extend(request, params);
109
+ const orderbook = await this.watchPublic(topic, message);
110
+ return orderbook.limit();
111
+ }
112
+ handleOrderBook(client, message) {
113
+ //
114
+ // {
115
+ // "topic": "PERP_BTC_USDC@orderbook",
116
+ // "ts": 1650121915308,
117
+ // "data": {
118
+ // "symbol": "PERP_BTC_USDC",
119
+ // "bids": [
120
+ // [
121
+ // 0.30891,
122
+ // 2469.98
123
+ // ]
124
+ // ],
125
+ // "asks": [
126
+ // [
127
+ // 0.31075,
128
+ // 2379.63
129
+ // ]
130
+ // ]
131
+ // }
132
+ // }
133
+ //
134
+ const data = this.safeDict(message, 'data', {});
135
+ const marketId = this.safeString(data, 'symbol');
136
+ const market = this.safeMarket(marketId);
137
+ const symbol = market['symbol'];
138
+ const topic = this.safeString(message, 'topic');
139
+ if (!(symbol in this.orderbooks)) {
140
+ this.orderbooks[symbol] = this.orderBook();
141
+ }
142
+ const orderbook = this.orderbooks[symbol];
143
+ const timestamp = this.safeInteger(message, 'ts');
144
+ const snapshot = this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks');
145
+ orderbook.reset(snapshot);
146
+ client.resolve(orderbook, topic);
147
+ }
148
+ async watchTicker(symbol, params = {}) {
149
+ /**
150
+ * @method
151
+ * @name woofipro#watchTicker
152
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/24-hour-ticker
153
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
154
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
155
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
156
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
157
+ */
158
+ await this.loadMarkets();
159
+ const name = 'ticker';
160
+ const market = this.market(symbol);
161
+ symbol = market['symbol'];
162
+ const topic = market['id'] + '@' + name;
163
+ const request = {
164
+ 'event': 'subscribe',
165
+ 'topic': topic,
166
+ };
167
+ const message = this.extend(request, params);
168
+ return await this.watchPublic(topic, message);
169
+ }
170
+ parseWsTicker(ticker, market = undefined) {
171
+ //
172
+ // {
173
+ // "symbol": "PERP_BTC_USDC",
174
+ // "open": 19441.5,
175
+ // "close": 20147.07,
176
+ // "high": 20761.87,
177
+ // "low": 19320.54,
178
+ // "volume": 2481.103,
179
+ // "amount": 50037935.0286,
180
+ // "count": 3689
181
+ // }
182
+ //
183
+ return this.safeTicker({
184
+ 'symbol': this.safeSymbol(undefined, market),
185
+ 'timestamp': undefined,
186
+ 'datetime': undefined,
187
+ 'high': this.safeString(ticker, 'high'),
188
+ 'low': this.safeString(ticker, 'low'),
189
+ 'bid': undefined,
190
+ 'bidVolume': undefined,
191
+ 'ask': undefined,
192
+ 'askVolume': undefined,
193
+ 'vwap': undefined,
194
+ 'open': this.safeString(ticker, 'open'),
195
+ 'close': this.safeString(ticker, 'close'),
196
+ 'last': undefined,
197
+ 'previousClose': undefined,
198
+ 'change': undefined,
199
+ 'percentage': undefined,
200
+ 'average': undefined,
201
+ 'baseVolume': this.safeString(ticker, 'volume'),
202
+ 'quoteVolume': this.safeString(ticker, 'amount'),
203
+ 'info': ticker,
204
+ }, market);
205
+ }
206
+ handleTicker(client, message) {
207
+ //
208
+ // {
209
+ // "topic": "PERP_BTC_USDC@ticker",
210
+ // "ts": 1657120017000,
211
+ // "data": {
212
+ // "symbol": "PERP_BTC_USDC",
213
+ // "open": 19441.5,
214
+ // "close": 20147.07,
215
+ // "high": 20761.87,
216
+ // "low": 19320.54,
217
+ // "volume": 2481.103,
218
+ // "amount": 50037935.0286,
219
+ // "count": 3689
220
+ // }
221
+ // }
222
+ //
223
+ const data = this.safeDict(message, 'data', {});
224
+ const topic = this.safeString(message, 'topic');
225
+ const marketId = this.safeString(data, 'symbol');
226
+ const market = this.safeMarket(marketId);
227
+ const timestamp = this.safeInteger(message, 'ts');
228
+ data['date'] = timestamp;
229
+ const ticker = this.parseWsTicker(data, market);
230
+ ticker['symbol'] = market['symbol'];
231
+ this.tickers[market['symbol']] = ticker;
232
+ client.resolve(ticker, topic);
233
+ return message;
234
+ }
235
+ async watchTickers(symbols = undefined, params = {}) {
236
+ /**
237
+ * @method
238
+ * @name woofipro#watchTickers
239
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/24-hour-tickers
240
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
241
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
242
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
243
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
244
+ */
245
+ await this.loadMarkets();
246
+ symbols = this.marketSymbols(symbols);
247
+ const name = 'tickers';
248
+ const topic = name;
249
+ const request = {
250
+ 'event': 'subscribe',
251
+ 'topic': topic,
252
+ };
253
+ const message = this.extend(request, params);
254
+ const tickers = await this.watchPublic(topic, message);
255
+ return this.filterByArray(tickers, 'symbol', symbols);
256
+ }
257
+ handleTickers(client, message) {
258
+ //
259
+ // {
260
+ // "topic":"tickers",
261
+ // "ts":1618820615000,
262
+ // "data":[
263
+ // {
264
+ // "symbol":"PERP_NEAR_USDC",
265
+ // "open":16.297,
266
+ // "close":17.183,
267
+ // "high":24.707,
268
+ // "low":11.997,
269
+ // "volume":0,
270
+ // "amount":0,
271
+ // "count":0
272
+ // },
273
+ // ...
274
+ // ]
275
+ // }
276
+ //
277
+ const topic = this.safeString(message, 'topic');
278
+ const data = this.safeList(message, 'data', []);
279
+ const timestamp = this.safeInteger(message, 'ts');
280
+ const result = [];
281
+ for (let i = 0; i < data.length; i++) {
282
+ const marketId = this.safeString(data[i], 'symbol');
283
+ const market = this.safeMarket(marketId);
284
+ const ticker = this.parseWsTicker(this.extend(data[i], { 'date': timestamp }), market);
285
+ this.tickers[market['symbol']] = ticker;
286
+ result.push(ticker);
287
+ }
288
+ client.resolve(result, topic);
289
+ }
290
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
291
+ /**
292
+ * @method
293
+ * @name woofipro#watchOHLCV
294
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
295
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/k-line
296
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
297
+ * @param {string} timeframe the length of time each candle represents
298
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
299
+ * @param {int} [limit] the maximum amount of candles to fetch
300
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
301
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
302
+ */
303
+ await this.loadMarkets();
304
+ if ((timeframe !== '1m') && (timeframe !== '5m') && (timeframe !== '15m') && (timeframe !== '30m') && (timeframe !== '1h') && (timeframe !== '1d') && (timeframe !== '1w') && (timeframe !== '1M')) {
305
+ throw new errors.NotSupported(this.id + ' watchOHLCV timeframe argument must be 1m, 5m, 15m, 30m, 1h, 1d, 1w, 1M');
306
+ }
307
+ const market = this.market(symbol);
308
+ const interval = this.safeString(this.timeframes, timeframe, timeframe);
309
+ const name = 'kline';
310
+ const topic = market['id'] + '@' + name + '_' + interval;
311
+ const request = {
312
+ 'event': 'subscribe',
313
+ 'topic': topic,
314
+ };
315
+ const message = this.extend(request, params);
316
+ const ohlcv = await this.watchPublic(topic, message);
317
+ if (this.newUpdates) {
318
+ limit = ohlcv.getLimit(market['symbol'], limit);
319
+ }
320
+ return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
321
+ }
322
+ handleOHLCV(client, message) {
323
+ //
324
+ // {
325
+ // "topic":"PERP_BTC_USDC@kline_1m",
326
+ // "ts":1618822432146,
327
+ // "data":{
328
+ // "symbol":"PERP_BTC_USDC",
329
+ // "type":"1m",
330
+ // "open":56948.97,
331
+ // "close":56891.76,
332
+ // "high":56948.97,
333
+ // "low":56889.06,
334
+ // "volume":44.00947568,
335
+ // "amount":2504584.9,
336
+ // "startTime":1618822380000,
337
+ // "endTime":1618822440000
338
+ // }
339
+ // }
340
+ //
341
+ const data = this.safeDict(message, 'data', {});
342
+ const topic = this.safeString(message, 'topic');
343
+ const marketId = this.safeString(data, 'symbol');
344
+ const market = this.safeMarket(marketId);
345
+ const symbol = market['symbol'];
346
+ const interval = this.safeString(data, 'type');
347
+ const timeframe = this.findTimeframe(interval);
348
+ const parsed = [
349
+ this.safeInteger(data, 'startTime'),
350
+ this.safeNumber(data, 'open'),
351
+ this.safeNumber(data, 'high'),
352
+ this.safeNumber(data, 'low'),
353
+ this.safeNumber(data, 'close'),
354
+ this.safeNumber(data, 'volume'),
355
+ ];
356
+ this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
357
+ let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
358
+ if (stored === undefined) {
359
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
360
+ stored = new Cache.ArrayCacheByTimestamp(limit);
361
+ this.ohlcvs[symbol][timeframe] = stored;
362
+ }
363
+ const ohlcvCache = this.ohlcvs[symbol][timeframe];
364
+ ohlcvCache.append(parsed);
365
+ client.resolve(ohlcvCache, topic);
366
+ }
367
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
368
+ /**
369
+ * @method
370
+ * @name woofipro#watchTrades
371
+ * @description watches information on multiple trades made in a market
372
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/trade
373
+ * @param {string} symbol unified market symbol of the market trades were made in
374
+ * @param {int} [since] the earliest time in ms to fetch trades for
375
+ * @param {int} [limit] the maximum number of trade structures to retrieve
376
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
377
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
378
+ */
379
+ await this.loadMarkets();
380
+ const market = this.market(symbol);
381
+ symbol = market['symbol'];
382
+ const topic = market['id'] + '@trade';
383
+ const request = {
384
+ 'event': 'subscribe',
385
+ 'topic': topic,
386
+ };
387
+ const message = this.extend(request, params);
388
+ const trades = await this.watchPublic(topic, message);
389
+ if (this.newUpdates) {
390
+ limit = trades.getLimit(market['symbol'], limit);
391
+ }
392
+ return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
393
+ }
394
+ handleTrade(client, message) {
395
+ //
396
+ // {
397
+ // "topic":"PERP_ADA_USDC@trade",
398
+ // "ts":1618820361552,
399
+ // "data":{
400
+ // "symbol":"PERP_ADA_USDC",
401
+ // "price":1.27988,
402
+ // "size":300,
403
+ // "side":"BUY",
404
+ // }
405
+ // }
406
+ //
407
+ const topic = this.safeString(message, 'topic');
408
+ const timestamp = this.safeInteger(message, 'ts');
409
+ const data = this.safeDict(message, 'data', {});
410
+ const marketId = this.safeString(data, 'symbol');
411
+ const market = this.safeMarket(marketId);
412
+ const symbol = market['symbol'];
413
+ const trade = this.parseWsTrade(this.extend(data, { 'timestamp': timestamp }), market);
414
+ if (!(symbol in this.trades)) {
415
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
416
+ const stored = new Cache.ArrayCache(limit);
417
+ this.trades[symbol] = stored;
418
+ }
419
+ const trades = this.trades[symbol];
420
+ trades.append(trade);
421
+ this.trades[symbol] = trades;
422
+ client.resolve(trades, topic);
423
+ }
424
+ parseWsTrade(trade, market = undefined) {
425
+ //
426
+ // {
427
+ // "symbol":"PERP_ADA_USDC",
428
+ // "timestamp":1618820361552,
429
+ // "price":1.27988,
430
+ // "size":300,
431
+ // "side":"BUY",
432
+ // }
433
+ // private stream
434
+ // {
435
+ // symbol: 'PERP_XRP_USDC',
436
+ // clientOrderId: '',
437
+ // orderId: 1167632251,
438
+ // type: 'MARKET',
439
+ // side: 'BUY',
440
+ // quantity: 20,
441
+ // price: 0,
442
+ // tradeId: '1715179456664012',
443
+ // executedPrice: 0.5276,
444
+ // executedQuantity: 20,
445
+ // fee: 0.006332,
446
+ // feeAsset: 'USDC',
447
+ // totalExecutedQuantity: 20,
448
+ // avgPrice: 0.5276,
449
+ // averageExecutedPrice: 0.5276,
450
+ // status: 'FILLED',
451
+ // reason: '',
452
+ // totalFee: 0.006332,
453
+ // visible: 0,
454
+ // visibleQuantity: 0,
455
+ // timestamp: 1715179456660,
456
+ // orderTag: 'CCXT',
457
+ // createdTime: 1715179456656,
458
+ // maker: false
459
+ // }
460
+ //
461
+ const marketId = this.safeString(trade, 'symbol');
462
+ market = this.safeMarket(marketId, market);
463
+ const symbol = market['symbol'];
464
+ const price = this.safeString2(trade, 'executedPrice', 'price');
465
+ const amount = this.safeString2(trade, 'executedQuantity', 'size');
466
+ const cost = Precise["default"].stringMul(price, amount);
467
+ const side = this.safeStringLower(trade, 'side');
468
+ const timestamp = this.safeInteger(trade, 'timestamp');
469
+ let takerOrMaker = undefined;
470
+ const maker = this.safeBool(trade, 'maker');
471
+ if (maker !== undefined) {
472
+ takerOrMaker = maker ? 'maker' : 'taker';
473
+ }
474
+ let fee = undefined;
475
+ const feeValue = this.safeString(trade, 'fee');
476
+ if (feeValue !== undefined) {
477
+ fee = {
478
+ 'cost': feeValue,
479
+ 'currency': this.safeCurrencyCode(this.safeString(trade, 'feeAsset')),
480
+ };
481
+ }
482
+ return this.safeTrade({
483
+ 'id': this.safeString(trade, 'tradeId'),
484
+ 'timestamp': timestamp,
485
+ 'datetime': this.iso8601(timestamp),
486
+ 'symbol': symbol,
487
+ 'side': side,
488
+ 'price': price,
489
+ 'amount': amount,
490
+ 'cost': cost,
491
+ 'order': this.safeString(trade, 'orderId'),
492
+ 'takerOrMaker': takerOrMaker,
493
+ 'type': this.safeStringLower(trade, 'type'),
494
+ 'fee': fee,
495
+ 'info': trade,
496
+ }, market);
497
+ }
498
+ handleAuth(client, message) {
499
+ //
500
+ // {
501
+ // "event": "auth",
502
+ // "success": true,
503
+ // "ts": 1657463158812
504
+ // }
505
+ //
506
+ const messageHash = 'authenticated';
507
+ const success = this.safeValue(message, 'success');
508
+ if (success) {
509
+ // client.resolve (message, messageHash);
510
+ const future = this.safeValue(client.futures, 'authenticated');
511
+ future.resolve(true);
512
+ }
513
+ else {
514
+ const error = new errors.AuthenticationError(this.json(message));
515
+ client.reject(error, messageHash);
516
+ // allows further authentication attempts
517
+ if (messageHash in client.subscriptions) {
518
+ delete client.subscriptions['authenticated'];
519
+ }
520
+ }
521
+ }
522
+ async authenticate(params = {}) {
523
+ this.checkRequiredCredentials();
524
+ const url = this.urls['api']['ws']['private'] + '/' + this.accountId;
525
+ const client = this.client(url);
526
+ const messageHash = 'authenticated';
527
+ const event = 'auth';
528
+ const future = client.future(messageHash);
529
+ const authenticated = this.safeValue(client.subscriptions, messageHash);
530
+ if (authenticated === undefined) {
531
+ const ts = this.nonce().toString();
532
+ const auth = ts;
533
+ let secret = this.secret;
534
+ if (secret.indexOf('ed25519:') >= 0) {
535
+ const parts = secret.split('ed25519:');
536
+ secret = parts[1];
537
+ }
538
+ const signature = crypto.eddsa(this.encode(auth), this.base58ToBinary(secret), ed25519.ed25519);
539
+ const request = {
540
+ 'event': event,
541
+ 'params': {
542
+ 'orderly_key': this.apiKey,
543
+ 'sign': signature,
544
+ 'timestamp': ts,
545
+ },
546
+ };
547
+ const message = this.extend(request, params);
548
+ this.watch(url, messageHash, message, messageHash);
549
+ }
550
+ return await future;
551
+ }
552
+ async watchPrivate(messageHash, message, params = {}) {
553
+ await this.authenticate(params);
554
+ const url = this.urls['api']['ws']['private'] + '/' + this.accountId;
555
+ const requestId = this.requestId(url);
556
+ const subscribe = {
557
+ 'id': requestId,
558
+ };
559
+ const request = this.extend(subscribe, message);
560
+ return await this.watch(url, messageHash, request, messageHash, subscribe);
561
+ }
562
+ async watchPrivateMultiple(messageHashes, message, params = {}) {
563
+ await this.authenticate(params);
564
+ const url = this.urls['api']['ws']['private'] + '/' + this.accountId;
565
+ const requestId = this.requestId(url);
566
+ const subscribe = {
567
+ 'id': requestId,
568
+ };
569
+ const request = this.extend(subscribe, message);
570
+ return await this.watchMultiple(url, messageHashes, request, messageHashes, subscribe);
571
+ }
572
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
573
+ /**
574
+ * @method
575
+ * @name woofipro#watchOrders
576
+ * @description watches information on multiple orders made by the user
577
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/execution-report
578
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/algo-execution-report
579
+ * @param {string} symbol unified market symbol of the market orders were made in
580
+ * @param {int} [since] the earliest time in ms to fetch orders for
581
+ * @param {int} [limit] the maximum number of order structures to retrieve
582
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
583
+ * @param {bool} [params.trigger] true if trigger order
584
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
585
+ */
586
+ await this.loadMarkets();
587
+ const trigger = this.safeBool2(params, 'stop', 'trigger', false);
588
+ const topic = (trigger) ? 'algoexecutionreport' : 'executionreport';
589
+ params = this.omit(params, ['stop', 'trigger']);
590
+ let messageHash = topic;
591
+ if (symbol !== undefined) {
592
+ const market = this.market(symbol);
593
+ symbol = market['symbol'];
594
+ messageHash += ':' + symbol;
595
+ }
596
+ const request = {
597
+ 'event': 'subscribe',
598
+ 'topic': topic,
599
+ };
600
+ const message = this.extend(request, params);
601
+ const orders = await this.watchPrivate(messageHash, message);
602
+ if (this.newUpdates) {
603
+ limit = orders.getLimit(symbol, limit);
604
+ }
605
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
606
+ }
607
+ async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
608
+ /**
609
+ * @method
610
+ * @name woofipro#watchMyTrades
611
+ * @description watches information on multiple trades made by the user
612
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/execution-report
613
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/algo-execution-report
614
+ * @param {string} symbol unified market symbol of the market orders were made in
615
+ * @param {int} [since] the earliest time in ms to fetch orders for
616
+ * @param {int} [limit] the maximum number of order structures to retrieve
617
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
618
+ * @param {bool} [params.trigger] true if trigger order
619
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
620
+ */
621
+ await this.loadMarkets();
622
+ const trigger = this.safeBool2(params, 'stop', 'trigger', false);
623
+ const topic = (trigger) ? 'algoexecutionreport' : 'executionreport';
624
+ params = this.omit(params, 'stop');
625
+ let messageHash = 'myTrades';
626
+ if (symbol !== undefined) {
627
+ const market = this.market(symbol);
628
+ symbol = market['symbol'];
629
+ messageHash += ':' + symbol;
630
+ }
631
+ const request = {
632
+ 'event': 'subscribe',
633
+ 'topic': topic,
634
+ };
635
+ const message = this.extend(request, params);
636
+ const orders = await this.watchPrivate(messageHash, message);
637
+ if (this.newUpdates) {
638
+ limit = orders.getLimit(symbol, limit);
639
+ }
640
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
641
+ }
642
+ parseWsOrder(order, market = undefined) {
643
+ //
644
+ // {
645
+ // "symbol": "PERP_BTC_USDT",
646
+ // "clientOrderId": 0,
647
+ // "orderId": 52952826,
648
+ // "type": "LIMIT",
649
+ // "side": "SELL",
650
+ // "quantity": 0.01,
651
+ // "price": 22000,
652
+ // "tradeId": 0,
653
+ // "executedPrice": 0,
654
+ // "executedQuantity": 0,
655
+ // "fee": 0,
656
+ // "feeAsset": "USDT",
657
+ // "totalExecutedQuantity": 0,
658
+ // "status": "NEW",
659
+ // "reason": '',
660
+ // "orderTag": "default",
661
+ // "totalFee": 0,
662
+ // "visible": 0.01,
663
+ // "timestamp": 1657515556799,
664
+ // "reduceOnly": false,
665
+ // "maker": false
666
+ // }
667
+ // algo order
668
+ // {
669
+ // "symbol":"PERP_MATIC_USDC",
670
+ // "rootAlgoOrderId":123,
671
+ // "parentAlgoOrderId":123,
672
+ // "algoOrderId":123,
673
+ // "orderTag":"some tags",
674
+ // "algoType": "STOP",
675
+ // "clientOrderId":"client_id",
676
+ // "type":"LIMIT",
677
+ // "side":"BUY",
678
+ // "quantity":7029.0,
679
+ // "price":0.7699,
680
+ // "tradeId":0,
681
+ // "triggerTradePrice":0,
682
+ // "triggerTime":1234567,
683
+ // "triggered": false,
684
+ // "activated": false,
685
+ // "executedPrice":0.0,
686
+ // "executedQuantity":0.0,
687
+ // "fee":0.0,
688
+ // "feeAsset":"USDC",
689
+ // "totalExecutedQuantity":0.0,
690
+ // "averageExecutedQuantity":0.0,
691
+ // "avgPrice":0,
692
+ // "triggerPrice":0.0,
693
+ // "triggerPriceType":"STOP",
694
+ // "isActivated": false,
695
+ // "status":"NEW",
696
+ // "rootAlgoStatus": "FILLED",
697
+ // "algoStatus": "FILLED",
698
+ // "reason":"",
699
+ // "totalFee":0.0,
700
+ // "visible": 7029.0,
701
+ // "visibleQuantity":7029.0,
702
+ // "timestamp":1704679472448,
703
+ // "maker":false,
704
+ // "isMaker":false,
705
+ // "createdTime":1704679472448
706
+ // }
707
+ //
708
+ const orderId = this.safeString(order, 'orderId');
709
+ const marketId = this.safeString(order, 'symbol');
710
+ market = this.market(marketId);
711
+ const symbol = market['symbol'];
712
+ const timestamp = this.safeInteger(order, 'timestamp');
713
+ const fee = {
714
+ 'cost': this.safeString(order, 'totalFee'),
715
+ 'currency': this.safeString(order, 'feeAsset'),
716
+ };
717
+ let price = this.safeNumber(order, 'price');
718
+ const avgPrice = this.safeNumber(order, 'avgPrice');
719
+ if ((price === 0) && (avgPrice !== undefined)) {
720
+ price = avgPrice;
721
+ }
722
+ const amount = this.safeString(order, 'quantity');
723
+ const side = this.safeStringLower(order, 'side');
724
+ const type = this.safeStringLower(order, 'type');
725
+ const filled = this.safeNumber(order, 'totalExecutedQuantity');
726
+ const totalExecQuantity = this.safeString(order, 'totalExecutedQuantity');
727
+ let remaining = amount;
728
+ if (Precise["default"].stringGe(amount, totalExecQuantity)) {
729
+ remaining = Precise["default"].stringSub(remaining, totalExecQuantity);
730
+ }
731
+ const rawStatus = this.safeString(order, 'status');
732
+ const status = this.parseOrderStatus(rawStatus);
733
+ const trades = undefined;
734
+ const clientOrderId = this.safeString(order, 'clientOrderId');
735
+ const triggerPrice = this.safeNumber(order, 'triggerPrice');
736
+ return this.safeOrder({
737
+ 'info': order,
738
+ 'symbol': symbol,
739
+ 'id': orderId,
740
+ 'clientOrderId': clientOrderId,
741
+ 'timestamp': timestamp,
742
+ 'datetime': this.iso8601(timestamp),
743
+ 'lastTradeTimestamp': timestamp,
744
+ 'type': type,
745
+ 'timeInForce': undefined,
746
+ 'postOnly': undefined,
747
+ 'side': side,
748
+ 'price': price,
749
+ 'stopPrice': triggerPrice,
750
+ 'triggerPrice': triggerPrice,
751
+ 'amount': amount,
752
+ 'cost': undefined,
753
+ 'average': undefined,
754
+ 'filled': filled,
755
+ 'remaining': remaining,
756
+ 'status': status,
757
+ 'fee': fee,
758
+ 'trades': trades,
759
+ });
760
+ }
761
+ handleOrderUpdate(client, message) {
762
+ //
763
+ // {
764
+ // "topic": "executionreport",
765
+ // "ts": 1657515556799,
766
+ // "data": {
767
+ // "symbol": "PERP_BTC_USDT",
768
+ // "clientOrderId": 0,
769
+ // "orderId": 52952826,
770
+ // "type": "LIMIT",
771
+ // "side": "SELL",
772
+ // "quantity": 0.01,
773
+ // "price": 22000,
774
+ // "tradeId": 0,
775
+ // "executedPrice": 0,
776
+ // "executedQuantity": 0,
777
+ // "fee": 0,
778
+ // "feeAsset": "USDT",
779
+ // "totalExecutedQuantity": 0,
780
+ // "status": "NEW",
781
+ // "reason": '',
782
+ // "orderTag": "default",
783
+ // "totalFee": 0,
784
+ // "visible": 0.01,
785
+ // "timestamp": 1657515556799,
786
+ // "maker": false
787
+ // }
788
+ // }
789
+ //
790
+ const topic = this.safeString(message, 'topic');
791
+ const data = this.safeValue(message, 'data');
792
+ if (Array.isArray(data)) {
793
+ // algoexecutionreport
794
+ for (let i = 0; i < data.length; i++) {
795
+ const order = data[i];
796
+ const tradeId = this.omitZero(this.safeString(data, 'tradeId'));
797
+ if (tradeId !== undefined) {
798
+ this.handleMyTrade(client, order);
799
+ }
800
+ this.handleOrder(client, order, topic);
801
+ }
802
+ }
803
+ else {
804
+ // executionreport
805
+ const tradeId = this.omitZero(this.safeString(data, 'tradeId'));
806
+ if (tradeId !== undefined) {
807
+ this.handleMyTrade(client, data);
808
+ }
809
+ this.handleOrder(client, data, topic);
810
+ }
811
+ }
812
+ handleOrder(client, message, topic) {
813
+ const parsed = this.parseWsOrder(message);
814
+ const symbol = this.safeString(parsed, 'symbol');
815
+ const orderId = this.safeString(parsed, 'id');
816
+ if (symbol !== undefined) {
817
+ if (this.orders === undefined) {
818
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
819
+ this.orders = new Cache.ArrayCacheBySymbolById(limit);
820
+ }
821
+ const cachedOrders = this.orders;
822
+ const orders = this.safeDict(cachedOrders.hashmap, symbol, {});
823
+ const order = this.safeDict(orders, orderId);
824
+ if (order !== undefined) {
825
+ const fee = this.safeValue(order, 'fee');
826
+ if (fee !== undefined) {
827
+ parsed['fee'] = fee;
828
+ }
829
+ const fees = this.safeList(order, 'fees');
830
+ if (fees !== undefined) {
831
+ parsed['fees'] = fees;
832
+ }
833
+ parsed['trades'] = this.safeList(order, 'trades');
834
+ parsed['timestamp'] = this.safeInteger(order, 'timestamp');
835
+ parsed['datetime'] = this.safeString(order, 'datetime');
836
+ }
837
+ cachedOrders.append(parsed);
838
+ client.resolve(this.orders, topic);
839
+ const messageHashSymbol = topic + ':' + symbol;
840
+ client.resolve(this.orders, messageHashSymbol);
841
+ }
842
+ }
843
+ handleMyTrade(client, message) {
844
+ //
845
+ // {
846
+ // symbol: 'PERP_XRP_USDC',
847
+ // clientOrderId: '',
848
+ // orderId: 1167632251,
849
+ // type: 'MARKET',
850
+ // side: 'BUY',
851
+ // quantity: 20,
852
+ // price: 0,
853
+ // tradeId: '1715179456664012',
854
+ // executedPrice: 0.5276,
855
+ // executedQuantity: 20,
856
+ // fee: 0.006332,
857
+ // feeAsset: 'USDC',
858
+ // totalExecutedQuantity: 20,
859
+ // avgPrice: 0.5276,
860
+ // averageExecutedPrice: 0.5276,
861
+ // status: 'FILLED',
862
+ // reason: '',
863
+ // totalFee: 0.006332,
864
+ // visible: 0,
865
+ // visibleQuantity: 0,
866
+ // timestamp: 1715179456660,
867
+ // orderTag: 'CCXT',
868
+ // createdTime: 1715179456656,
869
+ // maker: false
870
+ // }
871
+ //
872
+ const messageHash = 'myTrades';
873
+ const marketId = this.safeString(message, 'symbol');
874
+ const market = this.safeMarket(marketId);
875
+ const symbol = market['symbol'];
876
+ const trade = this.parseWsTrade(message, market);
877
+ let trades = this.myTrades;
878
+ if (trades === undefined) {
879
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
880
+ trades = new Cache.ArrayCacheBySymbolById(limit);
881
+ this.myTrades = trades;
882
+ }
883
+ trades.append(trade);
884
+ client.resolve(trades, messageHash);
885
+ const symbolSpecificMessageHash = messageHash + ':' + symbol;
886
+ client.resolve(trades, symbolSpecificMessageHash);
887
+ }
888
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
889
+ /**
890
+ * @method
891
+ * @name woofipro#watchPositions
892
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/position-push
893
+ * @description watch all open positions
894
+ * @param {string[]|undefined} symbols list of unified market symbols
895
+ * @param {object} params extra parameters specific to the exchange API endpoint
896
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
897
+ */
898
+ await this.loadMarkets();
899
+ const messageHashes = [];
900
+ symbols = this.marketSymbols(symbols);
901
+ if (!this.isEmpty(symbols)) {
902
+ for (let i = 0; i < symbols.length; i++) {
903
+ const symbol = symbols[i];
904
+ messageHashes.push('positions::' + symbol);
905
+ }
906
+ }
907
+ else {
908
+ messageHashes.push('positions');
909
+ }
910
+ const url = this.urls['api']['ws']['private'] + '/' + this.accountId;
911
+ const client = this.client(url);
912
+ this.setPositionsCache(client, symbols);
913
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
914
+ const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
915
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && this.positions === undefined) {
916
+ const snapshot = await client.future('fetchPositionsSnapshot');
917
+ return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
918
+ }
919
+ const request = {
920
+ 'event': 'subscribe',
921
+ 'topic': 'position',
922
+ };
923
+ const newPositions = await this.watchPrivateMultiple(messageHashes, request, params);
924
+ if (this.newUpdates) {
925
+ return newPositions;
926
+ }
927
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
928
+ }
929
+ setPositionsCache(client, type, symbols = undefined) {
930
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', false);
931
+ if (fetchPositionsSnapshot) {
932
+ const messageHash = 'fetchPositionsSnapshot';
933
+ if (!(messageHash in client.futures)) {
934
+ client.future(messageHash);
935
+ this.spawn(this.loadPositionsSnapshot, client, messageHash);
936
+ }
937
+ }
938
+ else {
939
+ this.positions = new Cache.ArrayCacheBySymbolBySide();
940
+ }
941
+ }
942
+ async loadPositionsSnapshot(client, messageHash) {
943
+ const positions = await this.fetchPositions();
944
+ this.positions = new Cache.ArrayCacheBySymbolBySide();
945
+ const cache = this.positions;
946
+ for (let i = 0; i < positions.length; i++) {
947
+ const position = positions[i];
948
+ const contracts = this.safeString(position, 'contracts', '0');
949
+ if (Precise["default"].stringGt(contracts, '0')) {
950
+ cache.append(position);
951
+ }
952
+ }
953
+ // don't remove the future from the .futures cache
954
+ const future = client.futures[messageHash];
955
+ future.resolve(cache);
956
+ client.resolve(cache, 'positions');
957
+ }
958
+ handlePositions(client, message) {
959
+ //
960
+ // {
961
+ // "topic":"position",
962
+ // "ts":1705292345255,
963
+ // "data":{
964
+ // "positions":[
965
+ // {
966
+ // "symbol":"PERP_ETH_USDC",
967
+ // "positionQty":3.1408,
968
+ // "costPosition":5706.51952,
969
+ // "lastSumUnitaryFunding":0.804,
970
+ // "sumUnitaryFundingVersion":0,
971
+ // "pendingLongQty":0.0,
972
+ // "pendingShortQty":-1.0,
973
+ // "settlePrice":1816.9,
974
+ // "averageOpenPrice":1804.51490427,
975
+ // "unsettledPnl":-2.79856,
976
+ // "pnl24H":-338.90179488,
977
+ // "fee24H":4.242423,
978
+ // "markPrice":1816.2,
979
+ // "estLiqPrice":0.0,
980
+ // "version":179967,
981
+ // "imrwithOrders":0.1,
982
+ // "mmrwithOrders":0.05,
983
+ // "mmr":0.05,
984
+ // "imr":0.1,
985
+ // "timestamp":1685154032762
986
+ // }
987
+ // ]
988
+ // }
989
+ // }
990
+ //
991
+ const data = this.safeDict(message, 'data', {});
992
+ const rawPositions = this.safeList(data, 'positions', []);
993
+ if (this.positions === undefined) {
994
+ this.positions = new Cache.ArrayCacheBySymbolBySide();
995
+ }
996
+ const cache = this.positions;
997
+ const newPositions = [];
998
+ for (let i = 0; i < rawPositions.length; i++) {
999
+ const rawPosition = rawPositions[i];
1000
+ const marketId = this.safeString(rawPosition, 'symbol');
1001
+ const market = this.safeMarket(marketId);
1002
+ const position = this.parseWsPosition(rawPosition, market);
1003
+ newPositions.push(position);
1004
+ cache.append(position);
1005
+ const messageHash = 'positions::' + market['symbol'];
1006
+ client.resolve(position, messageHash);
1007
+ }
1008
+ client.resolve(newPositions, 'positions');
1009
+ }
1010
+ parseWsPosition(position, market = undefined) {
1011
+ //
1012
+ // {
1013
+ // "symbol":"PERP_ETH_USDC",
1014
+ // "positionQty":3.1408,
1015
+ // "costPosition":5706.51952,
1016
+ // "lastSumUnitaryFunding":0.804,
1017
+ // "sumUnitaryFundingVersion":0,
1018
+ // "pendingLongQty":0.0,
1019
+ // "pendingShortQty":-1.0,
1020
+ // "settlePrice":1816.9,
1021
+ // "averageOpenPrice":1804.51490427,
1022
+ // "unsettledPnl":-2.79856,
1023
+ // "pnl24H":-338.90179488,
1024
+ // "fee24H":4.242423,
1025
+ // "markPrice":1816.2,
1026
+ // "estLiqPrice":0.0,
1027
+ // "version":179967,
1028
+ // "imrwithOrders":0.1,
1029
+ // "mmrwithOrders":0.05,
1030
+ // "mmr":0.05,
1031
+ // "imr":0.1,
1032
+ // "timestamp":1685154032762
1033
+ // }
1034
+ //
1035
+ const contract = this.safeString(position, 'symbol');
1036
+ market = this.safeMarket(contract, market);
1037
+ let size = this.safeString(position, 'positionQty');
1038
+ let side = undefined;
1039
+ if (Precise["default"].stringGt(size, '0')) {
1040
+ side = 'long';
1041
+ }
1042
+ else {
1043
+ side = 'short';
1044
+ }
1045
+ const contractSize = this.safeString(market, 'contractSize');
1046
+ const markPrice = this.safeString(position, 'markPrice');
1047
+ const timestamp = this.safeInteger(position, 'timestamp');
1048
+ const entryPrice = this.safeString(position, 'averageOpenPrice');
1049
+ const unrealisedPnl = this.safeString(position, 'unsettledPnl');
1050
+ size = Precise["default"].stringAbs(size);
1051
+ const notional = Precise["default"].stringMul(size, markPrice);
1052
+ return this.safePosition({
1053
+ 'info': position,
1054
+ 'id': undefined,
1055
+ 'symbol': this.safeString(market, 'symbol'),
1056
+ 'timestamp': timestamp,
1057
+ 'datetime': this.iso8601(timestamp),
1058
+ 'lastUpdateTimestamp': undefined,
1059
+ 'initialMargin': undefined,
1060
+ 'initialMarginPercentage': undefined,
1061
+ 'maintenanceMargin': undefined,
1062
+ 'maintenanceMarginPercentage': undefined,
1063
+ 'entryPrice': this.parseNumber(entryPrice),
1064
+ 'notional': this.parseNumber(notional),
1065
+ 'leverage': undefined,
1066
+ 'unrealizedPnl': this.parseNumber(unrealisedPnl),
1067
+ 'contracts': this.parseNumber(size),
1068
+ 'contractSize': this.parseNumber(contractSize),
1069
+ 'marginRatio': undefined,
1070
+ 'liquidationPrice': this.safeNumber(position, 'estLiqPrice'),
1071
+ 'markPrice': this.parseNumber(markPrice),
1072
+ 'lastPrice': undefined,
1073
+ 'collateral': undefined,
1074
+ 'marginMode': 'cross',
1075
+ 'marginType': undefined,
1076
+ 'side': side,
1077
+ 'percentage': undefined,
1078
+ 'hedged': undefined,
1079
+ 'stopLossPrice': undefined,
1080
+ 'takeProfitPrice': undefined,
1081
+ });
1082
+ }
1083
+ async watchBalance(params = {}) {
1084
+ /**
1085
+ * @method
1086
+ * @name woofipro#watchBalance
1087
+ * @description watch balance and get the amount of funds available for trading or funds locked in orders
1088
+ * @see https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/balance
1089
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1090
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1091
+ */
1092
+ await this.loadMarkets();
1093
+ const topic = 'balance';
1094
+ const messageHash = topic;
1095
+ const request = {
1096
+ 'event': 'subscribe',
1097
+ 'topic': topic,
1098
+ };
1099
+ const message = this.extend(request, params);
1100
+ return await this.watchPrivate(messageHash, message);
1101
+ }
1102
+ handleBalance(client, message) {
1103
+ //
1104
+ // {
1105
+ // "topic":"balance",
1106
+ // "ts":1651836695254,
1107
+ // "data":{
1108
+ // "balances":{
1109
+ // "USDC":{
1110
+ // "holding":5555815.47398272,
1111
+ // "frozen":0,
1112
+ // "interest":0,
1113
+ // "pendingShortQty":0,
1114
+ // "pendingExposure":0,
1115
+ // "pendingLongQty":0,
1116
+ // "pendingLongExposure":0,
1117
+ // "version":894,
1118
+ // "staked":51370692,
1119
+ // "unbonding":0,
1120
+ // "vault":0,
1121
+ // "averageOpenPrice":0.00000574,
1122
+ // "pnl24H":0,
1123
+ // "fee24H":0.01914,
1124
+ // "markPrice":0.31885
1125
+ // }
1126
+ // }
1127
+ // }
1128
+ // }
1129
+ //
1130
+ const data = this.safeDict(message, 'data', {});
1131
+ const balances = this.safeDict(data, 'balances', {});
1132
+ const keys = Object.keys(balances);
1133
+ const ts = this.safeInteger(message, 'ts');
1134
+ this.balance['info'] = data;
1135
+ this.balance['timestamp'] = ts;
1136
+ this.balance['datetime'] = this.iso8601(ts);
1137
+ for (let i = 0; i < keys.length; i++) {
1138
+ const key = keys[i];
1139
+ const value = balances[key];
1140
+ const code = this.safeCurrencyCode(key);
1141
+ const account = (code in this.balance) ? this.balance[code] : this.account();
1142
+ const total = this.safeString(value, 'holding');
1143
+ const used = this.safeString(value, 'frozen');
1144
+ account['total'] = total;
1145
+ account['used'] = used;
1146
+ account['free'] = Precise["default"].stringSub(total, used);
1147
+ this.balance[code] = account;
1148
+ }
1149
+ this.balance = this.safeBalance(this.balance);
1150
+ client.resolve(this.balance, 'balance');
1151
+ }
1152
+ handleErrorMessage(client, message) {
1153
+ //
1154
+ // {"id":"1","event":"subscribe","success":false,"ts":1710780997216,"errorMsg":"Auth is needed."}
1155
+ //
1156
+ if (!('success' in message)) {
1157
+ return false;
1158
+ }
1159
+ const success = this.safeBool(message, 'success');
1160
+ if (success) {
1161
+ return false;
1162
+ }
1163
+ const errorMessage = this.safeString(message, 'errorMsg');
1164
+ try {
1165
+ if (errorMessage !== undefined) {
1166
+ const feedback = this.id + ' ' + this.json(message);
1167
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorMessage, feedback);
1168
+ }
1169
+ return false;
1170
+ }
1171
+ catch (error) {
1172
+ if (error instanceof errors.AuthenticationError) {
1173
+ const messageHash = 'authenticated';
1174
+ client.reject(error, messageHash);
1175
+ if (messageHash in client.subscriptions) {
1176
+ delete client.subscriptions[messageHash];
1177
+ }
1178
+ }
1179
+ else {
1180
+ client.reject(error);
1181
+ }
1182
+ return true;
1183
+ }
1184
+ }
1185
+ handleMessage(client, message) {
1186
+ if (this.handleErrorMessage(client, message)) {
1187
+ return;
1188
+ }
1189
+ const methods = {
1190
+ 'ping': this.handlePing,
1191
+ 'pong': this.handlePong,
1192
+ 'subscribe': this.handleSubscribe,
1193
+ 'orderbook': this.handleOrderBook,
1194
+ 'ticker': this.handleTicker,
1195
+ 'tickers': this.handleTickers,
1196
+ 'kline': this.handleOHLCV,
1197
+ 'trade': this.handleTrade,
1198
+ 'auth': this.handleAuth,
1199
+ 'executionreport': this.handleOrderUpdate,
1200
+ 'algoexecutionreport': this.handleOrderUpdate,
1201
+ 'position': this.handlePositions,
1202
+ 'balance': this.handleBalance,
1203
+ };
1204
+ const event = this.safeString(message, 'event');
1205
+ let method = this.safeValue(methods, event);
1206
+ if (method !== undefined) {
1207
+ method.call(this, client, message);
1208
+ return;
1209
+ }
1210
+ const topic = this.safeString(message, 'topic');
1211
+ if (topic !== undefined) {
1212
+ method = this.safeValue(methods, topic);
1213
+ if (method !== undefined) {
1214
+ method.call(this, client, message);
1215
+ return;
1216
+ }
1217
+ const splitTopic = topic.split('@');
1218
+ const splitLength = splitTopic.length;
1219
+ if (splitLength === 2) {
1220
+ const name = this.safeString(splitTopic, 1);
1221
+ method = this.safeValue(methods, name);
1222
+ if (method !== undefined) {
1223
+ method.call(this, client, message);
1224
+ return;
1225
+ }
1226
+ const splitName = name.split('_');
1227
+ const splitNameLength = splitTopic.length;
1228
+ if (splitNameLength === 2) {
1229
+ method = this.safeValue(methods, this.safeString(splitName, 0));
1230
+ if (method !== undefined) {
1231
+ method.call(this, client, message);
1232
+ }
1233
+ }
1234
+ }
1235
+ }
1236
+ }
1237
+ ping(client) {
1238
+ return { 'event': 'ping' };
1239
+ }
1240
+ handlePing(client, message) {
1241
+ return { 'event': 'pong' };
1242
+ }
1243
+ handlePong(client, message) {
1244
+ //
1245
+ // { event: "pong", ts: 1614667590000 }
1246
+ //
1247
+ client.lastPong = this.milliseconds();
1248
+ return message;
1249
+ }
1250
+ handleSubscribe(client, message) {
1251
+ //
1252
+ // {
1253
+ // "id": "666888",
1254
+ // "event": "subscribe",
1255
+ // "success": true,
1256
+ // "ts": 1657117712212
1257
+ // }
1258
+ //
1259
+ return message;
1260
+ }
1261
+ }
1262
+
1263
+ module.exports = woofipro;