ccxt 4.5.33 → 4.5.34

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 (184) hide show
  1. package/README.md +19 -5
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +4 -4
  4. package/dist/cjs/src/{btcalpha.js → alp.js} +45 -45
  5. package/dist/cjs/src/ascendex.js +2 -2
  6. package/dist/cjs/src/aster.js +15 -22
  7. package/dist/cjs/src/backpack.js +2 -2
  8. package/dist/cjs/src/binance.js +6 -4
  9. package/dist/cjs/src/bingx.js +2 -1
  10. package/dist/cjs/src/bitfinex.js +6 -11
  11. package/dist/cjs/src/bitget.js +4 -4
  12. package/dist/cjs/src/bitmart.js +1 -1
  13. package/dist/cjs/src/bitmex.js +1 -1
  14. package/dist/cjs/src/bitso.js +1 -1
  15. package/dist/cjs/src/bitstamp.js +1 -1
  16. package/dist/cjs/src/blofin.js +1 -1
  17. package/dist/cjs/src/bybit.js +49 -26
  18. package/dist/cjs/src/cex.js +1 -1
  19. package/dist/cjs/src/coinbase.js +7 -6
  20. package/dist/cjs/src/coinbaseexchange.js +1 -1
  21. package/dist/cjs/src/coincatch.js +3 -3
  22. package/dist/cjs/src/coinex.js +2 -2
  23. package/dist/cjs/src/coinmetro.js +1 -1
  24. package/dist/cjs/src/cryptocom.js +4 -1
  25. package/dist/cjs/src/deepcoin.js +1 -1
  26. package/dist/cjs/src/defx.js +1 -1
  27. package/dist/cjs/src/delta.js +3 -3
  28. package/dist/cjs/src/digifinex.js +1 -1
  29. package/dist/cjs/src/dydx.js +1 -1
  30. package/dist/cjs/src/exmo.js +2 -2
  31. package/dist/cjs/src/foxbit.js +1 -1
  32. package/dist/cjs/src/gate.js +23 -3
  33. package/dist/cjs/src/hashkey.js +1 -1
  34. package/dist/cjs/src/hibachi.js +1 -1
  35. package/dist/cjs/src/hitbtc.js +2 -2
  36. package/dist/cjs/src/htx.js +26 -1
  37. package/dist/cjs/src/hyperliquid.js +5 -4
  38. package/dist/cjs/src/kraken.js +1 -1
  39. package/dist/cjs/src/kucoin.js +1 -1
  40. package/dist/cjs/src/kucoinfutures.js +1 -1
  41. package/dist/cjs/src/luno.js +1 -1
  42. package/dist/cjs/src/mexc.js +2 -2
  43. package/dist/cjs/src/modetrade.js +1 -1
  44. package/dist/cjs/src/ndax.js +1 -1
  45. package/dist/cjs/src/okx.js +4 -4
  46. package/dist/cjs/src/paradex.js +1 -1
  47. package/dist/cjs/src/phemex.js +1 -1
  48. package/dist/cjs/src/poloniex.js +2 -2
  49. package/dist/cjs/src/pro/apex.js +5 -4
  50. package/dist/cjs/src/pro/arkham.js +1 -1
  51. package/dist/cjs/src/pro/aster.js +905 -33
  52. package/dist/cjs/src/pro/bitget.js +14 -1
  53. package/dist/cjs/src/pro/okx.js +1 -1
  54. package/dist/cjs/src/toobit.js +1 -1
  55. package/dist/cjs/src/whitebit.js +1 -1
  56. package/dist/cjs/src/woo.js +3 -3
  57. package/dist/cjs/src/woofipro.js +1 -1
  58. package/dist/cjs/src/xt.js +2 -2
  59. package/dist/cjs/src/zebpay.js +2 -2
  60. package/dist/cjs/src/zonda.js +1 -1
  61. package/js/ccxt.d.ts +5 -5
  62. package/js/ccxt.js +4 -4
  63. package/js/src/abstract/aster.d.ts +6 -8
  64. package/js/src/abstract/binance.d.ts +2 -0
  65. package/js/src/abstract/binancecoinm.d.ts +2 -0
  66. package/js/src/abstract/binanceus.d.ts +2 -0
  67. package/js/src/abstract/binanceusdm.d.ts +2 -0
  68. package/js/src/abstract/bingx.d.ts +1 -0
  69. package/js/src/abstract/bybit.d.ts +15 -0
  70. package/js/src/abstract/cryptocom.d.ts +3 -0
  71. package/js/src/abstract/gate.d.ts +13 -0
  72. package/js/src/abstract/gateio.d.ts +13 -0
  73. package/js/src/abstract/htx.d.ts +25 -0
  74. package/js/src/abstract/huobi.d.ts +25 -0
  75. package/js/src/{btcalpha.d.ts → alp.d.ts} +37 -37
  76. package/js/src/{btcalpha.js → alp.js} +44 -44
  77. package/js/src/ascendex.d.ts +2 -2
  78. package/js/src/ascendex.js +2 -2
  79. package/js/src/aster.js +15 -22
  80. package/js/src/backpack.js +2 -2
  81. package/js/src/binance.d.ts +4 -4
  82. package/js/src/binance.js +6 -4
  83. package/js/src/bingx.d.ts +1 -1
  84. package/js/src/bingx.js +2 -1
  85. package/js/src/bitfinex.d.ts +1 -2
  86. package/js/src/bitfinex.js +6 -11
  87. package/js/src/bitget.d.ts +3 -3
  88. package/js/src/bitget.js +4 -4
  89. package/js/src/bitmart.d.ts +1 -1
  90. package/js/src/bitmart.js +1 -1
  91. package/js/src/bitmex.d.ts +1 -1
  92. package/js/src/bitmex.js +1 -1
  93. package/js/src/bitso.d.ts +1 -1
  94. package/js/src/bitso.js +1 -1
  95. package/js/src/bitstamp.d.ts +1 -1
  96. package/js/src/bitstamp.js +1 -1
  97. package/js/src/blofin.d.ts +1 -1
  98. package/js/src/blofin.js +1 -1
  99. package/js/src/bybit.d.ts +1 -1
  100. package/js/src/bybit.js +49 -26
  101. package/js/src/cex.d.ts +1 -1
  102. package/js/src/cex.js +1 -1
  103. package/js/src/coinbase.d.ts +1 -1
  104. package/js/src/coinbase.js +7 -6
  105. package/js/src/coinbaseexchange.d.ts +1 -1
  106. package/js/src/coinbaseexchange.js +1 -1
  107. package/js/src/coincatch.d.ts +3 -3
  108. package/js/src/coincatch.js +3 -3
  109. package/js/src/coinex.d.ts +2 -2
  110. package/js/src/coinex.js +2 -2
  111. package/js/src/coinmetro.d.ts +1 -1
  112. package/js/src/coinmetro.js +1 -1
  113. package/js/src/cryptocom.d.ts +1 -1
  114. package/js/src/cryptocom.js +4 -1
  115. package/js/src/deepcoin.d.ts +1 -1
  116. package/js/src/deepcoin.js +1 -1
  117. package/js/src/defx.d.ts +1 -1
  118. package/js/src/defx.js +1 -1
  119. package/js/src/delta.d.ts +3 -3
  120. package/js/src/delta.js +3 -3
  121. package/js/src/digifinex.d.ts +1 -1
  122. package/js/src/digifinex.js +1 -1
  123. package/js/src/dydx.d.ts +1 -1
  124. package/js/src/dydx.js +1 -1
  125. package/js/src/exmo.d.ts +2 -2
  126. package/js/src/exmo.js +2 -2
  127. package/js/src/foxbit.js +1 -1
  128. package/js/src/gate.d.ts +3 -3
  129. package/js/src/gate.js +23 -3
  130. package/js/src/hashkey.d.ts +1 -1
  131. package/js/src/hashkey.js +1 -1
  132. package/js/src/hibachi.d.ts +1 -1
  133. package/js/src/hibachi.js +1 -1
  134. package/js/src/hitbtc.d.ts +2 -2
  135. package/js/src/hitbtc.js +2 -2
  136. package/js/src/htx.d.ts +1 -1
  137. package/js/src/htx.js +26 -1
  138. package/js/src/hyperliquid.d.ts +3 -3
  139. package/js/src/hyperliquid.js +5 -4
  140. package/js/src/kraken.d.ts +1 -1
  141. package/js/src/kraken.js +1 -1
  142. package/js/src/kucoin.d.ts +1 -1
  143. package/js/src/kucoin.js +1 -1
  144. package/js/src/kucoinfutures.d.ts +1 -1
  145. package/js/src/kucoinfutures.js +1 -1
  146. package/js/src/luno.d.ts +1 -1
  147. package/js/src/luno.js +1 -1
  148. package/js/src/mexc.d.ts +2 -2
  149. package/js/src/mexc.js +2 -2
  150. package/js/src/modetrade.d.ts +1 -1
  151. package/js/src/modetrade.js +1 -1
  152. package/js/src/ndax.d.ts +1 -1
  153. package/js/src/ndax.js +1 -1
  154. package/js/src/okx.d.ts +3 -3
  155. package/js/src/okx.js +4 -4
  156. package/js/src/paradex.js +1 -1
  157. package/js/src/phemex.d.ts +1 -1
  158. package/js/src/phemex.js +1 -1
  159. package/js/src/poloniex.d.ts +2 -2
  160. package/js/src/poloniex.js +2 -2
  161. package/js/src/pro/apex.js +5 -4
  162. package/js/src/pro/arkham.js +1 -1
  163. package/js/src/pro/aster.d.ts +68 -2
  164. package/js/src/pro/aster.js +906 -34
  165. package/js/src/pro/bitget.js +14 -1
  166. package/js/src/pro/okx.d.ts +1 -1
  167. package/js/src/pro/okx.js +1 -1
  168. package/js/src/toobit.d.ts +1 -1
  169. package/js/src/toobit.js +1 -1
  170. package/js/src/whitebit.js +1 -1
  171. package/js/src/woo.d.ts +3 -3
  172. package/js/src/woo.js +3 -3
  173. package/js/src/woofipro.d.ts +1 -1
  174. package/js/src/woofipro.js +1 -1
  175. package/js/src/xt.d.ts +2 -2
  176. package/js/src/xt.js +2 -2
  177. package/js/src/zebpay.d.ts +2 -2
  178. package/js/src/zebpay.js +2 -2
  179. package/js/src/zonda.d.ts +1 -1
  180. package/js/src/zonda.js +1 -1
  181. package/package.json +1 -1
  182. /package/dist/cjs/src/abstract/{btcalpha.js → alp.js} +0 -0
  183. /package/js/src/abstract/{btcalpha.d.ts → alp.d.ts} +0 -0
  184. /package/js/src/abstract/{btcalpha.js → alp.js} +0 -0
@@ -1,25 +1,29 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  import asterRest from '../aster.js';
3
+ import { Precise } from '../base/Precise.js';
3
4
  import { ArgumentsRequired } from '../base/errors.js';
4
- import { ArrayCache, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
5
+ import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
5
6
  // ---------------------------------------------------------------------------
6
7
  export default class aster extends asterRest {
7
8
  describe() {
8
9
  return this.deepExtend(super.describe(), {
9
10
  'has': {
10
11
  'ws': true,
11
- 'watchBalance': false,
12
+ 'watchBalance': true,
12
13
  'watchBidsAsks': true,
13
- 'watchTicker': true,
14
- 'watchTickers': true,
15
14
  'watchMarkPrice': true,
16
15
  'watchMarkPrices': true,
17
16
  'watchTrades': true,
18
17
  'watchTradesForSymbols': true,
18
+ 'watchOrders': true,
19
19
  'watchOrderBook': true,
20
20
  'watchOrderBookForSymbols': true,
21
21
  'watchOHLCV': true,
22
22
  'watchOHLCVForSymbols': true,
23
+ 'watchPositions': true,
24
+ 'watchTicker': true,
25
+ 'watchTickers': true,
26
+ 'watchMyTrades': true,
23
27
  'unWatchTicker': true,
24
28
  'unWatchTickers': true,
25
29
  'unWatchMarkPrice': true,
@@ -35,12 +39,40 @@ export default class aster extends asterRest {
35
39
  'urls': {
36
40
  'api': {
37
41
  'ws': {
38
- 'spot': 'wss://sstream.asterdex.com/stream',
39
- 'swap': 'wss://fstream.asterdex.com/stream',
42
+ 'public': {
43
+ 'spot': 'wss://sstream.asterdex.com/stream',
44
+ 'swap': 'wss://fstream.asterdex.com/stream',
45
+ },
46
+ 'private': {
47
+ 'spot': 'wss://sstream.asterdex.com/ws',
48
+ 'swap': 'wss://fstream.asterdex.com/ws',
49
+ },
40
50
  },
41
51
  },
42
52
  },
43
- 'options': {},
53
+ 'options': {
54
+ 'listenKey': {
55
+ 'spot': undefined,
56
+ 'swap': undefined,
57
+ },
58
+ 'lastAuthenticatedTime': {
59
+ 'spot': 0,
60
+ 'swap': 0,
61
+ },
62
+ 'listenKeyRefreshRate': {
63
+ 'spot': 3600000,
64
+ 'swap': 3600000,
65
+ },
66
+ 'watchBalance': {
67
+ 'fetchBalanceSnapshot': false,
68
+ 'awaitBalanceSnapshot': true, // whether to wait for the balance snapshot before providing updates
69
+ },
70
+ 'wallet': 'wb',
71
+ 'watchPositions': {
72
+ 'fetchPositionsSnapshot': true,
73
+ 'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
74
+ },
75
+ },
44
76
  'streaming': {},
45
77
  'exceptions': {},
46
78
  });
@@ -109,7 +141,7 @@ export default class aster extends asterRest {
109
141
  if (symbolsLength === 0) {
110
142
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
111
143
  }
112
- const url = this.urls['api']['ws'][type];
144
+ const url = this.urls['api']['ws']['public'][type];
113
145
  const subscriptionArgs = [];
114
146
  const messageHashes = [];
115
147
  const request = {
@@ -152,7 +184,7 @@ export default class aster extends asterRest {
152
184
  if (symbolsLength === 0) {
153
185
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
154
186
  }
155
- const url = this.urls['api']['ws'][type];
187
+ const url = this.urls['api']['ws']['public'][type];
156
188
  const subscriptionArgs = [];
157
189
  const messageHashes = [];
158
190
  const request = {
@@ -220,7 +252,7 @@ export default class aster extends asterRest {
220
252
  if (symbolsLength === 0) {
221
253
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
222
254
  }
223
- const url = this.urls['api']['ws'][type];
255
+ const url = this.urls['api']['ws']['public'][type];
224
256
  const subscriptionArgs = [];
225
257
  const messageHashes = [];
226
258
  const request = {
@@ -265,7 +297,7 @@ export default class aster extends asterRest {
265
297
  if (symbolsLength === 0) {
266
298
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
267
299
  }
268
- const url = this.urls['api']['ws'][type];
300
+ const url = this.urls['api']['ws']['public'][type];
269
301
  const subscriptionArgs = [];
270
302
  const messageHashes = [];
271
303
  const request = {
@@ -391,7 +423,7 @@ export default class aster extends asterRest {
391
423
  if (symbolsLength === 0) {
392
424
  throw new ArgumentsRequired(this.id + ' watchBidsAsks() requires a non-empty array of symbols');
393
425
  }
394
- const url = this.urls['api']['ws'][type];
426
+ const url = this.urls['api']['ws']['public'][type];
395
427
  const subscriptionArgs = [];
396
428
  const messageHashes = [];
397
429
  const request = {
@@ -431,7 +463,7 @@ export default class aster extends asterRest {
431
463
  if (symbolsLength === 0) {
432
464
  throw new ArgumentsRequired(this.id + ' unWatchBidsAsks() requires a non-empty array of symbols');
433
465
  }
434
- const url = this.urls['api']['ws'][type];
466
+ const url = this.urls['api']['ws']['public'][type];
435
467
  const subscriptionArgs = [];
436
468
  const messageHashes = [];
437
469
  const request = {
@@ -542,7 +574,7 @@ export default class aster extends asterRest {
542
574
  if (symbolsLength === 0) {
543
575
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
544
576
  }
545
- const url = this.urls['api']['ws'][type];
577
+ const url = this.urls['api']['ws']['public'][type];
546
578
  const subscriptionArgs = [];
547
579
  const messageHashes = [];
548
580
  const request = {
@@ -585,7 +617,7 @@ export default class aster extends asterRest {
585
617
  if (symbolsLength === 0) {
586
618
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
587
619
  }
588
- const url = this.urls['api']['ws'][type];
620
+ const url = this.urls['api']['ws']['public'][type];
589
621
  const subscriptionArgs = [];
590
622
  const messageHashes = [];
591
623
  const request = {
@@ -637,30 +669,158 @@ export default class aster extends asterRest {
637
669
  client.resolve(stored, messageHash);
638
670
  }
639
671
  parseWsTrade(trade, market = undefined) {
672
+ //
673
+ // public watchTrades
674
+ //
675
+ // {
676
+ // "e": "trade", // event type
677
+ // "E": 1579481530911, // event time
678
+ // "s": "ETHBTC", // symbol
679
+ // "t": 158410082, // trade id
680
+ // "p": "0.01914100", // price
681
+ // "q": "0.00700000", // quantity
682
+ // "b": 586187049, // buyer order id
683
+ // "a": 586186710, // seller order id
684
+ // "T": 1579481530910, // trade time
685
+ // "m": false, // is the buyer the market maker
686
+ // "M": true // binance docs say it should be ignored
687
+ // }
688
+ //
689
+ // {
690
+ // "e": "aggTrade", // Event type
691
+ // "E": 123456789, // Event time
692
+ // "s": "BNBBTC", // Symbol
693
+ // "a": 12345, // Aggregate trade ID
694
+ // "p": "0.001", // Price
695
+ // "q": "100", // Quantity
696
+ // "f": 100, // First trade ID
697
+ // "l": 105, // Last trade ID
698
+ // "T": 123456785, // Trade time
699
+ // "m": true, // Is the buyer the market maker?
700
+ // "M": true // Ignore
701
+ // }
702
+ //
703
+ // private watchMyTrades spot
704
+ //
705
+ // {
706
+ // "e": "executionReport",
707
+ // "E": 1611063861489,
708
+ // "s": "BNBUSDT",
709
+ // "c": "m4M6AD5MF3b1ERe65l4SPq",
710
+ // "S": "BUY",
711
+ // "o": "MARKET",
712
+ // "f": "GTC",
713
+ // "q": "2.00000000",
714
+ // "p": "0.00000000",
715
+ // "P": "0.00000000",
716
+ // "F": "0.00000000",
717
+ // "g": -1,
718
+ // "C": '',
719
+ // "x": "TRADE",
720
+ // "X": "PARTIALLY_FILLED",
721
+ // "r": "NONE",
722
+ // "i": 1296882607,
723
+ // "l": "0.33200000",
724
+ // "z": "0.33200000",
725
+ // "L": "46.86600000",
726
+ // "n": "0.00033200",
727
+ // "N": "BNB",
728
+ // "T": 1611063861488,
729
+ // "t": 109747654,
730
+ // "I": 2696953381,
731
+ // "w": false,
732
+ // "m": false,
733
+ // "M": true,
734
+ // "O": 1611063861488,
735
+ // "Z": "15.55951200",
736
+ // "Y": "15.55951200",
737
+ // "Q": "0.00000000"
738
+ // }
739
+ //
740
+ // private watchMyTrades future/delivery
741
+ //
742
+ // {
743
+ // "s": "BTCUSDT",
744
+ // "c": "pb2jD6ZQHpfzSdUac8VqMK",
745
+ // "S": "SELL",
746
+ // "o": "MARKET",
747
+ // "f": "GTC",
748
+ // "q": "0.001",
749
+ // "p": "0",
750
+ // "ap": "33468.46000",
751
+ // "sp": "0",
752
+ // "x": "TRADE",
753
+ // "X": "FILLED",
754
+ // "i": 13351197194,
755
+ // "l": "0.001",
756
+ // "z": "0.001",
757
+ // "L": "33468.46",
758
+ // "n": "0.00027086",
759
+ // "N": "BNB",
760
+ // "T": 1612095165362,
761
+ // "t": 458032604,
762
+ // "b": "0",
763
+ // "a": "0",
764
+ // "m": false,
765
+ // "R": false,
766
+ // "wt": "CONTRACT_PRICE",
767
+ // "ot": "MARKET",
768
+ // "ps": "BOTH",
769
+ // "cp": false,
770
+ // "rp": "0.00335000",
771
+ // "pP": false,
772
+ // "si": 0,
773
+ // "ss": 0
774
+ // }
775
+ //
776
+ const id = this.safeString2(trade, 't', 'a');
640
777
  const timestamp = this.safeInteger(trade, 'T');
641
- const symbol = market['symbol'];
642
- const amountString = this.safeString(trade, 'q');
643
- const priceString = this.safeString(trade, 'p');
644
- const isMaker = this.safeBool(trade, 'm');
778
+ const price = this.safeString2(trade, 'L', 'p');
779
+ const amount = this.safeString2(trade, 'q', 'l');
780
+ let cost = this.safeString(trade, 'Y');
781
+ if (cost === undefined) {
782
+ if ((price !== undefined) && (amount !== undefined)) {
783
+ cost = Precise.stringMul(price, amount);
784
+ }
785
+ }
786
+ const marketId = this.safeString(trade, 's');
787
+ const defaultType = (market === undefined) ? this.safeString(this.options, 'defaultType', 'spot') : market['type'];
788
+ const symbol = this.safeSymbol(marketId, market, undefined, defaultType);
789
+ let side = this.safeStringLower(trade, 'S');
645
790
  let takerOrMaker = undefined;
646
- if (isMaker !== undefined) {
647
- takerOrMaker = isMaker ? 'maker' : 'taker';
791
+ const orderId = this.safeString(trade, 'i');
792
+ if ('m' in trade) {
793
+ if (side === undefined) {
794
+ side = trade['m'] ? 'sell' : 'buy'; // this is reversed intentionally
795
+ }
796
+ takerOrMaker = trade['m'] ? 'maker' : 'taker';
797
+ }
798
+ let fee = undefined;
799
+ const feeCost = this.safeString(trade, 'n');
800
+ if (feeCost !== undefined) {
801
+ const feeCurrencyId = this.safeString(trade, 'N');
802
+ const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
803
+ fee = {
804
+ 'cost': feeCost,
805
+ 'currency': feeCurrencyCode,
806
+ };
648
807
  }
808
+ const type = this.safeStringLower(trade, 'o');
649
809
  return this.safeTrade({
650
- 'id': this.safeString(trade, 'a'),
651
810
  'info': trade,
652
811
  'timestamp': timestamp,
653
812
  'datetime': this.iso8601(timestamp),
654
813
  'symbol': symbol,
655
- 'order': undefined,
656
- 'type': undefined,
657
- 'side': undefined,
814
+ 'id': id,
815
+ 'order': orderId,
816
+ 'type': type,
658
817
  'takerOrMaker': takerOrMaker,
659
- 'price': priceString,
660
- 'amount': amountString,
661
- 'cost': undefined,
662
- 'fee': undefined,
663
- }, market);
818
+ 'side': side,
819
+ 'price': price,
820
+ 'amount': amount,
821
+ 'cost': cost,
822
+ 'fee': fee,
823
+ });
664
824
  }
665
825
  /**
666
826
  * @method
@@ -715,7 +875,7 @@ export default class aster extends asterRest {
715
875
  if (symbolsLength === 0) {
716
876
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
717
877
  }
718
- const url = this.urls['api']['ws'][type];
878
+ const url = this.urls['api']['ws']['public'][type];
719
879
  const subscriptionArgs = [];
720
880
  const messageHashes = [];
721
881
  const request = {
@@ -757,7 +917,7 @@ export default class aster extends asterRest {
757
917
  if (symbolsLength === 0) {
758
918
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
759
919
  }
760
- const url = this.urls['api']['ws'][type];
920
+ const url = this.urls['api']['ws']['public'][type];
761
921
  const subscriptionArgs = [];
762
922
  const messageHashes = [];
763
923
  const request = {
@@ -882,7 +1042,7 @@ export default class aster extends asterRest {
882
1042
  const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
883
1043
  const firstMarket = this.market(marketSymbols[0]);
884
1044
  const type = this.safeString(firstMarket, 'type', 'swap');
885
- const url = this.urls['api']['ws'][type];
1045
+ const url = this.urls['api']['ws']['public'][type];
886
1046
  const subscriptionArgs = [];
887
1047
  const messageHashes = [];
888
1048
  const request = {
@@ -929,7 +1089,7 @@ export default class aster extends asterRest {
929
1089
  const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
930
1090
  const firstMarket = this.market(marketSymbols[0]);
931
1091
  const type = this.safeString(firstMarket, 'type', 'swap');
932
- const url = this.urls['api']['ws'][type];
1092
+ const url = this.urls['api']['ws']['public'][type];
933
1093
  const subscriptionArgs = [];
934
1094
  const messageHashes = [];
935
1095
  const request = {
@@ -1013,6 +1173,704 @@ export default class aster extends asterRest {
1013
1173
  this.safeNumber(ohlcv, 'v'),
1014
1174
  ];
1015
1175
  }
1176
+ async authenticate(type = 'spot', params = {}) {
1177
+ const time = this.milliseconds();
1178
+ const lastAuthenticatedTimeOptions = this.safeDict(this.options, 'lastAuthenticatedTime', {});
1179
+ const lastAuthenticatedTime = this.safeInteger(lastAuthenticatedTimeOptions, type, 0);
1180
+ const listenKeyRefreshRateOptions = this.safeDict(this.options, 'listenKeyRefreshRate', {});
1181
+ const listenKeyRefreshRate = this.safeInteger(listenKeyRefreshRateOptions, type, 3600000); // 1 hour
1182
+ if (time - lastAuthenticatedTime > listenKeyRefreshRate) {
1183
+ let response = undefined;
1184
+ if (type === 'spot') {
1185
+ response = await this.sapiPrivatePostV1ListenKey(params);
1186
+ }
1187
+ else {
1188
+ response = await this.fapiPrivatePostV1ListenKey(params);
1189
+ }
1190
+ this.options['listenKey'][type] = this.safeString(response, 'listenKey');
1191
+ this.options['lastAuthenticatedTime'][type] = time;
1192
+ params = this.extend({ 'type': type }, params);
1193
+ this.delay(listenKeyRefreshRate, this.keepAliveListenKey, params);
1194
+ }
1195
+ }
1196
+ async keepAliveListenKey(params = {}) {
1197
+ const type = this.safeString(params, 'type', 'spot');
1198
+ const listenKeyOptions = this.safeDict(this.options, 'listenKey', {});
1199
+ const listenKey = this.safeString(listenKeyOptions, type);
1200
+ if (listenKey === undefined) {
1201
+ return;
1202
+ }
1203
+ try {
1204
+ await this.sapiPrivatePutV1ListenKey(); // extend the expiry
1205
+ }
1206
+ catch (error) {
1207
+ const url = this.urls['api']['ws']['private'][type] + '/' + listenKey;
1208
+ const client = this.client(url);
1209
+ const messageHashes = Object.keys(client.futures);
1210
+ for (let i = 0; i < messageHashes.length; i++) {
1211
+ const messageHash = messageHashes[i];
1212
+ client.reject(error, messageHash);
1213
+ }
1214
+ this.options['listenKey'][type] = undefined;
1215
+ this.options['lastAuthenticatedTime'][type] = 0;
1216
+ return;
1217
+ }
1218
+ // whether or not to schedule another listenKey keepAlive request
1219
+ const listenKeyRefreshOptions = this.safeDict(this.options, 'listenKeyRefresh', {});
1220
+ const listenKeyRefreshRate = this.safeInteger(listenKeyRefreshOptions, 'listenKeyRefreshRate', 3600000);
1221
+ this.delay(listenKeyRefreshRate, this.keepAliveListenKey, params);
1222
+ }
1223
+ getPrivateUrl(type = 'spot') {
1224
+ const listenKeyOptions = this.safeDict(this.options, 'listenKey', {});
1225
+ const listenKey = this.safeString(listenKeyOptions, type);
1226
+ const url = this.urls['api']['ws']['private'][type] + '/' + listenKey;
1227
+ return url;
1228
+ }
1229
+ /**
1230
+ * @method
1231
+ * @name aster#watchBalance
1232
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
1233
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#payload-account_update
1234
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#event-balance-and-position-update
1235
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1236
+ * @param {string} [params.type] 'spot' or 'swap', default is 'spot'
1237
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
1238
+ */
1239
+ async watchBalance(params = {}) {
1240
+ await this.loadMarkets();
1241
+ let type = undefined;
1242
+ [type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params, type);
1243
+ await this.authenticate(type, params);
1244
+ const url = this.getPrivateUrl(type);
1245
+ const client = this.client(url);
1246
+ this.setBalanceCache(client, type);
1247
+ const options = this.safeDict(this.options, 'watchBalance');
1248
+ const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
1249
+ const awaitBalanceSnapshot = this.safeBool(options, 'awaitBalanceSnapshot', true);
1250
+ if (fetchBalanceSnapshot && awaitBalanceSnapshot) {
1251
+ await client.future(type + ':fetchBalanceSnapshot');
1252
+ }
1253
+ const messageHash = type + ':balance';
1254
+ const message = undefined;
1255
+ return await this.watch(url, messageHash, message, type);
1256
+ }
1257
+ setBalanceCache(client, type) {
1258
+ if ((type in client.subscriptions) && (type in this.balance)) {
1259
+ return;
1260
+ }
1261
+ const options = this.safeValue(this.options, 'watchBalance');
1262
+ const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
1263
+ if (fetchBalanceSnapshot) {
1264
+ const messageHash = type + ':fetchBalanceSnapshot';
1265
+ if (!(messageHash in client.futures)) {
1266
+ client.future(messageHash);
1267
+ this.spawn(this.loadBalanceSnapshot, client, messageHash, type);
1268
+ }
1269
+ }
1270
+ else {
1271
+ this.balance[type] = {};
1272
+ }
1273
+ }
1274
+ async loadBalanceSnapshot(client, messageHash, type) {
1275
+ const params = {
1276
+ 'type': type,
1277
+ };
1278
+ const response = await this.fetchBalance(params);
1279
+ this.balance[type] = this.extend(response, this.safeValue(this.balance, type, {}));
1280
+ // don't remove the future from the .futures cache
1281
+ if (messageHash in client.futures) {
1282
+ const future = client.futures[messageHash];
1283
+ future.resolve();
1284
+ client.resolve(this.balance[type], type + ':balance');
1285
+ }
1286
+ }
1287
+ handleBalance(client, message) {
1288
+ //
1289
+ // spot balance update
1290
+ // {
1291
+ // "B": [
1292
+ // {
1293
+ // "a": "USDT",
1294
+ // "f": "16.29445191",
1295
+ // "l": "0"
1296
+ // },
1297
+ // {
1298
+ // "a": "ETH",
1299
+ // "f": "0.00199920",
1300
+ // "l": "0"
1301
+ // }
1302
+ // ],
1303
+ // "e": "outboundAccountPosition",
1304
+ // "T": 1768547778317,
1305
+ // "u": 1768547778317,
1306
+ // "E": 1768547778321,
1307
+ // "m": "ORDER"
1308
+ // }
1309
+ //
1310
+ // swap balance and position update
1311
+ // {
1312
+ // "e": "ACCOUNT_UPDATE",
1313
+ // "T": 1768551627708,
1314
+ // "E": 1768551627710,
1315
+ // "a": {
1316
+ // "B": [
1317
+ // {
1318
+ // "a": "USDT",
1319
+ // "wb": "39.41184271",
1320
+ // "cw": "39.41184271",
1321
+ // "bc": "0"
1322
+ // }
1323
+ // ],
1324
+ // "P": [
1325
+ // {
1326
+ // "s": "ETHUSDT",
1327
+ // "pa": "0",
1328
+ // "ep": "0.00000000",
1329
+ // "cr": "-0.59070000",
1330
+ // "up": "0",
1331
+ // "mt": "isolated",
1332
+ // "iw": "0",
1333
+ // "ps": "BOTH",
1334
+ // "ma": "USDT"
1335
+ // }
1336
+ // ],
1337
+ // "m": "ORDER"
1338
+ // }
1339
+ // }
1340
+ //
1341
+ const subscriptions = client.subscriptions;
1342
+ const subscriptionsKeys = Object.keys(subscriptions);
1343
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
1344
+ const messageHash = accountType + ':balance';
1345
+ if (this.balance[accountType] === undefined) {
1346
+ this.balance[accountType] = {};
1347
+ }
1348
+ this.balance[accountType]['info'] = message;
1349
+ message = this.safeDict(message, 'a', message);
1350
+ const B = this.safeList(message, 'B', []);
1351
+ const wallet = this.safeString(this.options, 'wallet', 'wb');
1352
+ for (let i = 0; i < B.length; i++) {
1353
+ const entry = B[i];
1354
+ const currencyId = this.safeString(entry, 'a');
1355
+ const code = this.safeCurrencyCode(currencyId);
1356
+ const account = this.account();
1357
+ account['free'] = this.safeString(entry, 'f');
1358
+ account['used'] = this.safeString(entry, 'l');
1359
+ account['total'] = this.safeString(entry, wallet);
1360
+ this.balance[accountType][code] = account;
1361
+ }
1362
+ const timestamp = this.safeInteger(message, 'E');
1363
+ this.balance[accountType]['timestamp'] = timestamp;
1364
+ this.balance[accountType]['datetime'] = this.iso8601(timestamp);
1365
+ this.balance[accountType] = this.safeBalance(this.balance[accountType]);
1366
+ client.resolve(this.balance[accountType], messageHash);
1367
+ }
1368
+ /**
1369
+ * @method
1370
+ * @name aster#watchPositions
1371
+ * @description watch all open positions
1372
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#event-balance-and-position-update
1373
+ * @param {string[]|undefined} symbols list of unified market symbols
1374
+ * @param {number} [since] since timestamp
1375
+ * @param {number} [limit] limit
1376
+ * @param {object} params extra parameters specific to the exchange API endpoint
1377
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
1378
+ */
1379
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
1380
+ await this.loadMarkets();
1381
+ const type = 'swap';
1382
+ await this.authenticate(type, params);
1383
+ const url = this.getPrivateUrl(type);
1384
+ const client = this.client(url);
1385
+ this.setPositionsCache(client);
1386
+ const messageHashes = [];
1387
+ const messageHash = 'positions';
1388
+ symbols = this.marketSymbols(symbols, 'swap', true, true);
1389
+ if (symbols === undefined) {
1390
+ messageHashes.push(messageHash);
1391
+ }
1392
+ else {
1393
+ for (let i = 0; i < symbols.length; i++) {
1394
+ const symbol = symbols[i];
1395
+ messageHashes.push(messageHash + '::' + symbol);
1396
+ }
1397
+ }
1398
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
1399
+ const awaitPositionsSnapshot = this.handleOption('watchPositions', 'awaitPositionsSnapshot', true);
1400
+ const cache = this.positions;
1401
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
1402
+ const snapshot = await client.future('fetchPositionsSnapshot');
1403
+ return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
1404
+ }
1405
+ const newPositions = await this.watchMultiple(url, messageHashes, undefined, [type]);
1406
+ if (this.newUpdates) {
1407
+ return newPositions;
1408
+ }
1409
+ return this.filterBySymbolsSinceLimit(cache, symbols, since, limit, true);
1410
+ }
1411
+ setPositionsCache(client) {
1412
+ if (this.positions !== undefined) {
1413
+ return;
1414
+ }
1415
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', false);
1416
+ if (fetchPositionsSnapshot) {
1417
+ const messageHash = 'fetchPositionsSnapshot';
1418
+ if (!(messageHash in client.futures)) {
1419
+ client.future(messageHash);
1420
+ this.spawn(this.loadPositionsSnapshot, client, messageHash);
1421
+ }
1422
+ }
1423
+ else {
1424
+ this.positions = new ArrayCacheBySymbolBySide();
1425
+ }
1426
+ }
1427
+ async loadPositionsSnapshot(client, messageHash) {
1428
+ const positions = await this.fetchPositions();
1429
+ this.positions = new ArrayCacheBySymbolBySide();
1430
+ const cache = this.positions;
1431
+ for (let i = 0; i < positions.length; i++) {
1432
+ const position = positions[i];
1433
+ const contracts = this.safeNumber(position, 'contracts', 0);
1434
+ if (contracts > 0) {
1435
+ cache.append(position);
1436
+ }
1437
+ }
1438
+ // don't remove the future from the .futures cache
1439
+ if (messageHash in client.futures) {
1440
+ const future = client.futures[messageHash];
1441
+ future.resolve(cache);
1442
+ client.resolve(cache, 'positions');
1443
+ }
1444
+ }
1445
+ handlePositions(client, message) {
1446
+ //
1447
+ // {
1448
+ // "e": "ACCOUNT_UPDATE",
1449
+ // "T": 1768551627708,
1450
+ // "E": 1768551627710,
1451
+ // "a": {
1452
+ // "B": [
1453
+ // {
1454
+ // "a": "USDT",
1455
+ // "wb": "39.41184271",
1456
+ // "cw": "39.41184271",
1457
+ // "bc": "0"
1458
+ // }
1459
+ // ],
1460
+ // "P": [
1461
+ // {
1462
+ // "s": "ETHUSDT",
1463
+ // "pa": "0",
1464
+ // "ep": "0.00000000",
1465
+ // "cr": "-0.59070000",
1466
+ // "up": "0",
1467
+ // "mt": "isolated",
1468
+ // "iw": "0",
1469
+ // "ps": "BOTH",
1470
+ // "ma": "USDT"
1471
+ // }
1472
+ // ],
1473
+ // "m": "ORDER"
1474
+ // }
1475
+ // }
1476
+ //
1477
+ const messageHash = 'positions';
1478
+ const messageHashes = this.findMessageHashes(client, messageHash);
1479
+ if (!this.isEmpty(messageHashes)) {
1480
+ if (this.positions === undefined) {
1481
+ this.positions = new ArrayCacheBySymbolBySide();
1482
+ }
1483
+ const cache = this.positions;
1484
+ const data = this.safeDict(message, 'a', {});
1485
+ const rawPositions = this.safeList(data, 'P', []);
1486
+ const newPositions = [];
1487
+ for (let i = 0; i < rawPositions.length; i++) {
1488
+ const rawPosition = rawPositions[i];
1489
+ const position = this.parseWsPosition(rawPosition);
1490
+ const timestamp = this.safeInteger(message, 'E');
1491
+ position['timestamp'] = timestamp;
1492
+ position['datetime'] = this.iso8601(timestamp);
1493
+ newPositions.push(position);
1494
+ cache.append(position);
1495
+ const symbol = position['symbol'];
1496
+ const symbolMessageHash = messageHash + '::' + symbol;
1497
+ client.resolve(position, symbolMessageHash);
1498
+ }
1499
+ client.resolve(newPositions, 'positions');
1500
+ }
1501
+ }
1502
+ parseWsPosition(position, market = undefined) {
1503
+ //
1504
+ // {
1505
+ // "s": "BTCUSDT", // Symbol
1506
+ // "pa": "0", // Position Amount
1507
+ // "ep": "0.00000", // Entry Price
1508
+ // "cr": "200", // (Pre-fee) Accumulated Realized
1509
+ // "up": "0", // Unrealized PnL
1510
+ // "mt": "isolated", // Margin Type
1511
+ // "iw": "0.00000000", // Isolated Wallet (if isolated position)
1512
+ // "ps": "BOTH" // Position Side
1513
+ // }
1514
+ //
1515
+ const marketId = this.safeString(position, 's');
1516
+ const contracts = this.safeString(position, 'pa');
1517
+ const contractsAbs = Precise.stringAbs(this.safeString(position, 'pa'));
1518
+ let positionSide = this.safeStringLower(position, 'ps');
1519
+ let hedged = true;
1520
+ if (positionSide === 'both') {
1521
+ hedged = false;
1522
+ if (!Precise.stringEq(contracts, '0')) {
1523
+ if (Precise.stringLt(contracts, '0')) {
1524
+ positionSide = 'short';
1525
+ }
1526
+ else {
1527
+ positionSide = 'long';
1528
+ }
1529
+ }
1530
+ }
1531
+ return this.safePosition({
1532
+ 'info': position,
1533
+ 'id': undefined,
1534
+ 'symbol': this.safeSymbol(marketId, undefined, undefined, 'swap'),
1535
+ 'notional': undefined,
1536
+ 'marginMode': this.safeString(position, 'mt'),
1537
+ 'liquidationPrice': undefined,
1538
+ 'entryPrice': this.safeNumber(position, 'ep'),
1539
+ 'unrealizedPnl': this.safeNumber(position, 'up'),
1540
+ 'percentage': undefined,
1541
+ 'contracts': this.parseNumber(contractsAbs),
1542
+ 'contractSize': undefined,
1543
+ 'markPrice': undefined,
1544
+ 'side': positionSide,
1545
+ 'hedged': hedged,
1546
+ 'timestamp': undefined,
1547
+ 'datetime': undefined,
1548
+ 'maintenanceMargin': undefined,
1549
+ 'maintenanceMarginPercentage': undefined,
1550
+ 'collateral': undefined,
1551
+ 'initialMargin': undefined,
1552
+ 'initialMarginPercentage': undefined,
1553
+ 'leverage': undefined,
1554
+ 'marginRatio': undefined,
1555
+ });
1556
+ }
1557
+ /**
1558
+ * @method
1559
+ * @name aster#watchOrders
1560
+ * @description watches information on multiple orders made by the user
1561
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#payload-order-update
1562
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#event-order-update
1563
+ * @param {string} [symbol] unified market symbol of the market orders were made in
1564
+ * @param {int} [since] the earliest time in ms to fetch orders for
1565
+ * @param {int} [limit] the maximum number of order structures to retrieve
1566
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1567
+ * @param {string} [params.type] 'spot' or 'swap', default is 'spot' if symbol is not provided
1568
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1569
+ */
1570
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1571
+ await this.loadMarkets();
1572
+ let market = undefined;
1573
+ if (symbol !== undefined) {
1574
+ market = this.market(symbol);
1575
+ symbol = market['symbol'];
1576
+ }
1577
+ let messageHash = 'orders';
1578
+ let type = undefined;
1579
+ [type, params] = this.handleMarketTypeAndParams('watchOrders', market, params, type);
1580
+ await this.authenticate(type, params);
1581
+ if (market !== undefined) {
1582
+ messageHash += '::' + symbol;
1583
+ }
1584
+ const url = this.getPrivateUrl(type);
1585
+ const client = this.client(url);
1586
+ this.setBalanceCache(client, type);
1587
+ const orders = await this.watchMultiple(url, [messageHash], undefined, [type]);
1588
+ if (this.newUpdates) {
1589
+ limit = orders.getLimit(symbol, limit);
1590
+ }
1591
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
1592
+ }
1593
+ /**
1594
+ * @method
1595
+ * @name aster#watchMyTrades
1596
+ * @description watches information on multiple trades made by the user
1597
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#payload-order-update
1598
+ * @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#event-order-update
1599
+ * @param {string} [symbol] unified market symbol of the market orders were made in
1600
+ * @param {int} [since] the earliest time in ms to fetch orders for
1601
+ * @param {int} [limit] the maximum number of order structures to retrieve
1602
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1603
+ * @param {string} [params.type] 'spot' or 'swap', default is 'spot' if symbol is not provided
1604
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
1605
+ */
1606
+ async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1607
+ await this.loadMarkets();
1608
+ let market = undefined;
1609
+ if (symbol !== undefined) {
1610
+ market = this.market(symbol);
1611
+ symbol = market['symbol'];
1612
+ }
1613
+ let messageHash = 'myTrades';
1614
+ let type = undefined;
1615
+ [type, params] = this.handleMarketTypeAndParams('watchOrders', market, params, type);
1616
+ await this.authenticate(type, params);
1617
+ if (market !== undefined) {
1618
+ messageHash += '::' + symbol;
1619
+ }
1620
+ const url = this.getPrivateUrl(type);
1621
+ const client = this.client(url);
1622
+ this.setBalanceCache(client, type);
1623
+ const trades = await this.watchMultiple(url, [messageHash], undefined, [type]);
1624
+ if (this.newUpdates) {
1625
+ limit = trades.getLimit(symbol, limit);
1626
+ }
1627
+ return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
1628
+ }
1629
+ handleOrderUpdate(client, message) {
1630
+ const rawOrder = this.safeDict(message, 'o', message);
1631
+ const e = this.safeString(message, 'e');
1632
+ if ((e === 'ORDER_TRADE_UPDATE') || (e === 'ALGO_UPDATE')) {
1633
+ message = this.safeDict(message, 'o', message);
1634
+ }
1635
+ this.handleOrder(client, rawOrder);
1636
+ this.handleMyTrade(client, message);
1637
+ }
1638
+ handleMyTrade(client, message) {
1639
+ const messageHash = 'myTrades';
1640
+ const executionType = this.safeString(message, 'x');
1641
+ if (executionType === 'TRADE') {
1642
+ const isSwap = client.url.indexOf('fstream') >= 0;
1643
+ const type = isSwap ? 'swap' : 'spot';
1644
+ const fakeMarket = this.safeMarketStructure({ 'type': type });
1645
+ const trade = this.parseWsTrade(message, fakeMarket);
1646
+ const orderId = this.safeString(trade, 'order');
1647
+ let tradeFee = this.safeDict(trade, 'fee', {});
1648
+ tradeFee = this.extend({}, tradeFee);
1649
+ const symbol = this.safeString(trade, 'symbol');
1650
+ if (orderId !== undefined && tradeFee !== undefined && symbol !== undefined) {
1651
+ const cachedOrders = this.orders;
1652
+ if (cachedOrders !== undefined) {
1653
+ const orders = this.safeValue(cachedOrders.hashmap, symbol, {});
1654
+ const order = this.safeValue(orders, orderId);
1655
+ if (order !== undefined) {
1656
+ // accumulate order fees
1657
+ const fees = this.safeValue(order, 'fees');
1658
+ const fee = this.safeValue(order, 'fee');
1659
+ if (!this.isEmpty(fees)) {
1660
+ let insertNewFeeCurrency = true;
1661
+ for (let i = 0; i < fees.length; i++) {
1662
+ const orderFee = fees[i];
1663
+ if (orderFee['currency'] === tradeFee['currency']) {
1664
+ const feeCost = this.sum(tradeFee['cost'], orderFee['cost']);
1665
+ order['fees'][i]['cost'] = parseFloat(this.currencyToPrecision(tradeFee['currency'], feeCost));
1666
+ insertNewFeeCurrency = false;
1667
+ break;
1668
+ }
1669
+ }
1670
+ if (insertNewFeeCurrency) {
1671
+ order['fees'].push(tradeFee);
1672
+ }
1673
+ }
1674
+ else if (fee !== undefined) {
1675
+ if (fee['currency'] === tradeFee['currency']) {
1676
+ const feeCost = this.sum(fee['cost'], tradeFee['cost']);
1677
+ order['fee']['cost'] = parseFloat(this.currencyToPrecision(tradeFee['currency'], feeCost));
1678
+ }
1679
+ else if (fee['currency'] === undefined) {
1680
+ order['fee'] = tradeFee;
1681
+ }
1682
+ else {
1683
+ order['fees'] = [fee, tradeFee];
1684
+ order['fee'] = undefined;
1685
+ }
1686
+ }
1687
+ else {
1688
+ order['fee'] = tradeFee;
1689
+ }
1690
+ // save this trade in the order
1691
+ const orderTrades = this.safeList(order, 'trades', []);
1692
+ orderTrades.push(trade);
1693
+ order['trades'] = orderTrades;
1694
+ // don't append twice cause it breaks newUpdates mode
1695
+ // this order already exists in the cache
1696
+ }
1697
+ }
1698
+ }
1699
+ if (this.myTrades === undefined) {
1700
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
1701
+ this.myTrades = new ArrayCacheBySymbolById(limit);
1702
+ }
1703
+ const myTrades = this.myTrades;
1704
+ myTrades.append(trade);
1705
+ client.resolve(this.myTrades, messageHash);
1706
+ const messageHashSymbol = messageHash + ':' + symbol;
1707
+ client.resolve(this.myTrades, messageHashSymbol);
1708
+ }
1709
+ }
1710
+ handleOrder(client, message) {
1711
+ //
1712
+ // spot
1713
+ // {
1714
+ // "e": "executionReport", // Event type
1715
+ // "E": 1499405658658, // Event time
1716
+ // "s": "ETHBTC", // Symbol
1717
+ // "c": "mUvoqJxFIILMdfAW5iGSOW", // Client order ID
1718
+ // "S": "BUY", // Side
1719
+ // "o": "LIMIT", // Order type
1720
+ // "f": "GTC", // Time in force
1721
+ // "q": "1.00000000", // Order quantity
1722
+ // "p": "0.10264410", // Order price
1723
+ // "P": "0.00000000", // Stop price
1724
+ // "F": "0.00000000", // Iceberg quantity
1725
+ // "g": -1, // OrderListId
1726
+ // "C": null, // Original client order ID; This is the ID of the order being canceled
1727
+ // "x": "NEW", // Current execution type
1728
+ // "X": "NEW", // Current order status
1729
+ // "r": "NONE", // Order reject reason; will be an error code.
1730
+ // "i": 4293153, // Order ID
1731
+ // "l": "0.00000000", // Last executed quantity
1732
+ // "z": "0.00000000", // Cumulative filled quantity
1733
+ // "L": "0.00000000", // Last executed price
1734
+ // "n": "0", // Commission amount
1735
+ // "N": null, // Commission asset
1736
+ // "T": 1499405658657, // Transaction time
1737
+ // "t": -1, // Trade ID
1738
+ // "I": 8641984, // Ignore
1739
+ // "w": true, // Is the order on the book?
1740
+ // "m": false, // Is this trade the maker side?
1741
+ // "M": false, // Ignore
1742
+ // "O": 1499405658657, // Order creation time
1743
+ // "Z": "0.00000000", // Cumulative quote asset transacted quantity
1744
+ // "Y": "0.00000000" // Last quote asset transacted quantity (i.e. lastPrice * lastQty),
1745
+ // "Q": "0.00000000" // Quote Order Qty
1746
+ // }
1747
+ //
1748
+ // swap
1749
+ // {
1750
+ // "s":"BTCUSDT", // Symbol
1751
+ // "c":"TEST", // Client Order Id
1752
+ // // special client order id:
1753
+ // // starts with "autoclose-": liquidation order
1754
+ // // "adl_autoclose": ADL auto close order
1755
+ // "S":"SELL", // Side
1756
+ // "o":"TRAILING_STOP_MARKET", // Order Type
1757
+ // "f":"GTC", // Time in Force
1758
+ // "q":"0.001", // Original Quantity
1759
+ // "p":"0", // Original Price
1760
+ // "ap":"0", // Average Price
1761
+ // "sp":"7103.04", // Stop Price. Please ignore with TRAILING_STOP_MARKET order
1762
+ // "x":"NEW", // Execution Type
1763
+ // "X":"NEW", // Order Status
1764
+ // "i":8886774, // Order Id
1765
+ // "l":"0", // Order Last Filled Quantity
1766
+ // "z":"0", // Order Filled Accumulated Quantity
1767
+ // "L":"0", // Last Filled Price
1768
+ // "N":"USDT", // Commission Asset, will not push if no commission
1769
+ // "n":"0", // Commission, will not push if no commission
1770
+ // "T":1568879465651, // Order Trade Time
1771
+ // "t":0, // Trade Id
1772
+ // "b":"0", // Bids Notional
1773
+ // "a":"9.91", // Ask Notional
1774
+ // "m":false, // Is this trade the maker side?
1775
+ // "R":false, // Is this reduce only
1776
+ // "wt":"CONTRACT_PRICE", // Stop Price Working Type
1777
+ // "ot":"TRAILING_STOP_MARKET", // Original Order Type
1778
+ // "ps":"LONG", // Position Side
1779
+ // "cp":false, // If Close-All, pushed with conditional order
1780
+ // "AP":"7476.89", // Activation Price, only puhed with TRAILING_STOP_MARKET order
1781
+ // "cr":"5.0", // Callback Rate, only puhed with TRAILING_STOP_MARKET order
1782
+ // "rp":"0" // Realized Profit of the trade
1783
+ // }
1784
+ //
1785
+ const messageHash = 'orders';
1786
+ const messageHashes = this.findMessageHashes(client, messageHash);
1787
+ if (!this.isEmpty(messageHashes)) {
1788
+ const market = this.getMarketFromOrder(client, message);
1789
+ if (this.orders === undefined) {
1790
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
1791
+ this.orders = new ArrayCacheBySymbolById(limit);
1792
+ }
1793
+ const cache = this.orders;
1794
+ const parsed = this.parseWsOrder(message, market);
1795
+ const symbol = market['symbol'];
1796
+ const symbolMessageHash = messageHash + '::' + symbol;
1797
+ cache.append(parsed);
1798
+ client.resolve(cache, symbolMessageHash);
1799
+ client.resolve(cache, messageHash);
1800
+ }
1801
+ }
1802
+ parseWsOrder(order, market = undefined) {
1803
+ const executionType = this.safeString(order, 'x');
1804
+ const marketId = this.safeString(order, 's');
1805
+ market = this.safeMarket(marketId, market);
1806
+ let timestamp = this.safeInteger(order, 'O');
1807
+ const T = this.safeInteger(order, 'T');
1808
+ let lastTradeTimestamp = undefined;
1809
+ if (executionType === 'NEW' || executionType === 'AMENDMENT' || executionType === 'CANCELED') {
1810
+ if (timestamp === undefined) {
1811
+ timestamp = T;
1812
+ }
1813
+ }
1814
+ else if (executionType === 'TRADE') {
1815
+ lastTradeTimestamp = T;
1816
+ }
1817
+ const lastUpdateTimestamp = T;
1818
+ let fee = undefined;
1819
+ const feeCost = this.safeString(order, 'n');
1820
+ if ((feeCost !== undefined) && (Precise.stringGt(feeCost, '0'))) {
1821
+ const feeCurrencyId = this.safeString(order, 'N');
1822
+ const feeCurrency = this.safeCurrencyCode(feeCurrencyId);
1823
+ fee = {
1824
+ 'cost': feeCost,
1825
+ 'currency': feeCurrency,
1826
+ };
1827
+ }
1828
+ const rawStatus = this.safeString(order, 'X');
1829
+ const status = this.parseOrderStatus(rawStatus);
1830
+ let clientOrderId = this.safeString2(order, 'C', 'caid');
1831
+ if ((clientOrderId === undefined) || (clientOrderId.length === 0)) {
1832
+ clientOrderId = this.safeString(order, 'c');
1833
+ }
1834
+ const stopPrice = this.safeStringN(order, ['P', 'sp', 'tp']);
1835
+ let timeInForce = this.safeString(order, 'f');
1836
+ if (timeInForce === 'GTX') {
1837
+ // GTX means "Good Till Crossing" and is an equivalent way of saying Post Only
1838
+ timeInForce = 'PO';
1839
+ }
1840
+ return this.safeOrder({
1841
+ 'info': order,
1842
+ 'symbol': market['symbol'],
1843
+ 'id': this.safeString2(order, 'i', 'aid'),
1844
+ 'clientOrderId': clientOrderId,
1845
+ 'timestamp': timestamp,
1846
+ 'datetime': this.iso8601(timestamp),
1847
+ 'lastTradeTimestamp': lastTradeTimestamp,
1848
+ 'lastUpdateTimestamp': lastUpdateTimestamp,
1849
+ 'type': this.parseOrderType(this.safeStringLower(order, 'o')),
1850
+ 'timeInForce': timeInForce,
1851
+ 'postOnly': undefined,
1852
+ 'reduceOnly': this.safeBool(order, 'R'),
1853
+ 'side': this.safeStringLower(order, 'S'),
1854
+ 'price': this.safeString(order, 'p'),
1855
+ 'stopPrice': stopPrice,
1856
+ 'triggerPrice': stopPrice,
1857
+ 'amount': this.safeString(order, 'q'),
1858
+ 'cost': this.safeString(order, 'Z'),
1859
+ 'average': this.safeString(order, 'ap'),
1860
+ 'filled': this.safeString(order, 'z'),
1861
+ 'remaining': undefined,
1862
+ 'status': status,
1863
+ 'fee': fee,
1864
+ 'trades': undefined,
1865
+ });
1866
+ }
1867
+ getMarketFromOrder(client, order) {
1868
+ const marketId = this.safeString(order, 's');
1869
+ const subscriptions = client.subscriptions;
1870
+ const subscriptionsKeys = Object.keys(subscriptions);
1871
+ const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
1872
+ return this.safeMarket(marketId, undefined, undefined, marketType);
1873
+ }
1016
1874
  handleMessage(client, message) {
1017
1875
  const stream = this.safeString(message, 'stream');
1018
1876
  if (stream !== undefined) {
@@ -1035,5 +1893,19 @@ export default class aster extends asterRest {
1035
1893
  method.call(this, client, message);
1036
1894
  }
1037
1895
  }
1896
+ else {
1897
+ // private messages
1898
+ const event = this.safeString(message, 'e');
1899
+ if (event === 'outboundAccountPosition') {
1900
+ this.handleBalance(client, message);
1901
+ }
1902
+ else if (event === 'ACCOUNT_UPDATE') {
1903
+ this.handleBalance(client, message);
1904
+ this.handlePositions(client, message);
1905
+ }
1906
+ else if ((event === 'ORDER_TRADE_UPDATE') || (event === 'executionReport')) {
1907
+ this.handleOrderUpdate(client, message);
1908
+ }
1909
+ }
1038
1910
  }
1039
1911
  }