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