ccxt 4.5.56 → 4.5.57
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/README.md +10 -9
- package/dist/ccxt.browser.min.js +10 -10
- package/dist/cjs/ccxt.js +6 -11
- package/dist/cjs/src/apex.js +1 -1
- package/dist/cjs/src/arkham.js +3 -3
- package/dist/cjs/src/ascendex.js +2 -2
- package/dist/cjs/src/aster.js +7 -4
- package/dist/cjs/src/backpack.js +4 -4
- package/dist/cjs/src/base/Exchange.js +69 -32
- package/dist/cjs/src/base/functions/io.js +25 -0
- package/dist/cjs/src/base/functions.js +1 -0
- package/dist/cjs/src/bigone.js +3 -3
- package/dist/cjs/src/binance.js +192 -194
- package/dist/cjs/src/bingx.js +3 -3
- package/dist/cjs/src/bitfinex.js +71 -58
- package/dist/cjs/src/bitget.js +2 -2
- package/dist/cjs/src/bitmart.js +13 -6
- package/dist/cjs/src/bitmex.js +1 -1
- package/dist/cjs/src/bitopro.js +1 -1
- package/dist/cjs/src/bitrue.js +2 -2
- package/dist/cjs/src/bitso.js +1 -1
- package/dist/cjs/src/bitstamp.js +2 -1
- package/dist/cjs/src/bitteam.js +1 -1
- package/dist/cjs/src/bittrade.js +0 -1
- package/dist/cjs/src/bitvavo.js +457 -34
- package/dist/cjs/src/blofin.js +26 -3
- package/dist/cjs/src/bullish.js +6 -5
- package/dist/cjs/src/bydfi.js +1 -1
- package/dist/cjs/src/cex.js +3 -3
- package/dist/cjs/src/coinbase.js +75 -65
- package/dist/cjs/src/coinbaseexchange.js +2 -2
- package/dist/cjs/src/coinbaseinternational.js +2 -1
- package/dist/cjs/src/coinex.js +74 -74
- package/dist/cjs/src/coinmetro.js +1 -1
- package/dist/cjs/src/coinsph.js +1 -1
- package/dist/cjs/src/cryptocom.js +46 -48
- package/dist/cjs/src/cryptomus.js +43 -39
- package/dist/cjs/src/deepcoin.js +3 -2
- package/dist/cjs/src/delta.js +51 -52
- package/dist/cjs/src/deribit.js +31 -33
- package/dist/cjs/src/derive.js +26 -28
- package/dist/cjs/src/digifinex.js +43 -44
- package/dist/cjs/src/exmo.js +92 -83
- package/dist/cjs/src/extended.js +3497 -0
- package/dist/cjs/src/foxbit.js +71 -75
- package/dist/cjs/src/gate.js +53 -53
- package/dist/cjs/src/gemini.js +41 -43
- package/dist/cjs/src/grvt.js +4 -4
- package/dist/cjs/src/hashkey.js +52 -54
- package/dist/cjs/src/hitbtc.js +3 -13
- package/dist/cjs/src/hollaex.js +51 -54
- package/dist/cjs/src/htx.js +75 -67
- package/dist/cjs/src/hyperliquid.js +41 -42
- package/dist/cjs/src/indodax.js +2 -2
- package/dist/cjs/src/kraken.js +57 -58
- package/dist/cjs/src/kucoin.js +3 -2
- package/dist/cjs/src/latoken.js +30 -32
- package/dist/cjs/src/lbank.js +56 -56
- package/dist/cjs/src/lighter.js +35 -37
- package/dist/cjs/src/luno.js +35 -43
- package/dist/cjs/src/mexc.js +48 -49
- package/dist/cjs/src/modetrade.js +50 -52
- package/dist/cjs/src/ndax.js +35 -37
- package/dist/cjs/src/okx.js +17 -2
- package/dist/cjs/src/onetrading.js +21 -23
- package/dist/cjs/src/phemex.js +43 -45
- package/dist/cjs/src/poloniex.js +17 -12
- package/dist/cjs/src/pro/alpaca.js +1 -1
- package/dist/cjs/src/pro/apex.js +1 -1
- package/dist/cjs/src/pro/arkham.js +1 -1
- package/dist/cjs/src/pro/backpack.js +1 -1
- package/dist/cjs/src/pro/binance.js +3 -3
- package/dist/cjs/src/pro/bitget.js +1 -1
- package/dist/cjs/src/pro/bithumb.js +1 -1
- package/dist/cjs/src/pro/bitstamp.js +1 -1
- package/dist/cjs/src/pro/blockchaincom.js +1 -1
- package/dist/cjs/src/pro/bybit.js +1 -1
- package/dist/cjs/src/pro/cex.js +1 -1
- package/dist/cjs/src/pro/coinex.js +1 -1
- package/dist/cjs/src/pro/coinone.js +1 -1
- package/dist/cjs/src/pro/cryptocom.js +3 -1
- package/dist/cjs/src/pro/dydx.js +1 -1
- package/dist/cjs/src/pro/exmo.js +1 -1
- package/dist/cjs/src/pro/extended.js +865 -0
- package/dist/cjs/src/pro/gate.js +1 -1
- package/dist/cjs/src/pro/independentreserve.js +1 -1
- package/dist/cjs/src/pro/kucoin.js +1 -1
- package/dist/cjs/src/pro/luno.js +3 -3
- package/dist/cjs/src/pro/onetrading.js +1 -1
- package/dist/cjs/src/pro/toobit.js +1 -1
- package/dist/cjs/src/pro/weex.js +1 -1
- package/dist/cjs/src/static_dependencies/starknet/utils/hash/classHash.js +7 -7
- package/dist/cjs/src/tokocrypto.js +1 -1
- package/dist/cjs/src/toobit.js +2 -2
- package/dist/cjs/src/upbit.js +3 -3
- package/dist/cjs/src/weex.js +57 -62
- package/dist/cjs/src/whitebit.js +61 -63
- package/dist/cjs/src/woo.js +65 -54
- package/dist/cjs/src/woofipro.js +53 -47
- package/dist/cjs/src/xt.js +1 -1
- package/dist/cjs/src/zebpay.js +70 -72
- package/js/ccxt.d.ts +8 -14
- package/js/ccxt.js +6 -10
- package/js/src/abstract/bitvavo.d.ts +15 -7
- package/js/src/abstract/extended.d.ts +58 -0
- package/js/src/apex.js +1 -1
- package/js/src/arkham.js +3 -3
- package/js/src/ascendex.js +2 -2
- package/js/src/aster.js +7 -4
- package/js/src/backpack.js +4 -4
- package/js/src/base/Exchange.d.ts +10 -6
- package/js/src/base/Exchange.js +69 -32
- package/js/src/base/functions/io.d.ts +7 -0
- package/js/src/base/functions/io.js +24 -0
- package/js/src/bigone.js +3 -3
- package/js/src/binance.d.ts +2 -0
- package/js/src/binance.js +196 -198
- package/js/src/bingx.js +3 -3
- package/js/src/bitfinex.d.ts +2 -0
- package/js/src/bitfinex.js +71 -58
- package/js/src/bitget.js +2 -2
- package/js/src/bitmart.js +13 -6
- package/js/src/bitmex.js +1 -1
- package/js/src/bitopro.js +1 -1
- package/js/src/bitrue.js +2 -2
- package/js/src/bitso.js +1 -1
- package/js/src/bitstamp.js +2 -1
- package/js/src/bitteam.js +1 -1
- package/js/src/bittrade.js +0 -1
- package/js/src/bitvavo.d.ts +114 -21
- package/js/src/bitvavo.js +457 -34
- package/js/src/blofin.d.ts +1 -0
- package/js/src/blofin.js +26 -3
- package/js/src/bullish.js +6 -5
- package/js/src/bydfi.js +1 -1
- package/js/src/cex.js +3 -3
- package/js/src/coinbase.d.ts +63 -56
- package/js/src/coinbase.js +75 -65
- package/js/src/coinbaseexchange.js +2 -2
- package/js/src/coinbaseinternational.js +2 -1
- package/js/src/coinex.d.ts +1 -0
- package/js/src/coinex.js +74 -74
- package/js/src/coinmetro.d.ts +1 -1
- package/js/src/coinmetro.js +1 -1
- package/js/src/coinsph.js +1 -1
- package/js/src/cryptocom.d.ts +1 -0
- package/js/src/cryptocom.js +46 -48
- package/js/src/cryptomus.d.ts +2 -1
- package/js/src/cryptomus.js +43 -39
- package/js/src/deepcoin.js +3 -2
- package/js/src/delta.d.ts +1 -0
- package/js/src/delta.js +51 -52
- package/js/src/deribit.d.ts +1 -0
- package/js/src/deribit.js +31 -33
- package/js/src/derive.d.ts +1 -0
- package/js/src/derive.js +26 -28
- package/js/src/digifinex.d.ts +1 -0
- package/js/src/digifinex.js +43 -44
- package/js/src/exmo.d.ts +1 -0
- package/js/src/exmo.js +92 -83
- package/js/src/extended.d.ts +554 -0
- package/js/src/extended.js +3490 -0
- package/js/src/foxbit.d.ts +1 -0
- package/js/src/foxbit.js +71 -75
- package/js/src/gate.d.ts +1 -0
- package/js/src/gate.js +53 -53
- package/js/src/gemini.d.ts +2 -1
- package/js/src/gemini.js +41 -43
- package/js/src/grvt.js +4 -4
- package/js/src/hashkey.d.ts +1 -0
- package/js/src/hashkey.js +52 -54
- package/js/src/hitbtc.d.ts +0 -1
- package/js/src/hitbtc.js +3 -13
- package/js/src/hollaex.d.ts +1 -0
- package/js/src/hollaex.js +51 -54
- package/js/src/htx.d.ts +1 -0
- package/js/src/htx.js +75 -67
- package/js/src/hyperliquid.d.ts +1 -0
- package/js/src/hyperliquid.js +41 -42
- package/js/src/indodax.js +2 -2
- package/js/src/kraken.d.ts +2 -1
- package/js/src/kraken.js +57 -58
- package/js/src/kucoin.js +3 -2
- package/js/src/latoken.d.ts +1 -0
- package/js/src/latoken.js +30 -32
- package/js/src/lbank.d.ts +1 -0
- package/js/src/lbank.js +56 -56
- package/js/src/lighter.d.ts +1 -0
- package/js/src/lighter.js +35 -37
- package/js/src/luno.d.ts +1 -0
- package/js/src/luno.js +35 -43
- package/js/src/mexc.d.ts +2 -1
- package/js/src/mexc.js +48 -49
- package/js/src/modetrade.d.ts +1 -0
- package/js/src/modetrade.js +50 -52
- package/js/src/ndax.d.ts +1 -0
- package/js/src/ndax.js +35 -37
- package/js/src/okx.js +17 -2
- package/js/src/onetrading.d.ts +2 -1
- package/js/src/onetrading.js +21 -23
- package/js/src/phemex.d.ts +1 -0
- package/js/src/phemex.js +43 -45
- package/js/src/poloniex.js +17 -12
- package/js/src/pro/alpaca.js +1 -1
- package/js/src/pro/apex.js +1 -1
- package/js/src/pro/arkham.js +1 -1
- package/js/src/pro/backpack.js +1 -1
- package/js/src/pro/binance.js +3 -3
- package/js/src/pro/bitget.js +1 -1
- package/js/src/pro/bithumb.js +1 -1
- package/js/src/pro/bitstamp.js +1 -1
- package/js/src/pro/blockchaincom.js +1 -1
- package/js/src/pro/bybit.js +1 -1
- package/js/src/pro/cex.js +1 -1
- package/js/src/pro/coinex.js +1 -1
- package/js/src/pro/coinone.js +1 -1
- package/js/src/pro/cryptocom.js +3 -1
- package/js/src/pro/dydx.js +1 -1
- package/js/src/pro/exmo.js +1 -1
- package/js/src/pro/extended.d.ts +126 -0
- package/js/src/pro/extended.js +858 -0
- package/js/src/pro/gate.js +1 -1
- package/js/src/pro/independentreserve.js +1 -1
- package/js/src/pro/kucoin.js +1 -1
- package/js/src/pro/luno.d.ts +1 -1
- package/js/src/pro/luno.js +3 -3
- package/js/src/pro/onetrading.js +1 -1
- package/js/src/pro/toobit.js +1 -1
- package/js/src/pro/weex.js +1 -1
- package/js/src/tokocrypto.js +1 -1
- package/js/src/toobit.js +2 -2
- package/js/src/upbit.js +3 -3
- package/js/src/weex.d.ts +1 -0
- package/js/src/weex.js +57 -62
- package/js/src/whitebit.d.ts +1 -0
- package/js/src/whitebit.js +61 -63
- package/js/src/woo.d.ts +1 -0
- package/js/src/woo.js +65 -54
- package/js/src/woofipro.d.ts +1 -0
- package/js/src/woofipro.js +53 -47
- package/js/src/xt.js +1 -1
- package/js/src/zebpay.d.ts +2 -1
- package/js/src/zebpay.js +70 -72
- package/package.json +7 -7
- package/dist/cjs/src/gateio.js +0 -18
- package/dist/cjs/src/oxfun.js +0 -2933
- package/dist/cjs/src/pro/gateio.js +0 -18
- package/dist/cjs/src/pro/oxfun.js +0 -1113
- package/js/src/abstract/gateio.d.ts +0 -346
- package/js/src/abstract/gateio.js +0 -5
- package/js/src/abstract/oxfun.d.ts +0 -37
- package/js/src/gateio.d.ts +0 -4
- package/js/src/gateio.js +0 -11
- package/js/src/oxfun.d.ts +0 -442
- package/js/src/oxfun.js +0 -2926
- package/js/src/pro/gateio.d.ts +0 -4
- package/js/src/pro/gateio.js +0 -11
- package/js/src/pro/oxfun.d.ts +0 -234
- package/js/src/pro/oxfun.js +0 -1106
- /package/dist/cjs/src/abstract/{oxfun.js → extended.js} +0 -0
- /package/js/src/abstract/{oxfun.js → extended.js} +0 -0
|
@@ -0,0 +1,865 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var extended$1 = require('../extended.js');
|
|
6
|
+
var errors = require('../base/errors.js');
|
|
7
|
+
var Cache = require('../base/ws/Cache.js');
|
|
8
|
+
|
|
9
|
+
// ----------------------------------------------------------------------------
|
|
10
|
+
// ----------------------------------------------------------------------------
|
|
11
|
+
class extended extends extended$1["default"] {
|
|
12
|
+
describe() {
|
|
13
|
+
return this.deepExtend(super.describe(), {
|
|
14
|
+
'has': {
|
|
15
|
+
'ws': true,
|
|
16
|
+
'watchFundingRate': true,
|
|
17
|
+
'watchOHLCV': true,
|
|
18
|
+
'watchOrderBook': true,
|
|
19
|
+
'watchIndexPrice': true,
|
|
20
|
+
'watchMarkPrice': true,
|
|
21
|
+
'watchTrades': true,
|
|
22
|
+
'watchBalance': true,
|
|
23
|
+
'watchMyTrades': true,
|
|
24
|
+
'watchOrders': true,
|
|
25
|
+
'watchPositions': true,
|
|
26
|
+
},
|
|
27
|
+
'urls': {
|
|
28
|
+
'api': {
|
|
29
|
+
'ws': 'wss://api.starknet.extended.exchange/stream.extended.exchange/v1',
|
|
30
|
+
},
|
|
31
|
+
'test': {
|
|
32
|
+
'ws': 'wss://api.starknet.sepolia.extended.exchange/stream.extended.exchange/v1',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
'options': {
|
|
36
|
+
'ws': {
|
|
37
|
+
'options': {
|
|
38
|
+
'headers': {
|
|
39
|
+
'User-Agent': this.userAgents['chrome'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @method
|
|
48
|
+
* @name extended#watchOrderBook
|
|
49
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
50
|
+
* @see https://api.docs.extended.exchange/#order-book-stream
|
|
51
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
52
|
+
* @param {int} [limit] the maximum amount of order book entries to return
|
|
53
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
54
|
+
* @param {string} [params.depth] set to '1' to receive best bid and ask snapshots only
|
|
55
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
|
|
56
|
+
*/
|
|
57
|
+
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
58
|
+
await this.loadMarkets();
|
|
59
|
+
const market = this.market(symbol);
|
|
60
|
+
symbol = market['symbol'];
|
|
61
|
+
const messageHash = 'orderbook:' + symbol;
|
|
62
|
+
const query = this.urlencode(params);
|
|
63
|
+
let url = this.urls['api']['ws'] + '/orderbooks/' + market['id'];
|
|
64
|
+
if (query.length > 0) {
|
|
65
|
+
url += '?' + query;
|
|
66
|
+
}
|
|
67
|
+
const orderbook = await this.watch(url, messageHash, undefined, messageHash, {
|
|
68
|
+
'symbol': symbol,
|
|
69
|
+
'limit': limit,
|
|
70
|
+
});
|
|
71
|
+
return orderbook.limit();
|
|
72
|
+
}
|
|
73
|
+
handleOrderBook(client, message) {
|
|
74
|
+
//
|
|
75
|
+
// {
|
|
76
|
+
// "ts": 1701563440000,
|
|
77
|
+
// "type": "SNAPSHOT",
|
|
78
|
+
// "data": {
|
|
79
|
+
// "m": "BTC-USD",
|
|
80
|
+
// "b": [
|
|
81
|
+
// { "p": "25670", "q": "0.1" }
|
|
82
|
+
// ],
|
|
83
|
+
// "a": [
|
|
84
|
+
// { "p": "25770", "q": "0.1" }
|
|
85
|
+
// ]
|
|
86
|
+
// },
|
|
87
|
+
// "seq": 1
|
|
88
|
+
// }
|
|
89
|
+
//
|
|
90
|
+
const data = this.safeDict(message, 'data', {});
|
|
91
|
+
const marketId = this.safeString(data, 'm');
|
|
92
|
+
const market = this.safeMarket(marketId);
|
|
93
|
+
const symbol = market['symbol'];
|
|
94
|
+
const messageHash = 'orderbook:' + symbol;
|
|
95
|
+
const timestamp = this.safeInteger(message, 'ts');
|
|
96
|
+
const nonce = this.safeInteger(message, 'seq');
|
|
97
|
+
const type = this.safeString(message, 'type', this.safeString(data, 't'));
|
|
98
|
+
if (!(symbol in this.orderbooks)) {
|
|
99
|
+
const defaultLimit = this.safeInteger(this.options, 'watchOrderBookLimit', 1000);
|
|
100
|
+
const subscription = this.safeDict(client.subscriptions, messageHash, {});
|
|
101
|
+
const limit = this.safeInteger(subscription, 'limit', defaultLimit);
|
|
102
|
+
this.orderbooks[symbol] = this.orderBook({}, limit);
|
|
103
|
+
}
|
|
104
|
+
const orderbook = this.orderbooks[symbol];
|
|
105
|
+
if (type === 'SNAPSHOT') {
|
|
106
|
+
const snapshot = this.parseOrderBook(data, symbol, timestamp, 'b', 'a', 'p', 'q');
|
|
107
|
+
snapshot['nonce'] = nonce;
|
|
108
|
+
orderbook.reset(snapshot);
|
|
109
|
+
client.resolve(orderbook, messageHash);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const previousNonce = this.safeInteger(orderbook, 'nonce');
|
|
113
|
+
if ((previousNonce !== undefined) && (nonce !== previousNonce + 1)) {
|
|
114
|
+
delete client.subscriptions[messageHash];
|
|
115
|
+
delete this.orderbooks[symbol];
|
|
116
|
+
const error = new errors.InvalidNonce(this.id + ' watchOrderBook received invalid nonce');
|
|
117
|
+
client.reject(error, messageHash);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
this.handleDeltas(orderbook['bids'], this.safeList(data, 'b', []));
|
|
121
|
+
this.handleDeltas(orderbook['asks'], this.safeList(data, 'a', []));
|
|
122
|
+
orderbook['timestamp'] = timestamp;
|
|
123
|
+
orderbook['datetime'] = this.iso8601(timestamp);
|
|
124
|
+
orderbook['nonce'] = nonce;
|
|
125
|
+
client.resolve(orderbook, messageHash);
|
|
126
|
+
}
|
|
127
|
+
handleDelta(bookside, delta) {
|
|
128
|
+
const price = this.safeFloat(delta, 'p');
|
|
129
|
+
const amount = this.safeFloat2(delta, 'c', 'q');
|
|
130
|
+
bookside.store(price, amount);
|
|
131
|
+
}
|
|
132
|
+
handleDeltas(bookside, deltas) {
|
|
133
|
+
for (let i = 0; i < deltas.length; i++) {
|
|
134
|
+
this.handleDelta(bookside, deltas[i]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async watchPrivate(messageHash, subscription = undefined) {
|
|
138
|
+
this.checkRequiredCredentials();
|
|
139
|
+
const url = this.urls['api']['ws'] + '/account';
|
|
140
|
+
if ((this.clients === undefined) || !(url in this.clients)) {
|
|
141
|
+
const defaultOptions = {
|
|
142
|
+
'ws': {
|
|
143
|
+
'options': {
|
|
144
|
+
'headers': {},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
this.extendExchangeOptions(defaultOptions);
|
|
149
|
+
const originalOptions = this.options['ws']['options'];
|
|
150
|
+
const originalHeaders = this.safeDict(originalOptions, 'headers', {});
|
|
151
|
+
this.options['ws']['options'] = this.extend(this.extend({}, originalOptions), {
|
|
152
|
+
'headers': this.extend(this.extend({
|
|
153
|
+
'User-Agent': this.userAgents['chrome'],
|
|
154
|
+
}, originalHeaders), {
|
|
155
|
+
'X-Api-Key': this.apiKey,
|
|
156
|
+
}),
|
|
157
|
+
});
|
|
158
|
+
this.client(url);
|
|
159
|
+
this.options['ws']['options'] = originalOptions;
|
|
160
|
+
}
|
|
161
|
+
return await this.watch(url, messageHash, undefined, messageHash, subscription);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* @method
|
|
165
|
+
* @name extended#watchOrders
|
|
166
|
+
* @description watches information on multiple orders made by the user
|
|
167
|
+
* @see https://api.docs.extended.exchange/#account-updates-stream
|
|
168
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
169
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
170
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
171
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
172
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
|
|
173
|
+
*/
|
|
174
|
+
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
175
|
+
await this.loadMarkets();
|
|
176
|
+
let messageHash = 'orders';
|
|
177
|
+
if (symbol !== undefined) {
|
|
178
|
+
const market = this.market(symbol);
|
|
179
|
+
symbol = market['symbol'];
|
|
180
|
+
messageHash += ':' + symbol;
|
|
181
|
+
}
|
|
182
|
+
const orders = await this.watchPrivate(messageHash, {
|
|
183
|
+
'symbol': symbol,
|
|
184
|
+
'limit': limit,
|
|
185
|
+
});
|
|
186
|
+
if (this.newUpdates) {
|
|
187
|
+
limit = orders.getLimit(symbol, limit);
|
|
188
|
+
}
|
|
189
|
+
return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* @method
|
|
193
|
+
* @name extended#watchBalance
|
|
194
|
+
* @description watches balance updates
|
|
195
|
+
* @see https://api.docs.extended.exchange/#account-updates-stream
|
|
196
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
197
|
+
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
|
|
198
|
+
*/
|
|
199
|
+
async watchBalance(params = {}) {
|
|
200
|
+
await this.loadMarkets();
|
|
201
|
+
return await this.watchPrivate('balance', params);
|
|
202
|
+
}
|
|
203
|
+
handleBalance(client, message) {
|
|
204
|
+
//
|
|
205
|
+
// {
|
|
206
|
+
// "type": "BALANCE",
|
|
207
|
+
// "data": {
|
|
208
|
+
// "balance": {
|
|
209
|
+
// "collateralName": "BTC",
|
|
210
|
+
// "balance": "100.000000",
|
|
211
|
+
// "equity": "20.000000",
|
|
212
|
+
// "availableForTrade": "3.000000",
|
|
213
|
+
// "availableForWithdrawal": "4.000000",
|
|
214
|
+
// "updatedTime": 1699976104901
|
|
215
|
+
// },
|
|
216
|
+
// "spotBalances": [
|
|
217
|
+
// {
|
|
218
|
+
// "asset": "BTC",
|
|
219
|
+
// "balance": "0.5",
|
|
220
|
+
// "availableToWithdraw": "0.5",
|
|
221
|
+
// "updatedAt": 1701563440
|
|
222
|
+
// }
|
|
223
|
+
// ]
|
|
224
|
+
// },
|
|
225
|
+
// "ts": 1715885952304,
|
|
226
|
+
// "seq": 1
|
|
227
|
+
// }
|
|
228
|
+
//
|
|
229
|
+
const data = this.safeDict(message, 'data', {});
|
|
230
|
+
const result = {
|
|
231
|
+
'info': data,
|
|
232
|
+
};
|
|
233
|
+
const balance = this.safeDict(data, 'balance');
|
|
234
|
+
if (balance !== undefined) {
|
|
235
|
+
const currencyId = this.safeString(balance, 'collateralName');
|
|
236
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
237
|
+
if (code !== undefined) {
|
|
238
|
+
const account = this.account();
|
|
239
|
+
account['free'] = this.safeString(balance, 'availableForWithdrawal');
|
|
240
|
+
account['total'] = this.safeString(balance, 'balance');
|
|
241
|
+
result[code] = account;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const spotBalances = this.safeList(data, 'spotBalances', []);
|
|
245
|
+
for (let i = 0; i < spotBalances.length; i++) {
|
|
246
|
+
const spotBalance = this.safeDict(spotBalances, i, {});
|
|
247
|
+
const currencyId = this.safeString(spotBalance, 'asset');
|
|
248
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
249
|
+
if (code !== undefined) {
|
|
250
|
+
const account = this.account();
|
|
251
|
+
account['free'] = this.safeString(spotBalance, 'availableToWithdraw');
|
|
252
|
+
account['total'] = this.safeString(spotBalance, 'balance');
|
|
253
|
+
result[code] = account;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const timestamp = this.safeInteger(message, 'ts');
|
|
257
|
+
result['timestamp'] = timestamp;
|
|
258
|
+
result['datetime'] = this.iso8601(timestamp);
|
|
259
|
+
this.balance = this.safeBalance(this.deepExtend(this.balance, result));
|
|
260
|
+
client.resolve(this.balance, 'balance');
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* @method
|
|
264
|
+
* @name extended#watchMyTrades
|
|
265
|
+
* @description watches information on multiple trades made by the user
|
|
266
|
+
* @see https://api.docs.extended.exchange/#account-updates-stream
|
|
267
|
+
* @param {string} [symbol] unified market symbol of the trades
|
|
268
|
+
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
269
|
+
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
270
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
271
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
272
|
+
*/
|
|
273
|
+
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
274
|
+
await this.loadMarkets();
|
|
275
|
+
let messageHash = 'myTrades';
|
|
276
|
+
if (symbol !== undefined) {
|
|
277
|
+
const market = this.market(symbol);
|
|
278
|
+
symbol = market['symbol'];
|
|
279
|
+
messageHash += ':' + symbol;
|
|
280
|
+
}
|
|
281
|
+
const trades = await this.watchPrivate(messageHash, {
|
|
282
|
+
'symbol': symbol,
|
|
283
|
+
'limit': limit,
|
|
284
|
+
});
|
|
285
|
+
if (this.newUpdates) {
|
|
286
|
+
limit = trades.getLimit(symbol, limit);
|
|
287
|
+
}
|
|
288
|
+
return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
|
|
289
|
+
}
|
|
290
|
+
handleMyTrades(client, message) {
|
|
291
|
+
//
|
|
292
|
+
// {
|
|
293
|
+
// "type": "TRADE",
|
|
294
|
+
// "data": {
|
|
295
|
+
// "trades": [
|
|
296
|
+
// {
|
|
297
|
+
// "id": 1784963886257016832,
|
|
298
|
+
// "accountId": 3017,
|
|
299
|
+
// "market": "BTC-USD",
|
|
300
|
+
// "orderId": 9223372036854775808,
|
|
301
|
+
// "externalOrderId": "ext-1",
|
|
302
|
+
// "side": "BUY",
|
|
303
|
+
// "price": "58853.4000000000000000",
|
|
304
|
+
// "qty": "0.0900000000000000",
|
|
305
|
+
// "value": "5296.8060000000000000",
|
|
306
|
+
// "fee": "0.0000000000000000",
|
|
307
|
+
// "tradeType": "DELEVERAGE",
|
|
308
|
+
// "createdTime": 1701563440000,
|
|
309
|
+
// "isTaker": true
|
|
310
|
+
// }
|
|
311
|
+
// ]
|
|
312
|
+
// },
|
|
313
|
+
// "ts": 1715886400000,
|
|
314
|
+
// "seq": 1
|
|
315
|
+
// }
|
|
316
|
+
//
|
|
317
|
+
if (this.myTrades === undefined) {
|
|
318
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
319
|
+
this.myTrades = new Cache.ArrayCacheBySymbolById(limit);
|
|
320
|
+
}
|
|
321
|
+
const stored = this.myTrades;
|
|
322
|
+
const data = this.safeDict(message, 'data', {});
|
|
323
|
+
const rawTrades = this.safeList(data, 'trades', []);
|
|
324
|
+
const symbols = {};
|
|
325
|
+
const first = this.safeDict(rawTrades, 0);
|
|
326
|
+
if (first === undefined) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
for (let i = 0; i < rawTrades.length; i++) {
|
|
330
|
+
const trade = this.parseTrade(rawTrades[i]);
|
|
331
|
+
const symbol = this.safeString(trade, 'symbol');
|
|
332
|
+
symbols[symbol] = true;
|
|
333
|
+
stored.append(trade);
|
|
334
|
+
}
|
|
335
|
+
const keys = Object.keys(symbols);
|
|
336
|
+
for (let i = 0; i < keys.length; i++) {
|
|
337
|
+
const messageHash = 'myTrades:' + keys[i];
|
|
338
|
+
client.resolve(stored, messageHash);
|
|
339
|
+
}
|
|
340
|
+
client.resolve(stored, 'myTrades');
|
|
341
|
+
const subscriptions = Object.keys(client.subscriptions);
|
|
342
|
+
for (let i = 0; i < subscriptions.length; i++) {
|
|
343
|
+
const messageHash = subscriptions[i];
|
|
344
|
+
if (messageHash.indexOf('myTrades:') === 0) {
|
|
345
|
+
client.resolve(stored, messageHash);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* @method
|
|
351
|
+
* @name extended#watchPositions
|
|
352
|
+
* @description watches information on multiple positions
|
|
353
|
+
* @see https://api.docs.extended.exchange/#account-updates-stream
|
|
354
|
+
* @param {string[]} [symbols] unified market symbols
|
|
355
|
+
* @param {int} [since] the earliest time in ms to fetch positions for
|
|
356
|
+
* @param {int} [limit] the maximum number of position structures to retrieve
|
|
357
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
358
|
+
* @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
359
|
+
*/
|
|
360
|
+
async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
|
|
361
|
+
await this.loadMarkets();
|
|
362
|
+
symbols = this.marketSymbols(symbols);
|
|
363
|
+
let messageHash = 'positions';
|
|
364
|
+
if (symbols !== undefined) {
|
|
365
|
+
messageHash += '::' + symbols.join(',');
|
|
366
|
+
}
|
|
367
|
+
const positions = await this.watchPrivate(messageHash, {
|
|
368
|
+
'symbols': symbols,
|
|
369
|
+
'limit': limit,
|
|
370
|
+
});
|
|
371
|
+
if (this.newUpdates) {
|
|
372
|
+
return positions;
|
|
373
|
+
}
|
|
374
|
+
return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
|
|
375
|
+
}
|
|
376
|
+
handlePositions(client, message) {
|
|
377
|
+
//
|
|
378
|
+
// {
|
|
379
|
+
// "type": "POSITION",
|
|
380
|
+
// "data": {
|
|
381
|
+
// "positions": [
|
|
382
|
+
// {
|
|
383
|
+
// "id": 1,
|
|
384
|
+
// "accountId": 1,
|
|
385
|
+
// "market": "BTC-USD",
|
|
386
|
+
// "side": "LONG",
|
|
387
|
+
// "leverage": "10",
|
|
388
|
+
// "size": "0.1",
|
|
389
|
+
// "value": "4000",
|
|
390
|
+
// "openPrice": "39000",
|
|
391
|
+
// "markPrice": "40000",
|
|
392
|
+
// "updatedAt": 1701563440000
|
|
393
|
+
// }
|
|
394
|
+
// ]
|
|
395
|
+
// },
|
|
396
|
+
// "ts": 1715886400000,
|
|
397
|
+
// "seq": 1
|
|
398
|
+
// }
|
|
399
|
+
//
|
|
400
|
+
if (this.positions === undefined) {
|
|
401
|
+
this.positions = new Cache.ArrayCacheBySymbolBySide();
|
|
402
|
+
}
|
|
403
|
+
const stored = this.positions;
|
|
404
|
+
const data = this.safeDict(message, 'data', {});
|
|
405
|
+
const rawPositions = this.safeList(data, 'positions', []);
|
|
406
|
+
const newPositions = [];
|
|
407
|
+
const first = this.safeDict(rawPositions, 0);
|
|
408
|
+
if (first === undefined) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
for (let i = 0; i < rawPositions.length; i++) {
|
|
412
|
+
const rawPosition = rawPositions[i];
|
|
413
|
+
const marketId = this.safeString(rawPosition, 'market');
|
|
414
|
+
if (marketId === undefined) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
const position = this.parsePosition(rawPosition);
|
|
418
|
+
newPositions.push(position);
|
|
419
|
+
stored.append(position);
|
|
420
|
+
}
|
|
421
|
+
const messageHashes = this.findMessageHashes(client, 'positions::');
|
|
422
|
+
for (let i = 0; i < messageHashes.length; i++) {
|
|
423
|
+
const messageHash = messageHashes[i];
|
|
424
|
+
const parts = messageHash.split('::');
|
|
425
|
+
const symbolsString = parts[1];
|
|
426
|
+
const symbols = symbolsString.split(',');
|
|
427
|
+
const filtered = this.filterByArray(newPositions, 'symbol', symbols, false);
|
|
428
|
+
if (!this.isEmpty(filtered)) {
|
|
429
|
+
client.resolve(filtered, messageHash);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
client.resolve(newPositions, 'positions');
|
|
433
|
+
}
|
|
434
|
+
handleOrders(client, message) {
|
|
435
|
+
//
|
|
436
|
+
// {
|
|
437
|
+
// "type": "ORDER",
|
|
438
|
+
// "data": {
|
|
439
|
+
// "orders": [
|
|
440
|
+
// {
|
|
441
|
+
// "id": 1791181340771614723,
|
|
442
|
+
// "accountId": 1791181340771614721,
|
|
443
|
+
// "externalId": "-1771812132822291885",
|
|
444
|
+
// "market": "BTC-USD",
|
|
445
|
+
// "type": "LIMIT",
|
|
446
|
+
// "side": "BUY",
|
|
447
|
+
// "status": "NEW",
|
|
448
|
+
// "price": "12400.000000",
|
|
449
|
+
// "averagePrice": "13140.000000",
|
|
450
|
+
// "qty": "10.000000",
|
|
451
|
+
// "filledQty": "3.513000",
|
|
452
|
+
// "payedFee": "0.513000",
|
|
453
|
+
// "reduceOnly": true,
|
|
454
|
+
// "postOnly": false,
|
|
455
|
+
// "createdTime": 1715885888571,
|
|
456
|
+
// "updatedTime": 1715885888571,
|
|
457
|
+
// "expireTime": 1715885888571
|
|
458
|
+
// }
|
|
459
|
+
// ]
|
|
460
|
+
// },
|
|
461
|
+
// "ts": 1715885884837,
|
|
462
|
+
// "seq": 1
|
|
463
|
+
// }
|
|
464
|
+
//
|
|
465
|
+
if (this.orders === undefined) {
|
|
466
|
+
const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
|
|
467
|
+
this.orders = new Cache.ArrayCacheBySymbolById(limit);
|
|
468
|
+
}
|
|
469
|
+
const orders = this.orders;
|
|
470
|
+
const data = this.safeDict(message, 'data', {});
|
|
471
|
+
const rawOrders = this.safeList(data, 'orders');
|
|
472
|
+
const symbols = {};
|
|
473
|
+
const first = this.safeDict(rawOrders, 0);
|
|
474
|
+
if (first === undefined) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
for (let i = 0; i < rawOrders.length; i++) {
|
|
478
|
+
const order = this.parseOrder(rawOrders[i]);
|
|
479
|
+
const symbol = this.safeString(order, 'symbol');
|
|
480
|
+
symbols[symbol] = true;
|
|
481
|
+
orders.append(order);
|
|
482
|
+
}
|
|
483
|
+
const keys = Object.keys(symbols);
|
|
484
|
+
for (let i = 0; i < keys.length; i++) {
|
|
485
|
+
const messageHash = 'orders:' + keys[i];
|
|
486
|
+
client.resolve(orders, messageHash);
|
|
487
|
+
}
|
|
488
|
+
client.resolve(orders, 'orders');
|
|
489
|
+
const subscriptions = Object.keys(client.subscriptions);
|
|
490
|
+
for (let i = 0; i < subscriptions.length; i++) {
|
|
491
|
+
const messageHash = subscriptions[i];
|
|
492
|
+
if (messageHash.indexOf('orders:') === 0) {
|
|
493
|
+
client.resolve(orders, messageHash);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* @method
|
|
499
|
+
* @name extended#watchFundingRate
|
|
500
|
+
* @description watch the current funding rate
|
|
501
|
+
* @see https://api.docs.extended.exchange/#funding-rates-stream
|
|
502
|
+
* @param {string} symbol unified market symbol
|
|
503
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
504
|
+
* @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/?id=funding-rate-structure}
|
|
505
|
+
*/
|
|
506
|
+
async watchFundingRate(symbol, params = {}) {
|
|
507
|
+
await this.loadMarkets();
|
|
508
|
+
const market = this.market(symbol);
|
|
509
|
+
symbol = market['symbol'];
|
|
510
|
+
const messageHash = 'fundingRate:' + symbol;
|
|
511
|
+
const query = this.urlencode(params);
|
|
512
|
+
let url = this.urls['api']['ws'] + '/funding/' + market['id'];
|
|
513
|
+
if (query.length > 0) {
|
|
514
|
+
url += '?' + query;
|
|
515
|
+
}
|
|
516
|
+
return await this.watch(url, messageHash, undefined, messageHash, {
|
|
517
|
+
'symbol': symbol,
|
|
518
|
+
'messageHash': messageHash,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
handleFundingRate(client, message) {
|
|
522
|
+
//
|
|
523
|
+
// {
|
|
524
|
+
// "ts": 1701563440000,
|
|
525
|
+
// "data": {
|
|
526
|
+
// "m": "BTC-USD",
|
|
527
|
+
// "T": 1701563440000,
|
|
528
|
+
// "f": "0.001"
|
|
529
|
+
// },
|
|
530
|
+
// "seq": 2
|
|
531
|
+
// }
|
|
532
|
+
//
|
|
533
|
+
const data = this.safeDict(message, 'data', {});
|
|
534
|
+
const fundingRate = this.parseWsFundingRate(data, undefined, message);
|
|
535
|
+
const symbol = this.safeString(fundingRate, 'symbol');
|
|
536
|
+
this.fundingRates[symbol] = fundingRate;
|
|
537
|
+
const messageHash = 'fundingRate:' + symbol;
|
|
538
|
+
client.resolve(fundingRate, messageHash);
|
|
539
|
+
}
|
|
540
|
+
parseWsFundingRate(fundingRate, market = undefined, message = undefined) {
|
|
541
|
+
const marketId = this.safeString(fundingRate, 'm');
|
|
542
|
+
market = this.safeMarket(marketId, market);
|
|
543
|
+
const timestamp = this.safeInteger(message, 'ts');
|
|
544
|
+
const fundingTimestamp = this.safeInteger(fundingRate, 'T');
|
|
545
|
+
return {
|
|
546
|
+
'info': fundingRate,
|
|
547
|
+
'symbol': market['symbol'],
|
|
548
|
+
'markPrice': undefined,
|
|
549
|
+
'indexPrice': undefined,
|
|
550
|
+
'interestRate': undefined,
|
|
551
|
+
'estimatedSettlePrice': undefined,
|
|
552
|
+
'timestamp': timestamp,
|
|
553
|
+
'datetime': this.iso8601(timestamp),
|
|
554
|
+
'fundingRate': this.safeNumber(fundingRate, 'f'),
|
|
555
|
+
'fundingTimestamp': fundingTimestamp,
|
|
556
|
+
'fundingDatetime': this.iso8601(fundingTimestamp),
|
|
557
|
+
'nextFundingRate': undefined,
|
|
558
|
+
'nextFundingTimestamp': undefined,
|
|
559
|
+
'nextFundingDatetime': undefined,
|
|
560
|
+
'previousFundingRate': undefined,
|
|
561
|
+
'previousFundingTimestamp': undefined,
|
|
562
|
+
'previousFundingDatetime': undefined,
|
|
563
|
+
'interval': undefined,
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* @method
|
|
568
|
+
* @name extended#watchMarkPrice
|
|
569
|
+
* @description watches a mark price for a specific market
|
|
570
|
+
* @see https://api.docs.extended.exchange/#mark-price-stream
|
|
571
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
572
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
573
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
574
|
+
*/
|
|
575
|
+
async watchMarkPrice(symbol, params = {}) {
|
|
576
|
+
await this.loadMarkets();
|
|
577
|
+
const market = this.market(symbol);
|
|
578
|
+
symbol = market['symbol'];
|
|
579
|
+
const messageHash = 'markPrice:' + symbol;
|
|
580
|
+
const query = this.urlencode(params);
|
|
581
|
+
let url = this.urls['api']['ws'] + '/prices/mark/' + market['id'];
|
|
582
|
+
if (query.length > 0) {
|
|
583
|
+
url += '?' + query;
|
|
584
|
+
}
|
|
585
|
+
return await this.watch(url, messageHash, undefined, messageHash, {
|
|
586
|
+
'name': 'markPrice',
|
|
587
|
+
'symbol': symbol,
|
|
588
|
+
'messageHash': messageHash,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
handleMarkPrice(client, message) {
|
|
592
|
+
//
|
|
593
|
+
// {
|
|
594
|
+
// "type": "MP",
|
|
595
|
+
// "data": {
|
|
596
|
+
// "m": "BTC-USD",
|
|
597
|
+
// "p": "80988.400408625006",
|
|
598
|
+
// "ts": 0
|
|
599
|
+
// },
|
|
600
|
+
// "ts": 1778641421485,
|
|
601
|
+
// "seq": 1
|
|
602
|
+
// }
|
|
603
|
+
//
|
|
604
|
+
const data = this.safeDict(message, 'data', {});
|
|
605
|
+
const marketId = this.safeString(data, 'm');
|
|
606
|
+
const market = this.safeMarket(marketId);
|
|
607
|
+
const symbol = market['symbol'];
|
|
608
|
+
let timestamp = this.safeInteger(data, 'ts');
|
|
609
|
+
if ((timestamp === undefined) || (timestamp === 0)) {
|
|
610
|
+
timestamp = this.safeInteger(message, 'ts');
|
|
611
|
+
}
|
|
612
|
+
const ticker = this.safeTicker({
|
|
613
|
+
'symbol': symbol,
|
|
614
|
+
'timestamp': timestamp,
|
|
615
|
+
'datetime': this.iso8601(timestamp),
|
|
616
|
+
'markPrice': this.safeString(data, 'p'),
|
|
617
|
+
'info': message,
|
|
618
|
+
}, market);
|
|
619
|
+
this.tickers[symbol] = ticker;
|
|
620
|
+
const messageHash = 'markPrice:' + symbol;
|
|
621
|
+
client.resolve(ticker, messageHash);
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* @method
|
|
625
|
+
* @name extended#watchTrades
|
|
626
|
+
* @description get the list of most recent trades for a particular symbol
|
|
627
|
+
* @see https://api.docs.extended.exchange/#trades-stream
|
|
628
|
+
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
629
|
+
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
630
|
+
* @param {int} [limit] the maximum amount of trades to fetch
|
|
631
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
632
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
|
|
633
|
+
*/
|
|
634
|
+
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
635
|
+
await this.loadMarkets();
|
|
636
|
+
const market = this.market(symbol);
|
|
637
|
+
symbol = market['symbol'];
|
|
638
|
+
const messageHash = 'trades:' + symbol;
|
|
639
|
+
const query = this.urlencode(params);
|
|
640
|
+
let url = this.urls['api']['ws'] + '/publicTrades/' + market['id'];
|
|
641
|
+
if (query.length > 0) {
|
|
642
|
+
url += '?' + query;
|
|
643
|
+
}
|
|
644
|
+
const trades = await this.watch(url, messageHash, undefined, messageHash, {
|
|
645
|
+
'symbol': symbol,
|
|
646
|
+
'limit': limit,
|
|
647
|
+
});
|
|
648
|
+
if (this.newUpdates) {
|
|
649
|
+
limit = trades.getLimit(symbol, limit);
|
|
650
|
+
}
|
|
651
|
+
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
652
|
+
}
|
|
653
|
+
handleTrades(client, message) {
|
|
654
|
+
//
|
|
655
|
+
// {
|
|
656
|
+
// "ts": 1701563440000,
|
|
657
|
+
// "data": [
|
|
658
|
+
// {
|
|
659
|
+
// "m": "BTC-USD",
|
|
660
|
+
// "S": "BUY",
|
|
661
|
+
// "tT": "TRADE",
|
|
662
|
+
// "T": 1701563440000,
|
|
663
|
+
// "p": "25670",
|
|
664
|
+
// "q": "0.1",
|
|
665
|
+
// "i": 25124
|
|
666
|
+
// }
|
|
667
|
+
// ],
|
|
668
|
+
// "seq": 2
|
|
669
|
+
// }
|
|
670
|
+
//
|
|
671
|
+
const data = this.safeList(message, 'data', []);
|
|
672
|
+
const first = this.safeDict(data, 0);
|
|
673
|
+
if (first === undefined) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const marketId = this.safeString(first, 'm');
|
|
677
|
+
const market = this.safeMarket(marketId);
|
|
678
|
+
const symbol = market['symbol'];
|
|
679
|
+
const messageHash = 'trades:' + symbol;
|
|
680
|
+
const subscription = this.safeDict(client.subscriptions, messageHash, {});
|
|
681
|
+
let stored = this.safeValue(this.trades, symbol);
|
|
682
|
+
if (stored === undefined) {
|
|
683
|
+
const defaultLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
684
|
+
const limit = this.safeInteger(subscription, 'limit', defaultLimit);
|
|
685
|
+
stored = new Cache.ArrayCache(limit);
|
|
686
|
+
this.trades[symbol] = stored;
|
|
687
|
+
}
|
|
688
|
+
const previousNonce = this.safeInteger(subscription, 'nonce');
|
|
689
|
+
const nonce = this.safeInteger(message, 'seq');
|
|
690
|
+
if ((previousNonce !== undefined) && (nonce !== undefined) && (nonce <= previousNonce)) {
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
subscription['nonce'] = nonce;
|
|
694
|
+
for (let i = 0; i < data.length; i++) {
|
|
695
|
+
const trade = this.parseTrade(data[i], market);
|
|
696
|
+
stored.append(trade);
|
|
697
|
+
}
|
|
698
|
+
client.resolve(stored, messageHash);
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* @method
|
|
702
|
+
* @name extended#watchOHLCV
|
|
703
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
704
|
+
* @see https://api.docs.extended.exchange/#candles-stream
|
|
705
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
706
|
+
* @param {string} timeframe the length of time each candle represents
|
|
707
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
708
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
709
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
710
|
+
* @param {string} [params.candleType] candle type: 'trades' (default), 'mark-prices', or 'index-prices'
|
|
711
|
+
* @param {string} [params.price] *ignored if params.candleType is set* 'mark' or 'index' for mark price and index price candles
|
|
712
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
713
|
+
*/
|
|
714
|
+
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
715
|
+
await this.loadMarkets();
|
|
716
|
+
const market = this.market(symbol);
|
|
717
|
+
symbol = market['symbol'];
|
|
718
|
+
const price = this.safeString(params, 'price');
|
|
719
|
+
let candleType = this.safeString(params, 'candleType');
|
|
720
|
+
if (candleType === undefined) {
|
|
721
|
+
if (price === 'mark') {
|
|
722
|
+
candleType = 'mark-prices';
|
|
723
|
+
}
|
|
724
|
+
else if (price === 'index') {
|
|
725
|
+
candleType = 'index-prices';
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
candleType = 'trades';
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
params = this.omit(params, ['candleType', 'price']);
|
|
732
|
+
const interval = this.safeString(this.timeframes, timeframe, timeframe);
|
|
733
|
+
const messageHash = 'ohlcv:' + symbol + ':' + timeframe + ':' + candleType;
|
|
734
|
+
const query = this.urlencode(this.extend({ 'interval': interval }, params));
|
|
735
|
+
const url = this.urls['api']['ws'] + '/candles/' + market['id'] + '/' + candleType + '?' + query;
|
|
736
|
+
const ohlcv = await this.watch(url, messageHash, undefined, messageHash, {
|
|
737
|
+
'name': 'ohlcv',
|
|
738
|
+
'symbol': symbol,
|
|
739
|
+
'timeframe': timeframe,
|
|
740
|
+
'candleType': candleType,
|
|
741
|
+
'limit': limit,
|
|
742
|
+
'messageHash': messageHash,
|
|
743
|
+
});
|
|
744
|
+
if (this.newUpdates) {
|
|
745
|
+
limit = ohlcv.getLimit(symbol, limit);
|
|
746
|
+
}
|
|
747
|
+
return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
|
|
748
|
+
}
|
|
749
|
+
handleOHLCV(client, message) {
|
|
750
|
+
//
|
|
751
|
+
// {
|
|
752
|
+
// "ts": 1695738675123,
|
|
753
|
+
// "data": [
|
|
754
|
+
// {
|
|
755
|
+
// "T": 1695738674000,
|
|
756
|
+
// "o": "1000.0000",
|
|
757
|
+
// "l": "800.0000",
|
|
758
|
+
// "h": "2400.0000",
|
|
759
|
+
// "c": "2100.0000",
|
|
760
|
+
// "v": "10.0000"
|
|
761
|
+
// }
|
|
762
|
+
// ],
|
|
763
|
+
// "seq": 1
|
|
764
|
+
// }
|
|
765
|
+
//
|
|
766
|
+
const subscription = this.findSubscription(client, 'ohlcv');
|
|
767
|
+
if (subscription === undefined) {
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
const symbol = this.safeString(subscription, 'symbol');
|
|
771
|
+
const timeframe = this.safeString(subscription, 'timeframe');
|
|
772
|
+
const candleType = this.safeString(subscription, 'candleType');
|
|
773
|
+
const cacheKey = (candleType === 'trades') ? timeframe : timeframe + ':' + candleType;
|
|
774
|
+
const messageHash = this.safeString(subscription, 'messageHash');
|
|
775
|
+
this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
|
|
776
|
+
let stored = this.safeValue(this.ohlcvs[symbol], cacheKey);
|
|
777
|
+
if (stored === undefined) {
|
|
778
|
+
const defaultLimit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
779
|
+
const limit = this.safeInteger(subscription, 'limit', defaultLimit);
|
|
780
|
+
stored = new Cache.ArrayCacheByTimestamp(limit);
|
|
781
|
+
this.ohlcvs[symbol][cacheKey] = stored;
|
|
782
|
+
}
|
|
783
|
+
const previousNonce = this.safeInteger(subscription, 'nonce');
|
|
784
|
+
const nonce = this.safeInteger(message, 'seq');
|
|
785
|
+
if ((previousNonce !== undefined) && (nonce !== undefined) && (nonce <= previousNonce)) {
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
subscription['nonce'] = nonce;
|
|
789
|
+
const data = this.safeList(message, 'data', []);
|
|
790
|
+
for (let i = 0; i < data.length; i++) {
|
|
791
|
+
const parsed = this.parseOHLCV(data[i]);
|
|
792
|
+
stored.append(parsed);
|
|
793
|
+
}
|
|
794
|
+
client.resolve(stored, messageHash);
|
|
795
|
+
}
|
|
796
|
+
findSubscription(client, name) {
|
|
797
|
+
const keys = Object.keys(client.subscriptions);
|
|
798
|
+
for (let i = 0; i < keys.length; i++) {
|
|
799
|
+
const key = keys[i];
|
|
800
|
+
const subscription = this.safeDict(client.subscriptions, key);
|
|
801
|
+
const subscriptionName = this.safeString(subscription, 'name');
|
|
802
|
+
if (subscriptionName === name) {
|
|
803
|
+
return subscription;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
return undefined;
|
|
807
|
+
}
|
|
808
|
+
handleErrorMessage(client, message) {
|
|
809
|
+
//
|
|
810
|
+
// { "status": "ERROR", "error": { "code": 1001, "message": "Market not found." } }
|
|
811
|
+
//
|
|
812
|
+
const error = this.safeValue(message, 'error');
|
|
813
|
+
if (error === undefined) {
|
|
814
|
+
return false;
|
|
815
|
+
}
|
|
816
|
+
const feedback = this.id + ' ' + this.json(message);
|
|
817
|
+
const errorCode = this.safeString(error, 'code');
|
|
818
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
|
|
819
|
+
const errorMessage = this.safeString(error, 'message');
|
|
820
|
+
this.throwBroadlyMatchedException(this.exceptions['broad'], errorMessage, feedback);
|
|
821
|
+
throw new errors.ExchangeError(feedback);
|
|
822
|
+
}
|
|
823
|
+
handleMessage(client, message) {
|
|
824
|
+
if (this.handleErrorMessage(client, message)) {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
const type = this.safeString(message, 'type');
|
|
828
|
+
const data = this.safeValue(message, 'data');
|
|
829
|
+
if (Array.isArray(data)) {
|
|
830
|
+
const first = this.safeDict(data, 0, {});
|
|
831
|
+
const side = this.safeString(first, 'S');
|
|
832
|
+
if (side !== undefined) {
|
|
833
|
+
this.handleTrades(client, message);
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
this.handleOHLCV(client, message);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
else if (data !== undefined) {
|
|
840
|
+
if ((type === 'ORDER') || ('orders' in data)) {
|
|
841
|
+
this.handleOrders(client, message);
|
|
842
|
+
}
|
|
843
|
+
if ((type === 'TRADE') || ('trades' in data)) {
|
|
844
|
+
this.handleMyTrades(client, message);
|
|
845
|
+
}
|
|
846
|
+
if ((type === 'POSITION') || ('positions' in data)) {
|
|
847
|
+
this.handlePositions(client, message);
|
|
848
|
+
}
|
|
849
|
+
if ((type === 'BALANCE') || ('balance' in data) || ('spotBalances' in data)) {
|
|
850
|
+
this.handleBalance(client, message);
|
|
851
|
+
}
|
|
852
|
+
if (type === 'MP') {
|
|
853
|
+
this.handleMarkPrice(client, message);
|
|
854
|
+
}
|
|
855
|
+
else if ('f' in data) {
|
|
856
|
+
this.handleFundingRate(client, message);
|
|
857
|
+
}
|
|
858
|
+
else {
|
|
859
|
+
this.handleOrderBook(client, message);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
exports["default"] = extended;
|