ccxt 4.5.15 → 4.5.17

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.
package/js/src/delta.js CHANGED
@@ -68,6 +68,7 @@ export default class delta extends Exchange {
68
68
  'fetchOpenOrders': true,
69
69
  'fetchOption': true,
70
70
  'fetchOptionChain': false,
71
+ 'fetchOrder': true,
71
72
  'fetchOrderBook': true,
72
73
  'fetchPosition': true,
73
74
  'fetchPositionMode': false,
@@ -146,6 +147,8 @@ export default class delta extends Exchange {
146
147
  'private': {
147
148
  'get': [
148
149
  'orders',
150
+ 'orders/{order_id}',
151
+ 'orders/client_order_id/{client_oid}',
149
152
  'products/{product_id}/orders/leverage',
150
153
  'positions/margined',
151
154
  'positions',
@@ -159,8 +162,8 @@ export default class delta extends Exchange {
159
162
  'users/trading_preferences',
160
163
  'sub_accounts',
161
164
  'profile',
165
+ 'heartbeat',
162
166
  'deposits/address',
163
- 'orders/leverage',
164
167
  ],
165
168
  'post': [
166
169
  'orders',
@@ -170,6 +173,8 @@ export default class delta extends Exchange {
170
173
  'positions/change_margin',
171
174
  'positions/close_all',
172
175
  'wallets/sub_account_balance_transfer',
176
+ 'heartbeat/create',
177
+ 'heartbeat',
173
178
  'orders/cancel_after',
174
179
  'orders/leverage',
175
180
  ],
@@ -1886,9 +1891,40 @@ export default class delta extends Exchange {
1886
1891
  // "user_id":22142
1887
1892
  // }
1888
1893
  //
1894
+ // fetchOrder
1895
+ //
1896
+ // {
1897
+ // "id": 123,
1898
+ // "user_id": 453671,
1899
+ // "size": 10,
1900
+ // "unfilled_size": 2,
1901
+ // "side": "buy",
1902
+ // "order_type": "limit_order",
1903
+ // "limit_price": "59000",
1904
+ // "stop_order_type": "stop_loss_order",
1905
+ // "stop_price": "55000",
1906
+ // "paid_commission": "0.5432",
1907
+ // "commission": "0.5432",
1908
+ // "reduce_only": false,
1909
+ // "client_order_id": "my_signal_34521712",
1910
+ // "state": "open",
1911
+ // "created_at": "1725865012000000",
1912
+ // "product_id": 27,
1913
+ // "product_symbol": "BTCUSD"
1914
+ // }
1915
+ //
1889
1916
  const id = this.safeString(order, 'id');
1890
1917
  const clientOrderId = this.safeString(order, 'client_order_id');
1891
- const timestamp = this.parse8601(this.safeString(order, 'created_at'));
1918
+ const createdAt = this.safeString(order, 'created_at');
1919
+ let timestamp = undefined;
1920
+ if (createdAt !== undefined) {
1921
+ if (createdAt.indexOf('-') >= 0) {
1922
+ timestamp = this.parse8601(createdAt);
1923
+ }
1924
+ else {
1925
+ timestamp = this.safeIntegerProduct(order, 'created_at', 0.001);
1926
+ }
1927
+ }
1892
1928
  const marketId = this.safeString(order, 'product_id');
1893
1929
  const marketsByNumericId = this.safeDict(this.options, 'marketsByNumericId', {});
1894
1930
  market = this.safeValue(marketsByNumericId, marketId, market);
@@ -1896,7 +1932,9 @@ export default class delta extends Exchange {
1896
1932
  const status = this.parseOrderStatus(this.safeString(order, 'state'));
1897
1933
  const side = this.safeString(order, 'side');
1898
1934
  let type = this.safeString(order, 'order_type');
1899
- type = type.replace('_order', '');
1935
+ if (type !== undefined) {
1936
+ type = type.replace('_order', '');
1937
+ }
1900
1938
  const price = this.safeString(order, 'limit_price');
1901
1939
  const amount = this.safeString(order, 'size');
1902
1940
  const remaining = this.safeString(order, 'unfilled_size');
@@ -2161,6 +2199,63 @@ export default class delta extends Exchange {
2161
2199
  }),
2162
2200
  ];
2163
2201
  }
2202
+ /**
2203
+ * @method
2204
+ * @name delta#fetchOrder
2205
+ * @description fetches information on an order made by the user
2206
+ * @see https://docs.delta.exchange/#get-order-by-id
2207
+ * @see https://docs.delta.exchange/#get-order-by-client-oid
2208
+ * @param {string} id the order id
2209
+ * @param {string} [symbol] unified symbol of the market the order was made in
2210
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2211
+ * @param {string} [params.clientOrderId] client order id of the order
2212
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2213
+ */
2214
+ async fetchOrder(id, symbol = undefined, params = {}) {
2215
+ await this.loadMarkets();
2216
+ let market = undefined;
2217
+ if (symbol !== undefined) {
2218
+ market = this.market(symbol);
2219
+ }
2220
+ const clientOrderId = this.safeStringN(params, ['clientOrderId', 'client_oid', 'clientOid']);
2221
+ params = this.omit(params, ['clientOrderId', 'client_oid', 'clientOid']);
2222
+ const request = {};
2223
+ let response = undefined;
2224
+ if (clientOrderId !== undefined) {
2225
+ request['client_oid'] = clientOrderId;
2226
+ response = await this.privateGetOrdersClientOrderIdClientOid(this.extend(request, params));
2227
+ }
2228
+ else {
2229
+ request['order_id'] = id;
2230
+ response = await this.privateGetOrdersOrderId(this.extend(request, params));
2231
+ }
2232
+ //
2233
+ // {
2234
+ // "success": true,
2235
+ // "result": {
2236
+ // "id": 123,
2237
+ // "user_id": 453671,
2238
+ // "size": 10,
2239
+ // "unfilled_size": 2,
2240
+ // "side": "buy",
2241
+ // "order_type": "limit_order",
2242
+ // "limit_price": "59000",
2243
+ // "stop_order_type": "stop_loss_order",
2244
+ // "stop_price": "55000",
2245
+ // "paid_commission": "0.5432",
2246
+ // "commission": "0.5432",
2247
+ // "reduce_only": false,
2248
+ // "client_order_id": "my_signal_34521712",
2249
+ // "state": "open",
2250
+ // "created_at": "1725865012000000",
2251
+ // "product_id": 27,
2252
+ // "product_symbol": "BTCUSD"
2253
+ // }
2254
+ // }
2255
+ //
2256
+ const result = this.safeDict(response, 'result', {});
2257
+ return this.parseOrder(result, market);
2258
+ }
2164
2259
  /**
2165
2260
  * @method
2166
2261
  * @name delta#fetchOpenOrders
package/js/src/derive.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import Exchange from './abstract/derive.js';
9
- import Precise from './base/Precise.js';
9
+ import { Precise } from './base/Precise.js';
10
10
  import { BadRequest, InvalidOrder, ExchangeError, OrderNotFound, ArgumentsRequired, InsufficientFunds, RateLimitExceeded, AuthenticationError } from './base/errors.js';
11
11
  import { ecdsa } from './base/functions/crypto.js';
12
12
  import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js';
@@ -182,7 +182,9 @@ export default class hyperliquid extends Exchange {
182
182
  s: string;
183
183
  v: any;
184
184
  };
185
+ setRef(): Promise<any>;
185
186
  approveBuilderFee(builder: string, maxFeeRate: string): Promise<any>;
187
+ initializeClient(): Promise<boolean>;
186
188
  handleBuilderFeeApproval(): Promise<boolean>;
187
189
  /**
188
190
  * @method
@@ -411,7 +411,7 @@ export default class hyperliquid extends Exchange {
411
411
  */
412
412
  async fetchCurrencies(params = {}) {
413
413
  if (this.checkRequiredCredentials(false)) {
414
- await this.handleBuilderFeeApproval();
414
+ await this.initializeClient();
415
415
  }
416
416
  const request = {
417
417
  'type': 'meta',
@@ -1473,6 +1473,32 @@ export default class hyperliquid extends Exchange {
1473
1473
  };
1474
1474
  return this.signUserSignedAction(messageTypes, message);
1475
1475
  }
1476
+ async setRef() {
1477
+ if (this.safeBool(this.options, 'refSet', false)) {
1478
+ return true;
1479
+ }
1480
+ this.options['refSet'] = true;
1481
+ const action = {
1482
+ 'type': 'setReferrer',
1483
+ 'code': this.safeString(this.options, 'ref', 'CCXT1'),
1484
+ };
1485
+ const nonce = this.milliseconds();
1486
+ const signature = this.signL1Action(action, nonce);
1487
+ const request = {
1488
+ 'action': action,
1489
+ 'nonce': nonce,
1490
+ 'signature': signature,
1491
+ };
1492
+ let response = undefined;
1493
+ try {
1494
+ response = await this.privatePostExchange(request);
1495
+ return response;
1496
+ }
1497
+ catch (e) {
1498
+ response = undefined; // ignore this
1499
+ }
1500
+ return response;
1501
+ }
1476
1502
  async approveBuilderFee(builder, maxFeeRate) {
1477
1503
  const nonce = this.milliseconds();
1478
1504
  const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
@@ -1507,6 +1533,15 @@ export default class hyperliquid extends Exchange {
1507
1533
  //
1508
1534
  return await this.privatePostExchange(request);
1509
1535
  }
1536
+ async initializeClient() {
1537
+ try {
1538
+ await Promise.all([this.handleBuilderFeeApproval(), this.setRef()]);
1539
+ }
1540
+ catch (e) {
1541
+ return false;
1542
+ }
1543
+ return true;
1544
+ }
1510
1545
  async handleBuilderFeeApproval() {
1511
1546
  const buildFee = this.safeBool(this.options, 'builderFee', true);
1512
1547
  if (!buildFee) {
@@ -1565,7 +1600,7 @@ export default class hyperliquid extends Exchange {
1565
1600
  */
1566
1601
  async createOrders(orders, params = {}) {
1567
1602
  await this.loadMarkets();
1568
- await this.handleBuilderFeeApproval();
1603
+ await this.initializeClient();
1569
1604
  const request = this.createOrdersRequest(orders, params);
1570
1605
  const response = await this.privatePostExchange(request);
1571
1606
  //
@@ -1817,6 +1852,7 @@ export default class hyperliquid extends Exchange {
1817
1852
  throw new ArgumentsRequired(this.id + ' cancelOrders() requires a symbol argument');
1818
1853
  }
1819
1854
  await this.loadMarkets();
1855
+ await this.initializeClient();
1820
1856
  const request = this.cancelOrdersRequest(ids, symbol, params);
1821
1857
  const response = await this.privatePostExchange(request);
1822
1858
  //
@@ -1920,6 +1956,7 @@ export default class hyperliquid extends Exchange {
1920
1956
  async cancelOrdersForSymbols(orders, params = {}) {
1921
1957
  this.checkRequiredCredentials();
1922
1958
  await this.loadMarkets();
1959
+ await this.initializeClient();
1923
1960
  const nonce = this.milliseconds();
1924
1961
  const request = {
1925
1962
  'nonce': nonce,
@@ -1994,6 +2031,7 @@ export default class hyperliquid extends Exchange {
1994
2031
  async cancelAllOrdersAfter(timeout, params = {}) {
1995
2032
  this.checkRequiredCredentials();
1996
2033
  await this.loadMarkets();
2034
+ await this.initializeClient();
1997
2035
  params = this.omit(params, ['clientOrderId', 'client_id']);
1998
2036
  const nonce = this.milliseconds();
1999
2037
  const request = {
@@ -2187,6 +2225,7 @@ export default class hyperliquid extends Exchange {
2187
2225
  */
2188
2226
  async editOrders(orders, params = {}) {
2189
2227
  await this.loadMarkets();
2228
+ await this.initializeClient();
2190
2229
  const request = this.editOrdersRequest(orders, params);
2191
2230
  const response = await this.privatePostExchange(request);
2192
2231
  //
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/kraken.js';
2
- import type { IndexType, Int, OrderSide, OrderType, OHLCV, Trade, Order, Balances, Str, Dict, Transaction, Ticker, OrderBook, Tickers, Strings, Currency, Market, TransferEntry, Num, TradingFeeInterface, Currencies, int, LedgerEntry, DepositAddress, Position } from './base/types.js';
2
+ import type { IndexType, Int, OrderSide, OrderType, OHLCV, Trade, Order, Balances, Str, Dict, Transaction, Ticker, OrderBook, Tickers, Strings, Currency, Market, TransferEntry, Num, TradingFeeInterface, Currencies, int, LedgerEntry, DepositAddress, Position, OrderRequest } from './base/types.js';
3
3
  /**
4
4
  * @class kraken
5
5
  * @augments Exchange
@@ -196,6 +196,16 @@ export default class kraken extends Exchange {
196
196
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
197
197
  */
198
198
  createOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: Num, params?: {}): Promise<Order>;
199
+ /**
200
+ * @method
201
+ * @name kraken#createOrders
202
+ * @description create a list of trade orders
203
+ * @see https://docs.kraken.com/api/docs/rest-api/add-order-batch/
204
+ * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
205
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
206
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
207
+ */
208
+ createOrders(orders: OrderRequest[], params?: {}): Promise<Order[]>;
199
209
  findMarketByAltnameOrId(id: any): any;
200
210
  getDelistedMarketById(id: any): any;
201
211
  parseOrderStatus(status: Str): string;
package/js/src/kraken.js CHANGED
@@ -47,6 +47,7 @@ export default class kraken extends Exchange {
47
47
  'createMarketOrderWithCost': false,
48
48
  'createMarketSellOrderWithCost': false,
49
49
  'createOrder': true,
50
+ 'createOrders': true,
50
51
  'createStopLimitOrder': true,
51
52
  'createStopMarketOrder': true,
52
53
  'createStopOrder': true,
@@ -474,7 +475,11 @@ export default class kraken extends Exchange {
474
475
  'selfTradePrevention': true,
475
476
  'iceberg': true, // todo implement
476
477
  },
477
- 'createOrders': undefined,
478
+ 'createOrders': {
479
+ 'min': 2,
480
+ 'max': 15,
481
+ 'sameSymbolOnly': true,
482
+ },
478
483
  'fetchMyTrades': {
479
484
  'marginMode': false,
480
485
  'limit': undefined,
@@ -1679,6 +1684,79 @@ export default class kraken extends Exchange {
1679
1684
  // this usingCost flag is used to help the parsing but omited from the order
1680
1685
  return this.parseOrder(result);
1681
1686
  }
1687
+ /**
1688
+ * @method
1689
+ * @name kraken#createOrders
1690
+ * @description create a list of trade orders
1691
+ * @see https://docs.kraken.com/api/docs/rest-api/add-order-batch/
1692
+ * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1693
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1694
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1695
+ */
1696
+ async createOrders(orders, params = {}) {
1697
+ await this.loadMarkets();
1698
+ const ordersRequests = [];
1699
+ let orderSymbols = [];
1700
+ let symbol = undefined;
1701
+ let market = undefined;
1702
+ for (let i = 0; i < orders.length; i++) {
1703
+ const rawOrder = orders[i];
1704
+ const marketId = this.safeString(rawOrder, 'symbol');
1705
+ if (symbol === undefined) {
1706
+ symbol = marketId;
1707
+ }
1708
+ else {
1709
+ if (symbol !== marketId) {
1710
+ throw new BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
1711
+ }
1712
+ }
1713
+ market = this.market(marketId);
1714
+ orderSymbols.push(marketId);
1715
+ const type = this.safeString(rawOrder, 'type');
1716
+ const side = this.safeString(rawOrder, 'side');
1717
+ const amount = this.safeValue(rawOrder, 'amount');
1718
+ const price = this.safeValue(rawOrder, 'price');
1719
+ const orderParams = this.safeDict(rawOrder, 'params', {});
1720
+ const req = {
1721
+ 'type': side,
1722
+ 'ordertype': type,
1723
+ 'volume': this.amountToPrecision(market['symbol'], amount),
1724
+ };
1725
+ const orderRequest = this.orderRequest('createOrders', marketId, type, req, amount, price, orderParams);
1726
+ ordersRequests.push(orderRequest[0]);
1727
+ }
1728
+ orderSymbols = this.marketSymbols(orderSymbols, undefined, false, true, true);
1729
+ let response = undefined;
1730
+ let request = {
1731
+ 'orders': ordersRequests,
1732
+ 'pair': market['id'],
1733
+ };
1734
+ request = this.extend(request, params);
1735
+ response = await this.privatePostAddOrderBatch(request);
1736
+ //
1737
+ // {
1738
+ // "error":[
1739
+ // ],
1740
+ // "result":{
1741
+ // "orders":[
1742
+ // {
1743
+ // "txid":"OEPPJX-34RMM-OROGZE",
1744
+ // "descr":{
1745
+ // "order":"sell 6.000000 ADAUSDC @ limit 0.400000"
1746
+ // }
1747
+ // },
1748
+ // {
1749
+ // "txid":"OLQY7O-OYBXW-W23PGL",
1750
+ // "descr":{
1751
+ // "order":"sell 6.000000 ADAUSDC @ limit 0.400000"
1752
+ // }
1753
+ // }
1754
+ // ]
1755
+ // }
1756
+ //
1757
+ const result = this.safeDict(response, 'result', {});
1758
+ return this.parseOrders(this.safeList(result, 'orders'));
1759
+ }
1682
1760
  findMarketByAltnameOrId(id) {
1683
1761
  const marketsByAltname = this.safeValue(this.options, 'marketsByAltname', {});
1684
1762
  if (id in marketsByAltname) {
@@ -3471,10 +3549,11 @@ export default class kraken extends Exchange {
3471
3549
  isTriggerPercent = (price.endsWith('%')) ? true : false;
3472
3550
  }
3473
3551
  const isCancelOrderBatch = (path === 'CancelOrderBatch');
3552
+ const isBatchOrder = (path === 'AddOrderBatch');
3474
3553
  this.checkRequiredCredentials();
3475
3554
  const nonce = this.nonce().toString();
3476
3555
  // urlencodeNested is used to address https://github.com/ccxt/ccxt/issues/12872
3477
- if (isCancelOrderBatch || isTriggerPercent) {
3556
+ if (isCancelOrderBatch || isTriggerPercent || isBatchOrder) {
3478
3557
  body = this.json(this.extend({ 'nonce': nonce }, params));
3479
3558
  }
3480
3559
  else {
@@ -3490,7 +3569,7 @@ export default class kraken extends Exchange {
3490
3569
  'API-Key': this.apiKey,
3491
3570
  'API-Sign': signature,
3492
3571
  };
3493
- if (isCancelOrderBatch || isTriggerPercent) {
3572
+ if (isCancelOrderBatch || isTriggerPercent || isBatchOrder) {
3494
3573
  headers['Content-Type'] = 'application/json';
3495
3574
  }
3496
3575
  else {
@@ -3515,10 +3594,10 @@ export default class kraken extends Exchange {
3515
3594
  }
3516
3595
  if (body[0] === '{') {
3517
3596
  if (typeof response !== 'string') {
3597
+ const message = this.id + ' ' + body;
3518
3598
  if ('error' in response) {
3519
3599
  const numErrors = response['error'].length;
3520
3600
  if (numErrors) {
3521
- const message = this.id + ' ' + body;
3522
3601
  for (let i = 0; i < response['error'].length; i++) {
3523
3602
  const error = response['error'][i];
3524
3603
  this.throwExactlyMatchedException(this.exceptions['exact'], error, message);
@@ -3527,6 +3606,22 @@ export default class kraken extends Exchange {
3527
3606
  throw new ExchangeError(message);
3528
3607
  }
3529
3608
  }
3609
+ // handleCreateOrdersErrors:
3610
+ if ('result' in response) {
3611
+ const result = this.safeDict(response, 'result', {});
3612
+ if ('orders' in result) {
3613
+ const orders = this.safeList(result, 'orders', []);
3614
+ for (let i = 0; i < orders.length; i++) {
3615
+ const order = orders[i];
3616
+ const error = this.safeString(order, 'error');
3617
+ if (error !== undefined) {
3618
+ this.throwExactlyMatchedException(this.exceptions['exact'], error, message);
3619
+ this.throwBroadlyMatchedException(this.exceptions['broad'], error, message);
3620
+ throw new ExchangeError(message);
3621
+ }
3622
+ }
3623
+ }
3624
+ }
3530
3625
  }
3531
3626
  }
3532
3627
  return undefined;
package/js/src/kucoin.js CHANGED
@@ -494,6 +494,7 @@ export default class kucoin extends Exchange {
494
494
  'precisionMode': TICK_SIZE,
495
495
  'exceptions': {
496
496
  'exact': {
497
+ 'Order not exist or not allow to be cancelled': OrderNotFound,
497
498
  'The order does not exist.': OrderNotFound,
498
499
  'order not exist': OrderNotFound,
499
500
  'order not exist.': OrderNotFound,
package/js/src/mexc.js CHANGED
@@ -932,6 +932,7 @@ export default class mexc extends Exchange {
932
932
  '30029': InvalidOrder,
933
933
  '30032': InvalidOrder,
934
934
  '30041': InvalidOrder,
935
+ '30087': InvalidOrder,
935
936
  '60005': ExchangeError,
936
937
  '700001': AuthenticationError,
937
938
  '700002': AuthenticationError,
@@ -9,7 +9,7 @@ import gateRest from '../gate.js';
9
9
  import { AuthenticationError, BadRequest, ArgumentsRequired, ChecksumError, ExchangeError, NotSupported } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
11
11
  import { sha512 } from '../static_dependencies/noble-hashes/sha512.js';
12
- import Precise from '../base/Precise.js';
12
+ import { Precise } from '../base/Precise.js';
13
13
  // ---------------------------------------------------------------------------
14
14
  export default class gate extends gateRest {
15
15
  describe() {
@@ -9,7 +9,7 @@ import geminiRest from '../gemini.js';
9
9
  import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
10
10
  import { ExchangeError, NotSupported } from '../base/errors.js';
11
11
  import { sha384 } from '../static_dependencies/noble-hashes/sha512.js';
12
- import Precise from '../base/Precise.js';
12
+ import { Precise } from '../base/Precise.js';
13
13
  // ---------------------------------------------------------------------------
14
14
  export default class gemini extends geminiRest {
15
15
  describe() {
@@ -8,7 +8,7 @@
8
8
  import onetradingRest from '../onetrading.js';
9
9
  import { NotSupported, ExchangeError } from '../base/errors.js';
10
10
  import { ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
- import Precise from '../base/Precise.js';
11
+ import { Precise } from '../base/Precise.js';
12
12
  // ---------------------------------------------------------------------------
13
13
  export default class onetrading extends onetradingRest {
14
14
  describe() {
@@ -403,12 +403,36 @@ export default class upbit extends upbitRest {
403
403
  'hostname': this.hostname,
404
404
  });
405
405
  url += '/private';
406
+ const client = this.client(url);
407
+ // Track private channel subscriptions to support multiple concurrent watches
408
+ const subscriptionsKey = 'upbitPrivateSubscriptions';
409
+ if (!(subscriptionsKey in client.subscriptions)) {
410
+ client.subscriptions[subscriptionsKey] = {};
411
+ }
412
+ let channelKey = channel;
413
+ if (symbol !== undefined) {
414
+ channelKey = channel + ':' + symbol;
415
+ }
416
+ const subscriptions = client.subscriptions[subscriptionsKey];
417
+ const isNewChannel = !(channelKey in subscriptions);
418
+ if (isNewChannel) {
419
+ subscriptions[channelKey] = request;
420
+ }
421
+ // Build subscription message with all requested private channels
422
+ // Format: [{'ticket': uuid}, {'type': 'myOrder'}, {'type': 'myAsset'}, ...]
423
+ const requests = [];
424
+ const channelKeys = Object.keys(subscriptions);
425
+ for (let i = 0; i < channelKeys.length; i++) {
426
+ requests.push(subscriptions[channelKeys[i]]);
427
+ }
406
428
  const message = [
407
429
  {
408
430
  'ticket': this.uuid(),
409
431
  },
410
- request,
411
432
  ];
433
+ for (let i = 0; i < requests.length; i++) {
434
+ message.push(requests[i]);
435
+ }
412
436
  return await this.watch(url, messageHash, message, messageHash);
413
437
  }
414
438
  /**
package/js/src/woo.d.ts CHANGED
@@ -472,7 +472,7 @@ export default class woo extends Exchange {
472
472
  * @method
473
473
  * @name woo#withdraw
474
474
  * @description make a withdrawal
475
- * @see https://docs.woox.io/#token-withdraw
475
+ * @see https://docs.woox.io/#token-withdraw-v3
476
476
  * @param {string} code unified currency code
477
477
  * @param {float} amount the amount to withdraw
478
478
  * @param {string} address the address to withdraw to