ccxt 4.5.29 → 4.5.30
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 +6 -5
- package/dist/ccxt.browser.min.js +7 -7
- package/dist/cjs/ccxt.js +6 -1
- package/dist/cjs/src/abstract/bydfi.js +11 -0
- package/dist/cjs/src/bingx.js +1 -1
- package/dist/cjs/src/bullish.js +1 -1
- package/dist/cjs/src/bybit.js +2 -0
- package/dist/cjs/src/bydfi.js +2907 -0
- package/dist/cjs/src/coinbase.js +34 -1
- package/dist/cjs/src/dydx.js +3 -3
- package/dist/cjs/src/gate.js +3 -2
- package/dist/cjs/src/hyperliquid.js +10 -3
- package/dist/cjs/src/kucoin.js +112 -4
- package/dist/cjs/src/pro/apex.js +5 -3
- package/dist/cjs/src/pro/binance.js +10 -6
- package/dist/cjs/src/pro/bingx.js +5 -3
- package/dist/cjs/src/pro/bitmart.js +5 -3
- package/dist/cjs/src/pro/bybit.js +5 -3
- package/dist/cjs/src/pro/bydfi.js +1077 -0
- package/dist/cjs/src/pro/cryptocom.js +5 -3
- package/dist/cjs/src/pro/gate.js +5 -3
- package/dist/cjs/src/pro/hashkey.js +5 -3
- package/dist/cjs/src/pro/kucoinfutures.js +5 -3
- package/dist/cjs/src/pro/modetrade.js +5 -3
- package/dist/cjs/src/pro/toobit.js +11 -7
- package/dist/cjs/src/pro/woo.js +5 -3
- package/dist/cjs/src/pro/woofipro.js +5 -3
- package/dist/cjs/src/pro/xt.js +5 -3
- package/dist/cjs/src/toobit.js +2 -1
- package/js/ccxt.d.ts +8 -2
- package/js/ccxt.js +6 -2
- package/js/src/abstract/bydfi.d.ts +52 -0
- package/js/src/abstract/bydfi.js +11 -0
- package/js/src/bingx.js +1 -1
- package/js/src/bullish.js +1 -1
- package/js/src/bybit.js +2 -0
- package/js/src/bydfi.d.ts +472 -0
- package/js/src/bydfi.js +2905 -0
- package/js/src/coinbase.d.ts +11 -0
- package/js/src/coinbase.js +34 -1
- package/js/src/dydx.js +3 -3
- package/js/src/gate.js +3 -2
- package/js/src/hyperliquid.js +10 -3
- package/js/src/kucoin.d.ts +14 -0
- package/js/src/kucoin.js +112 -4
- package/js/src/pro/apex.js +5 -3
- package/js/src/pro/binance.js +10 -6
- package/js/src/pro/bingx.js +5 -3
- package/js/src/pro/bitmart.js +5 -3
- package/js/src/pro/bybit.js +5 -3
- package/js/src/pro/bydfi.d.ts +206 -0
- package/js/src/pro/bydfi.js +1076 -0
- package/js/src/pro/cryptocom.js +5 -3
- package/js/src/pro/gate.js +5 -3
- package/js/src/pro/hashkey.js +5 -3
- package/js/src/pro/kucoinfutures.js +5 -3
- package/js/src/pro/modetrade.js +5 -3
- package/js/src/pro/toobit.js +11 -7
- package/js/src/pro/woo.js +5 -3
- package/js/src/pro/woofipro.js +5 -3
- package/js/src/pro/xt.js +5 -3
- package/js/src/toobit.js +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,1077 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var bydfi$1 = require('../bydfi.js');
|
|
6
|
+
var Precise = require('../base/Precise.js');
|
|
7
|
+
var errors = require('../base/errors.js');
|
|
8
|
+
var Cache = require('../base/ws/Cache.js');
|
|
9
|
+
var sha256 = require('../static_dependencies/noble-hashes/sha256.js');
|
|
10
|
+
|
|
11
|
+
// ----------------------------------------------------------------------------
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
class bydfi extends bydfi$1["default"] {
|
|
14
|
+
describe() {
|
|
15
|
+
return this.deepExtend(super.describe(), {
|
|
16
|
+
'has': {
|
|
17
|
+
'ws': true,
|
|
18
|
+
'watchBalance': true,
|
|
19
|
+
'watchBidsAsks': false,
|
|
20
|
+
'watchMyTrades': false,
|
|
21
|
+
'watchOHLCV': true,
|
|
22
|
+
'watchOHLCVForSymbols': true,
|
|
23
|
+
'watchOrderBook': true,
|
|
24
|
+
'watchOrderBookForSymbols': true,
|
|
25
|
+
'watchOrders': true,
|
|
26
|
+
'watchOrdersForSymbols': true,
|
|
27
|
+
'watchPositions': true,
|
|
28
|
+
'watchTicker': true,
|
|
29
|
+
'watchTickers': true,
|
|
30
|
+
'watchTrades': false,
|
|
31
|
+
'watchTradesForSymbols': false,
|
|
32
|
+
'unwatchBidsAsks': false,
|
|
33
|
+
'unwatchOHLCV': true,
|
|
34
|
+
'unwatchOHLCVForSymbols': true,
|
|
35
|
+
'unwatchOrderBook': true,
|
|
36
|
+
'unwatchOrderBookForSymbols': true,
|
|
37
|
+
'unwatchTicker': true,
|
|
38
|
+
'unwatchTickers': true,
|
|
39
|
+
'unWatchTrades': false,
|
|
40
|
+
'unWatchTradesForSymbols': false,
|
|
41
|
+
'unWatchOrders': false,
|
|
42
|
+
'unWatchOrdersForSymbols': false,
|
|
43
|
+
'unWatchPositions': false,
|
|
44
|
+
},
|
|
45
|
+
'urls': {
|
|
46
|
+
'api': {
|
|
47
|
+
'ws': 'wss://stream.bydfi.com/v1/public/swap',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
'options': {
|
|
51
|
+
'watchOrderBookForSymbols': {
|
|
52
|
+
'depth': '100',
|
|
53
|
+
'frequency': '1000ms', // 100ms, 1000ms
|
|
54
|
+
},
|
|
55
|
+
'watchBalance': {
|
|
56
|
+
'fetchBalanceSnapshot': false,
|
|
57
|
+
'awaitBalanceSnapshot': true, // whether to wait for the balance snapshot before providing updates
|
|
58
|
+
},
|
|
59
|
+
'timeframes': {
|
|
60
|
+
'1m': '1m',
|
|
61
|
+
'3m': '3m',
|
|
62
|
+
'5m': '5m',
|
|
63
|
+
'15m': '15m',
|
|
64
|
+
'30m': '30m',
|
|
65
|
+
'1h': '1h',
|
|
66
|
+
'2h': '2h',
|
|
67
|
+
'4h': '4h',
|
|
68
|
+
'6h': '6h',
|
|
69
|
+
'8h': '8h',
|
|
70
|
+
'12h': '12h',
|
|
71
|
+
'1d': '1d',
|
|
72
|
+
'1w': '1w',
|
|
73
|
+
'1M': '1M',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
'streaming': {
|
|
77
|
+
'ping': this.ping,
|
|
78
|
+
'keepAlive': 119000, // 2 minutes
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
ping(client) {
|
|
83
|
+
return {
|
|
84
|
+
'id': this.requestId(),
|
|
85
|
+
'method': 'ping',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
requestId() {
|
|
89
|
+
this.lockId();
|
|
90
|
+
const reqid = this.sum(this.safeInteger(this.options, 'reqid', 0), 1);
|
|
91
|
+
this.options['reqid'] = reqid;
|
|
92
|
+
this.unlockId();
|
|
93
|
+
return reqid;
|
|
94
|
+
}
|
|
95
|
+
async watchPublic(messageHashes, channels, params = {}, subscription = {}) {
|
|
96
|
+
const url = this.urls['api']['ws'];
|
|
97
|
+
const id = this.requestId();
|
|
98
|
+
const subscriptionParams = {
|
|
99
|
+
'id': id,
|
|
100
|
+
};
|
|
101
|
+
const unsubscribe = this.safeBool(params, 'unsubscribe', false);
|
|
102
|
+
let method = 'SUBSCRIBE';
|
|
103
|
+
if (unsubscribe) {
|
|
104
|
+
method = 'UNSUBSCRIBE';
|
|
105
|
+
params = this.omit(params, 'unsubscribe');
|
|
106
|
+
subscriptionParams['unsubscribe'] = true;
|
|
107
|
+
subscriptionParams['messageHashes'] = messageHashes;
|
|
108
|
+
}
|
|
109
|
+
const message = {
|
|
110
|
+
'id': id,
|
|
111
|
+
'method': method,
|
|
112
|
+
'params': channels,
|
|
113
|
+
};
|
|
114
|
+
return await this.watchMultiple(url, messageHashes, this.deepExtend(message, params), messageHashes, this.extend(subscriptionParams, subscription));
|
|
115
|
+
}
|
|
116
|
+
async watchPrivate(messageHashes, params = {}) {
|
|
117
|
+
this.checkRequiredCredentials();
|
|
118
|
+
const url = this.urls['api']['ws'];
|
|
119
|
+
const subHash = 'private';
|
|
120
|
+
const client = this.client(url);
|
|
121
|
+
const privateSubscription = this.safeValue(client.subscriptions, subHash);
|
|
122
|
+
const subscription = {};
|
|
123
|
+
if (privateSubscription === undefined) {
|
|
124
|
+
const id = this.requestId();
|
|
125
|
+
const timestamp = this.milliseconds().toString();
|
|
126
|
+
const payload = this.apiKey + timestamp;
|
|
127
|
+
const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256.sha256, 'hex');
|
|
128
|
+
const request = {
|
|
129
|
+
'id': id,
|
|
130
|
+
'method': 'LOGIN',
|
|
131
|
+
'params': {
|
|
132
|
+
'apiKey': this.apiKey,
|
|
133
|
+
'timestamp': timestamp,
|
|
134
|
+
'sign': signature,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
params = this.deepExtend(request, params);
|
|
138
|
+
subscription['id'] = id;
|
|
139
|
+
}
|
|
140
|
+
return await this.watchMultiple(url, messageHashes, params, ['private'], subscription);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @method
|
|
144
|
+
* @name bydfi#watchTicker
|
|
145
|
+
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
146
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
|
|
147
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
148
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
149
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
150
|
+
*/
|
|
151
|
+
async watchTicker(symbol, params = {}) {
|
|
152
|
+
await this.loadMarkets();
|
|
153
|
+
const market = this.market(symbol);
|
|
154
|
+
const marketId = market['id'];
|
|
155
|
+
const messageHash = 'ticker::' + symbol;
|
|
156
|
+
const channel = marketId + '@ticker';
|
|
157
|
+
return await this.watchPublic([messageHash], [channel], params);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* @method
|
|
161
|
+
* @name bydfi#unWatchTicker
|
|
162
|
+
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
163
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
|
|
164
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
165
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
166
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
167
|
+
*/
|
|
168
|
+
async unWatchTicker(symbol, params = {}) {
|
|
169
|
+
return await this.unWatchTickers([symbol], params);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* @method
|
|
173
|
+
* @name bydfi#watchTickers
|
|
174
|
+
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
|
175
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
|
|
176
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#market-wide-ticker
|
|
177
|
+
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
|
|
178
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
179
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
180
|
+
*/
|
|
181
|
+
async watchTickers(symbols = undefined, params = {}) {
|
|
182
|
+
await this.loadMarkets();
|
|
183
|
+
symbols = this.marketSymbols(symbols, undefined, true);
|
|
184
|
+
const messageHashes = [];
|
|
185
|
+
const messageHash = 'ticker::';
|
|
186
|
+
const channels = [];
|
|
187
|
+
const channel = '@ticker';
|
|
188
|
+
if (symbols === undefined) {
|
|
189
|
+
messageHashes.push(messageHash + 'all');
|
|
190
|
+
channels.push('!ticker@arr');
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
194
|
+
const symbol = symbols[i];
|
|
195
|
+
const marketId = this.marketId(symbol);
|
|
196
|
+
messageHashes.push(messageHash + symbol);
|
|
197
|
+
channels.push(marketId + channel);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
await this.watchPublic(messageHashes, channels, params);
|
|
201
|
+
return this.filterByArray(this.tickers, 'symbol', symbols);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* @method
|
|
205
|
+
* @name bydfi#unWatchTickers
|
|
206
|
+
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
|
207
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#ticker-by-symbol
|
|
208
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#market-wide-ticker
|
|
209
|
+
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
|
|
210
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
211
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
|
|
212
|
+
*/
|
|
213
|
+
async unWatchTickers(symbols = undefined, params = {}) {
|
|
214
|
+
symbols = this.marketSymbols(symbols, undefined, true);
|
|
215
|
+
const messageHashes = [];
|
|
216
|
+
const messageHash = 'unsubscribe::ticker::';
|
|
217
|
+
const channels = [];
|
|
218
|
+
const channel = '@ticker';
|
|
219
|
+
const subscription = {
|
|
220
|
+
'topic': 'ticker',
|
|
221
|
+
};
|
|
222
|
+
if (symbols === undefined) {
|
|
223
|
+
// all tickers and tickers for specific symbols are different channels
|
|
224
|
+
// we need to unsubscribe from all ticker channels
|
|
225
|
+
const subHashes = this.getMessageHashesForTickersUnsubscription();
|
|
226
|
+
subscription['subHashIsPrefix'] = true;
|
|
227
|
+
for (let i = 0; i < subHashes.length; i++) {
|
|
228
|
+
const subHash = this.safeString(subHashes, i);
|
|
229
|
+
if (subHash !== undefined) {
|
|
230
|
+
const parts = subHash.split('::');
|
|
231
|
+
const symbol = this.safeString(parts, 1);
|
|
232
|
+
if (symbol === 'all') {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const marketId = this.marketId(symbol);
|
|
236
|
+
channels.push(marketId + channel);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
messageHashes.push(messageHash);
|
|
240
|
+
channels.push('!ticker@arr');
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
244
|
+
const symbol = symbols[i];
|
|
245
|
+
const marketId = this.marketId(symbol);
|
|
246
|
+
messageHashes.push(messageHash + symbol);
|
|
247
|
+
channels.push(marketId + channel);
|
|
248
|
+
}
|
|
249
|
+
subscription['symbols'] = symbols;
|
|
250
|
+
}
|
|
251
|
+
params = this.extend(params, { 'unsubscribe': true });
|
|
252
|
+
return await this.watchPublic(messageHashes, channels, params, subscription);
|
|
253
|
+
}
|
|
254
|
+
getMessageHashesForTickersUnsubscription() {
|
|
255
|
+
const url = this.urls['api']['ws']['public'];
|
|
256
|
+
const client = this.client(url);
|
|
257
|
+
const subscriptions = client.subscriptions;
|
|
258
|
+
const messageHashes = [];
|
|
259
|
+
const keys = Object.keys(subscriptions);
|
|
260
|
+
for (let i = 0; i < keys.length; i++) {
|
|
261
|
+
const key = keys[i];
|
|
262
|
+
if (key.indexOf('ticker::') === 0) {
|
|
263
|
+
messageHashes.push(key);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return messageHashes;
|
|
267
|
+
}
|
|
268
|
+
handleTicker(client, message) {
|
|
269
|
+
//
|
|
270
|
+
// {
|
|
271
|
+
// "s": "KAS-USDT",
|
|
272
|
+
// "c": 0.04543,
|
|
273
|
+
// "e": "24hrTicker",
|
|
274
|
+
// "E": 1766528295905,
|
|
275
|
+
// "v": 98278925,
|
|
276
|
+
// "h": 0.04685,
|
|
277
|
+
// "l": 0.04404,
|
|
278
|
+
// "o": 0.04657
|
|
279
|
+
// }
|
|
280
|
+
//
|
|
281
|
+
const ticker = this.parseTicker(message);
|
|
282
|
+
const symbol = ticker['symbol'];
|
|
283
|
+
const messageHash = 'ticker::' + symbol;
|
|
284
|
+
this.tickers[symbol] = ticker;
|
|
285
|
+
client.resolve(this.tickers[symbol], messageHash);
|
|
286
|
+
client.resolve(this.tickers, 'ticker::all');
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* @method
|
|
290
|
+
* @name bydfi#watchOHLCV
|
|
291
|
+
* @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
|
|
292
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
|
|
293
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
294
|
+
* @param {string} timeframe the length of time each candle represents
|
|
295
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
296
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
297
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
298
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
299
|
+
*/
|
|
300
|
+
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
301
|
+
const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
|
|
302
|
+
return result[symbol][timeframe];
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* @method
|
|
306
|
+
* @name bydfi#unWatchOHLCV
|
|
307
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
308
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
|
|
309
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
310
|
+
* @param {string} timeframe the length of time each candle represents
|
|
311
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
312
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
313
|
+
*/
|
|
314
|
+
async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
|
|
315
|
+
return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* @method
|
|
319
|
+
* @name bydfi#watchOHLCVForSymbols
|
|
320
|
+
* @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
|
|
321
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
|
|
322
|
+
* @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
|
323
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
324
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
325
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
326
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
327
|
+
*/
|
|
328
|
+
async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
|
|
329
|
+
const symbolsLength = symbolsAndTimeframes.length;
|
|
330
|
+
if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
|
|
331
|
+
throw new errors.ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like ['ETH/USDC', '1m']");
|
|
332
|
+
}
|
|
333
|
+
await this.loadMarkets();
|
|
334
|
+
const channels = [];
|
|
335
|
+
const messageHashes = [];
|
|
336
|
+
for (let i = 0; i < symbolsAndTimeframes.length; i++) {
|
|
337
|
+
const symbolAndTimeframe = symbolsAndTimeframes[i];
|
|
338
|
+
const marketId = this.safeString(symbolAndTimeframe, 0);
|
|
339
|
+
const market = this.market(marketId);
|
|
340
|
+
const tf = this.safeString(symbolAndTimeframe, 1);
|
|
341
|
+
const timeframes = this.safeDict(this.options, 'timeframes', {});
|
|
342
|
+
const interval = this.safeString(timeframes, tf, tf);
|
|
343
|
+
channels.push(market['id'] + '@kline_' + interval);
|
|
344
|
+
messageHashes.push('ohlcv::' + market['symbol'] + '::' + interval);
|
|
345
|
+
}
|
|
346
|
+
const [symbol, timeframe, candles] = await this.watchPublic(messageHashes, channels, params);
|
|
347
|
+
if (this.newUpdates) {
|
|
348
|
+
limit = candles.getLimit(symbol, limit);
|
|
349
|
+
}
|
|
350
|
+
const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
|
|
351
|
+
return this.createOHLCVObject(symbol, timeframe, filtered);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* @method
|
|
355
|
+
* @name bydfi#unWatchOHLCVForSymbols
|
|
356
|
+
* @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
357
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#candlestick-data
|
|
358
|
+
* @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
|
359
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
360
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
361
|
+
*/
|
|
362
|
+
async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
|
|
363
|
+
const symbolsLength = symbolsAndTimeframes.length;
|
|
364
|
+
if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
|
|
365
|
+
throw new errors.ArgumentsRequired(this.id + " unWatchOHLCVForSymbols() requires a an array of symbols and timeframes, like ['ETH/USDC', '1m']");
|
|
366
|
+
}
|
|
367
|
+
await this.loadMarkets();
|
|
368
|
+
const channels = [];
|
|
369
|
+
const messageHashes = [];
|
|
370
|
+
for (let i = 0; i < symbolsAndTimeframes.length; i++) {
|
|
371
|
+
const symbolAndTimeframe = symbolsAndTimeframes[i];
|
|
372
|
+
const marketId = this.safeString(symbolAndTimeframe, 0);
|
|
373
|
+
const market = this.market(marketId);
|
|
374
|
+
const tf = this.safeString(symbolAndTimeframe, 1);
|
|
375
|
+
const interval = this.safeString(this.timeframes, tf, tf);
|
|
376
|
+
channels.push(market['id'] + '@kline_' + interval);
|
|
377
|
+
messageHashes.push('unsubscribe::ohlcv::' + market['symbol'] + '::' + interval);
|
|
378
|
+
}
|
|
379
|
+
params = this.extend(params, { 'unsubscribe': true });
|
|
380
|
+
const subscription = {
|
|
381
|
+
'topic': 'ohlcv',
|
|
382
|
+
'symbolsAndTimeframes': symbolsAndTimeframes,
|
|
383
|
+
};
|
|
384
|
+
return await this.watchPublic(messageHashes, channels, params, subscription);
|
|
385
|
+
}
|
|
386
|
+
handleOHLCV(client, message) {
|
|
387
|
+
//
|
|
388
|
+
// {
|
|
389
|
+
// "s": "ETH-USDC",
|
|
390
|
+
// "c": 2956.13,
|
|
391
|
+
// "t": 1766506860000,
|
|
392
|
+
// "T": 1766506920000,
|
|
393
|
+
// "e": "kline",
|
|
394
|
+
// "v": 3955,
|
|
395
|
+
// "h": 2956.41,
|
|
396
|
+
// "i": "1m",
|
|
397
|
+
// "l": 2956.05,
|
|
398
|
+
// "o": 2956.05
|
|
399
|
+
// }
|
|
400
|
+
//
|
|
401
|
+
const marketId = this.safeString(message, 's');
|
|
402
|
+
const market = this.safeMarket(marketId);
|
|
403
|
+
const symbol = market['symbol'];
|
|
404
|
+
const interval = this.safeString(message, 'i');
|
|
405
|
+
const timeframes = this.safeDict(this.options, 'timeframes', {});
|
|
406
|
+
const timeframe = this.findTimeframe(interval, timeframes);
|
|
407
|
+
if (!(symbol in this.ohlcvs)) {
|
|
408
|
+
this.ohlcvs[symbol] = {};
|
|
409
|
+
}
|
|
410
|
+
if (!(timeframe in this.ohlcvs[symbol])) {
|
|
411
|
+
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
412
|
+
const stored = new Cache.ArrayCacheByTimestamp(limit);
|
|
413
|
+
this.ohlcvs[symbol][timeframe] = stored;
|
|
414
|
+
}
|
|
415
|
+
const ohlcv = this.ohlcvs[symbol][timeframe];
|
|
416
|
+
const parsed = this.parseWsOHLCV(message);
|
|
417
|
+
ohlcv.append(parsed);
|
|
418
|
+
const messageHash = 'ohlcv::' + symbol + '::' + timeframe;
|
|
419
|
+
client.resolve([symbol, timeframe, ohlcv], messageHash);
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* @method
|
|
423
|
+
* @name bydfi#watchOrderBook
|
|
424
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
425
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
|
|
426
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
427
|
+
* @param {int} [limit] the maximum amount of order book entries to return (default and maxi is 100)
|
|
428
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
429
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
|
|
430
|
+
*/
|
|
431
|
+
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
432
|
+
return await this.watchOrderBookForSymbols([symbol], limit, params);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* @method
|
|
436
|
+
* @name bydfi#unWatchOrderBook
|
|
437
|
+
* @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
438
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
|
|
439
|
+
* @param {string} symbol unified array of symbols
|
|
440
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
441
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
|
|
442
|
+
*/
|
|
443
|
+
async unWatchOrderBook(symbol, params = {}) {
|
|
444
|
+
return await this.unWatchOrderBookForSymbols([symbol], params);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* @method
|
|
448
|
+
* @name bydfi#watchOrderBookForSymbols
|
|
449
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
450
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
|
|
451
|
+
* @param {string[]} symbols unified array of symbols
|
|
452
|
+
* @param {int} [limit] the maximum amount of order book entries to return (default and max is 100)
|
|
453
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
454
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
|
|
455
|
+
*/
|
|
456
|
+
async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
|
|
457
|
+
await this.loadMarkets();
|
|
458
|
+
symbols = this.marketSymbols(symbols, undefined, false);
|
|
459
|
+
let depth = '100';
|
|
460
|
+
[depth, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', depth);
|
|
461
|
+
let frequency = '100ms';
|
|
462
|
+
[frequency, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'frequency', frequency);
|
|
463
|
+
let channelSuffix = '';
|
|
464
|
+
if (frequency === '100ms') {
|
|
465
|
+
channelSuffix = '@100ms';
|
|
466
|
+
}
|
|
467
|
+
const channels = [];
|
|
468
|
+
const messageHashes = [];
|
|
469
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
470
|
+
const symbol = symbols[i];
|
|
471
|
+
const market = this.market(symbol);
|
|
472
|
+
channels.push(market['id'] + '@depth' + depth + channelSuffix);
|
|
473
|
+
messageHashes.push('orderbook::' + symbol);
|
|
474
|
+
}
|
|
475
|
+
const orderbook = await this.watchPublic(messageHashes, channels, params);
|
|
476
|
+
return orderbook.limit();
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* @method
|
|
480
|
+
* @name bydfi#unWatchOrderBookForSymbols
|
|
481
|
+
* @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
482
|
+
* @see https://developers.bydfi.com/en/swap/websocket-market#limited-depth-information
|
|
483
|
+
* @param {string[]} symbols unified array of symbols
|
|
484
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
485
|
+
* @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
|
|
486
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure} indexed by market symbols
|
|
487
|
+
*/
|
|
488
|
+
async unWatchOrderBookForSymbols(symbols, params = {}) {
|
|
489
|
+
await this.loadMarkets();
|
|
490
|
+
symbols = this.marketSymbols(symbols, undefined, false);
|
|
491
|
+
let depth = '100';
|
|
492
|
+
[depth, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', depth);
|
|
493
|
+
let frequency = '100ms';
|
|
494
|
+
[frequency, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'frequency', frequency);
|
|
495
|
+
let channelSuffix = '';
|
|
496
|
+
if (frequency === '100ms') {
|
|
497
|
+
channelSuffix = '@100ms';
|
|
498
|
+
}
|
|
499
|
+
const channels = [];
|
|
500
|
+
const messageHashes = [];
|
|
501
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
502
|
+
const symbol = symbols[i];
|
|
503
|
+
const market = this.market(symbol);
|
|
504
|
+
channels.push(market['id'] + '@depth' + depth + channelSuffix);
|
|
505
|
+
messageHashes.push('unsubscribe::orderbook::' + symbol);
|
|
506
|
+
}
|
|
507
|
+
const subscription = {
|
|
508
|
+
'topic': 'orderbook',
|
|
509
|
+
'symbols': symbols,
|
|
510
|
+
};
|
|
511
|
+
params = this.extend(params, { 'unsubscribe': true });
|
|
512
|
+
return await this.watchPublic(messageHashes, channels, params, subscription);
|
|
513
|
+
}
|
|
514
|
+
handleOrderBook(client, message) {
|
|
515
|
+
//
|
|
516
|
+
// {
|
|
517
|
+
// "a": [ [ 150000, 15 ], ... ],
|
|
518
|
+
// "b": [ [ 90450.7, 3615 ], ... ],
|
|
519
|
+
// "s": "BTC-USDT",
|
|
520
|
+
// "e": "depthUpdate",
|
|
521
|
+
// "E": 1766577624512
|
|
522
|
+
// }
|
|
523
|
+
//
|
|
524
|
+
const marketId = this.safeString(message, 's');
|
|
525
|
+
const symbol = this.safeSymbol(marketId);
|
|
526
|
+
const timestamp = this.safeInteger(message, 'E');
|
|
527
|
+
if (!(symbol in this.orderbooks)) {
|
|
528
|
+
this.orderbooks[symbol] = this.orderBook();
|
|
529
|
+
}
|
|
530
|
+
const orderbook = this.orderbooks[symbol];
|
|
531
|
+
const parsed = this.parseOrderBook(message, symbol, timestamp, 'b', 'a');
|
|
532
|
+
orderbook.reset(parsed);
|
|
533
|
+
const messageHash = 'orderbook::' + symbol;
|
|
534
|
+
this.orderbooks[symbol] = orderbook;
|
|
535
|
+
client.resolve(orderbook, messageHash);
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* @method
|
|
539
|
+
* @name bydfi#watchOrders
|
|
540
|
+
* @description watches information on multiple orders made by the user
|
|
541
|
+
* @see https://developers.bydfi.com/en/swap/websocket-account#order-trade-update-push
|
|
542
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
543
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
544
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
545
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
546
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
|
|
547
|
+
*/
|
|
548
|
+
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
549
|
+
let symbols = undefined;
|
|
550
|
+
if (symbol !== undefined) {
|
|
551
|
+
symbols = [symbol];
|
|
552
|
+
}
|
|
553
|
+
return await this.watchOrdersForSymbols(symbols, since, limit, params);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* @method
|
|
557
|
+
* @name bydfi#watchOrdersForSymbols
|
|
558
|
+
* @description watches information on multiple orders made by the user
|
|
559
|
+
* @see https://developers.bydfi.com/en/swap/websocket-account#order-trade-update-push
|
|
560
|
+
* @param {string[]} symbols unified symbol of the market to fetch orders for
|
|
561
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
562
|
+
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
563
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
564
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
|
|
565
|
+
*/
|
|
566
|
+
async watchOrdersForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
|
|
567
|
+
await this.loadMarkets();
|
|
568
|
+
symbols = this.marketSymbols(symbols, undefined, true);
|
|
569
|
+
const messageHashes = [];
|
|
570
|
+
if (symbols === undefined) {
|
|
571
|
+
messageHashes.push('orders');
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
575
|
+
const symbol = symbols[i];
|
|
576
|
+
messageHashes.push('orders::' + symbol);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const orders = await this.watchPrivate(messageHashes, params);
|
|
580
|
+
if (this.newUpdates) {
|
|
581
|
+
const first = this.safeValue(orders, 0);
|
|
582
|
+
const tradeSymbol = this.safeString(first, 'symbol');
|
|
583
|
+
limit = orders.getLimit(tradeSymbol, limit);
|
|
584
|
+
}
|
|
585
|
+
return this.filterBySinceLimit(orders, since, limit, 'timestamp', true);
|
|
586
|
+
}
|
|
587
|
+
handleOrder(client, message) {
|
|
588
|
+
//
|
|
589
|
+
// {
|
|
590
|
+
// "T": 1766588450558,
|
|
591
|
+
// "E": 1766588450685,
|
|
592
|
+
// "e": "ORDER_TRADE_UPDATE",
|
|
593
|
+
// "o": {
|
|
594
|
+
// "S": "BUY",
|
|
595
|
+
// "ap": "0",
|
|
596
|
+
// "cpt": false,
|
|
597
|
+
// "ct": "future",
|
|
598
|
+
// "ev": "0",
|
|
599
|
+
// "fee": "0",
|
|
600
|
+
// "lv": 2,
|
|
601
|
+
// "mt": "isolated",
|
|
602
|
+
// "o": "7409609004526010368",
|
|
603
|
+
// "p": "1000",
|
|
604
|
+
// "ps": "BOTH",
|
|
605
|
+
// "pt": "ONE_WAY",
|
|
606
|
+
// "ro": false,
|
|
607
|
+
// "s": "ETH-USDC",
|
|
608
|
+
// "st": "NEW",
|
|
609
|
+
// "t": "LIMIT",
|
|
610
|
+
// "tp": "0",
|
|
611
|
+
// "u": "0.001",
|
|
612
|
+
// "v": "2"
|
|
613
|
+
// }
|
|
614
|
+
// }
|
|
615
|
+
//
|
|
616
|
+
const rawOrder = this.safeDict(message, 'o', {});
|
|
617
|
+
const marketId = this.safeString(rawOrder, 's');
|
|
618
|
+
const market = this.safeMarket(marketId);
|
|
619
|
+
const symbol = market['symbol'];
|
|
620
|
+
let match = false;
|
|
621
|
+
const messageHash = 'orders';
|
|
622
|
+
const symbolMessageHash = messageHash + '::' + symbol;
|
|
623
|
+
const messageHashes = this.findMessageHashes(client, messageHash);
|
|
624
|
+
for (let i = 0; i < messageHashes.length; i++) {
|
|
625
|
+
const hash = messageHashes[i];
|
|
626
|
+
if (hash === symbolMessageHash || hash === messageHash) {
|
|
627
|
+
match = true;
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if (match) {
|
|
632
|
+
if (this.orders === undefined) {
|
|
633
|
+
const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
|
|
634
|
+
this.orders = new Cache.ArrayCacheBySymbolById(limit);
|
|
635
|
+
}
|
|
636
|
+
const orders = this.orders;
|
|
637
|
+
const order = this.parseWsOrder(rawOrder, market);
|
|
638
|
+
const lastUpdateTimestamp = this.safeInteger(message, 'T');
|
|
639
|
+
order['lastUpdateTimestamp'] = lastUpdateTimestamp;
|
|
640
|
+
orders.append(order);
|
|
641
|
+
client.resolve(orders, messageHash);
|
|
642
|
+
client.resolve(orders, symbolMessageHash);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
parseWsOrder(order, market = undefined) {
|
|
646
|
+
//
|
|
647
|
+
// {
|
|
648
|
+
// "S": "BUY",
|
|
649
|
+
// "ap": "0",
|
|
650
|
+
// "cpt": false,
|
|
651
|
+
// "ct": "future",
|
|
652
|
+
// "ev": "0",
|
|
653
|
+
// "fee": "0",
|
|
654
|
+
// "lv": 2,
|
|
655
|
+
// "mt": "isolated",
|
|
656
|
+
// "o": "7409609004526010368",
|
|
657
|
+
// "p": "1000",
|
|
658
|
+
// "ps": "BOTH",
|
|
659
|
+
// "pt": "ONE_WAY",
|
|
660
|
+
// "ro": false,
|
|
661
|
+
// "s": "ETH-USDC",
|
|
662
|
+
// "st": "NEW",
|
|
663
|
+
// "t": "LIMIT",
|
|
664
|
+
// "tp": "0",
|
|
665
|
+
// "u": "0.001",
|
|
666
|
+
// "v": "2"
|
|
667
|
+
// }
|
|
668
|
+
//
|
|
669
|
+
const marketId = this.safeString(order, 's');
|
|
670
|
+
market = this.safeMarket(marketId, market);
|
|
671
|
+
const rawStatus = this.safeString(order, 'st');
|
|
672
|
+
const rawType = this.safeString(order, 't');
|
|
673
|
+
let fee = undefined;
|
|
674
|
+
const feeCost = this.safeString(order, 'fee');
|
|
675
|
+
if (feeCost !== undefined) {
|
|
676
|
+
fee = {
|
|
677
|
+
'cost': Precise["default"].stringAbs(feeCost),
|
|
678
|
+
'currency': market['quote'],
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
return this.safeOrder({
|
|
682
|
+
'info': order,
|
|
683
|
+
'id': this.safeString(order, 'o'),
|
|
684
|
+
'clientOrderId': this.safeString(order, 'cid'),
|
|
685
|
+
'timestamp': undefined,
|
|
686
|
+
'datetime': undefined,
|
|
687
|
+
'lastTradeTimestamp': undefined,
|
|
688
|
+
'lastUpdateTimestamp': undefined,
|
|
689
|
+
'status': this.parseOrderStatus(rawStatus),
|
|
690
|
+
'symbol': market['symbol'],
|
|
691
|
+
'type': this.parseOrderType(rawType),
|
|
692
|
+
'timeInForce': undefined,
|
|
693
|
+
'postOnly': undefined,
|
|
694
|
+
'reduceOnly': this.safeBool(order, 'ro'),
|
|
695
|
+
'side': this.safeStringLower(order, 'S'),
|
|
696
|
+
'price': this.safeString(order, 'p'),
|
|
697
|
+
'triggerPrice': undefined,
|
|
698
|
+
'stopLossPrice': undefined,
|
|
699
|
+
'takeProfitPrice': undefined,
|
|
700
|
+
'amount': this.safeString(order, 'v'),
|
|
701
|
+
'filled': this.safeString(order, 'ev'),
|
|
702
|
+
'remaining': this.safeString(order, 'qty'),
|
|
703
|
+
'cost': undefined,
|
|
704
|
+
'trades': undefined,
|
|
705
|
+
'fee': fee,
|
|
706
|
+
'average': this.omitZero(this.safeString(order, 'ap')),
|
|
707
|
+
}, market);
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* @method
|
|
711
|
+
* @name bydfi#watchPositions
|
|
712
|
+
* @description watch all open positions
|
|
713
|
+
* @see https://developers.bydfi.com/en/swap/websocket-account#balance-and-position-update-push
|
|
714
|
+
* @param {string[]} [symbols] list of unified market symbols
|
|
715
|
+
* @param {int} [since] the earliest time in ms to fetch positions for
|
|
716
|
+
* @param {int} [limit] the maximum number of positions to retrieve
|
|
717
|
+
* @param {object} params extra parameters specific to the exchange API endpoint
|
|
718
|
+
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
|
|
719
|
+
*/
|
|
720
|
+
async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
|
|
721
|
+
await this.loadMarkets();
|
|
722
|
+
symbols = this.marketSymbols(symbols, undefined, true);
|
|
723
|
+
const messageHashes = [];
|
|
724
|
+
const messageHash = 'positions';
|
|
725
|
+
if (symbols === undefined) {
|
|
726
|
+
messageHashes.push(messageHash);
|
|
727
|
+
}
|
|
728
|
+
else {
|
|
729
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
730
|
+
const symbol = symbols[i];
|
|
731
|
+
messageHashes.push(messageHash + '::' + symbol);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
const positions = await this.watchPrivate(messageHashes, params);
|
|
735
|
+
if (this.newUpdates) {
|
|
736
|
+
return positions;
|
|
737
|
+
}
|
|
738
|
+
return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
|
|
739
|
+
}
|
|
740
|
+
handlePositions(client, message) {
|
|
741
|
+
//
|
|
742
|
+
// {
|
|
743
|
+
// "a": {
|
|
744
|
+
// "B": [
|
|
745
|
+
// {
|
|
746
|
+
// "a": "USDC",
|
|
747
|
+
// "ba": "0",
|
|
748
|
+
// "im": "1.46282986",
|
|
749
|
+
// "om": "0",
|
|
750
|
+
// "tfm": "1.46282986",
|
|
751
|
+
// "wb": "109.86879703"
|
|
752
|
+
// }
|
|
753
|
+
// ],
|
|
754
|
+
// "m": "ORDER",
|
|
755
|
+
// "p": [
|
|
756
|
+
// {
|
|
757
|
+
// "S": "1",
|
|
758
|
+
// "ap": "2925.81666667",
|
|
759
|
+
// "c": "USDC",
|
|
760
|
+
// "ct": "FUTURE",
|
|
761
|
+
// "l": 2,
|
|
762
|
+
// "lq": "1471.1840621072728637",
|
|
763
|
+
// "lv": "0",
|
|
764
|
+
// "ma": "0",
|
|
765
|
+
// "mt": "ISOLATED",
|
|
766
|
+
// "pm": "1.4628298566666665",
|
|
767
|
+
// "pt": "ONEWAY",
|
|
768
|
+
// "rp": "-0.00036721",
|
|
769
|
+
// "s": "ETH-USDC",
|
|
770
|
+
// "t": "0",
|
|
771
|
+
// "uq": "0.001",
|
|
772
|
+
// "v": "1"
|
|
773
|
+
// }
|
|
774
|
+
// ]
|
|
775
|
+
// },
|
|
776
|
+
// "T": 1766592694451,
|
|
777
|
+
// "E": 1766592694554,
|
|
778
|
+
// "e": "ACCOUNT_UPDATE"
|
|
779
|
+
// }
|
|
780
|
+
//
|
|
781
|
+
const data = this.safeDict(message, 'a', {});
|
|
782
|
+
const positionsData = this.safeList(data, 'p', []);
|
|
783
|
+
const rawPosition = this.safeDict(positionsData, 0, {});
|
|
784
|
+
const marketId = this.safeString(rawPosition, 's');
|
|
785
|
+
const market = this.safeMarket(marketId);
|
|
786
|
+
const symbol = market['symbol'];
|
|
787
|
+
const messageHash = 'positions';
|
|
788
|
+
const symbolMessageHash = messageHash + '::' + symbol;
|
|
789
|
+
const messageHashes = this.findMessageHashes(client, messageHash);
|
|
790
|
+
let match = false;
|
|
791
|
+
for (let i = 0; i < messageHashes.length; i++) {
|
|
792
|
+
const hash = messageHashes[i];
|
|
793
|
+
if (hash === symbolMessageHash || hash === messageHash) {
|
|
794
|
+
match = true;
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
if (match) {
|
|
799
|
+
if (this.positions === undefined) {
|
|
800
|
+
this.positions = new Cache.ArrayCacheBySymbolBySide();
|
|
801
|
+
}
|
|
802
|
+
const cache = this.positions;
|
|
803
|
+
const parsedPosition = this.parseWsPosition(rawPosition, market);
|
|
804
|
+
const timestamp = this.safeInteger(message, 'T');
|
|
805
|
+
parsedPosition['timestamp'] = timestamp;
|
|
806
|
+
parsedPosition['datetime'] = this.iso8601(timestamp);
|
|
807
|
+
cache.append(parsedPosition);
|
|
808
|
+
const symbolSpecificMessageHash = messageHash + ':' + parsedPosition['symbol'];
|
|
809
|
+
client.resolve([parsedPosition], messageHash);
|
|
810
|
+
client.resolve([parsedPosition], symbolSpecificMessageHash);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
parseWsPosition(position, market = undefined) {
|
|
814
|
+
//
|
|
815
|
+
// {
|
|
816
|
+
// "S": "1",
|
|
817
|
+
// "ap": "2925.81666667",
|
|
818
|
+
// "c": "USDC",
|
|
819
|
+
// "ct": "FUTURE",
|
|
820
|
+
// "l": 2,
|
|
821
|
+
// "lq": "1471.1840621072728637",
|
|
822
|
+
// "lv": "0",
|
|
823
|
+
// "ma": "0",
|
|
824
|
+
// "mt": "ISOLATED",
|
|
825
|
+
// "pm": "1.4628298566666665",
|
|
826
|
+
// "pt": "ONEWAY",
|
|
827
|
+
// "rp": "-0.00036721",
|
|
828
|
+
// "s": "ETH-USDC",
|
|
829
|
+
// "t": "0",
|
|
830
|
+
// "uq": "0.001",
|
|
831
|
+
// "v": "1"
|
|
832
|
+
// }
|
|
833
|
+
//
|
|
834
|
+
const marketId = this.safeString(position, 's');
|
|
835
|
+
market = this.safeMarket(marketId, market);
|
|
836
|
+
const rawPositionSide = this.safeString(position, 'S');
|
|
837
|
+
const positionMode = this.safeString(position, 'pt');
|
|
838
|
+
return this.safePosition({
|
|
839
|
+
'info': position,
|
|
840
|
+
'id': this.safeString(position, 'id'),
|
|
841
|
+
'symbol': market['symbol'],
|
|
842
|
+
'entryPrice': this.parseNumber(this.safeString(position, 'ap')),
|
|
843
|
+
'markPrice': undefined,
|
|
844
|
+
'lastPrice': undefined,
|
|
845
|
+
'notional': undefined,
|
|
846
|
+
'collateral': undefined,
|
|
847
|
+
'unrealizedPnl': undefined,
|
|
848
|
+
'realizedPnl': this.parseNumber(this.safeString(position, 'rp')),
|
|
849
|
+
'side': this.parseWsPositionSide(rawPositionSide),
|
|
850
|
+
'contracts': this.parseNumber(this.safeString(position, 'v')),
|
|
851
|
+
'contractSize': this.parseNumber(this.safeString(position, 'uq')),
|
|
852
|
+
'timestamp': undefined,
|
|
853
|
+
'datetime': undefined,
|
|
854
|
+
'lastUpdateTimestamp': undefined,
|
|
855
|
+
'hedged': (positionMode !== 'ONEWAY'),
|
|
856
|
+
'maintenanceMargin': undefined,
|
|
857
|
+
'maintenanceMarginPercentage': undefined,
|
|
858
|
+
'initialMargin': this.parseNumber(this.safeString(position, 'pm')),
|
|
859
|
+
'initialMarginPercentage': undefined,
|
|
860
|
+
'leverage': this.safeInteger(position, 'l'),
|
|
861
|
+
'liquidationPrice': this.parseNumber(this.safeString(position, 'lq')),
|
|
862
|
+
'marginRatio': undefined,
|
|
863
|
+
'marginMode': this.safeStringLower(position, 'mt'),
|
|
864
|
+
'percentage': undefined,
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
parseWsPositionSide(rawPositionSide) {
|
|
868
|
+
const sides = {
|
|
869
|
+
'1': 'long',
|
|
870
|
+
'2': 'short',
|
|
871
|
+
};
|
|
872
|
+
return this.safeString(sides, rawPositionSide, rawPositionSide);
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* @method
|
|
876
|
+
* @name bydfi#watchBalance
|
|
877
|
+
* @description watch balance and get the amount of funds available for trading or funds locked in orders
|
|
878
|
+
* @see https://developers.bydfi.com/en/swap/websocket-account#balance-and-position-update-push
|
|
879
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
880
|
+
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
|
|
881
|
+
*/
|
|
882
|
+
async watchBalance(params = {}) {
|
|
883
|
+
await this.loadMarkets();
|
|
884
|
+
const url = this.urls['api']['ws'];
|
|
885
|
+
const client = this.client(url);
|
|
886
|
+
this.fetchBalanceSnapshot(client);
|
|
887
|
+
const options = this.safeDict(this.options, 'watchBalance');
|
|
888
|
+
const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
|
|
889
|
+
const awaitBalanceSnapshot = this.safeBool(options, 'awaitBalanceSnapshot', true);
|
|
890
|
+
if (fetchBalanceSnapshot && awaitBalanceSnapshot) {
|
|
891
|
+
await client.future('fetchBalanceSnapshot');
|
|
892
|
+
}
|
|
893
|
+
const messageHash = 'balance';
|
|
894
|
+
return await this.watchPrivate([messageHash], params);
|
|
895
|
+
}
|
|
896
|
+
fetchBalanceSnapshot(client) {
|
|
897
|
+
const options = this.safeValue(this.options, 'watchBalance');
|
|
898
|
+
const fetchBalanceSnapshot = this.safeBool(options, 'fetchBalanceSnapshot', false);
|
|
899
|
+
if (fetchBalanceSnapshot) {
|
|
900
|
+
const messageHash = 'fetchBalanceSnapshot';
|
|
901
|
+
if (!(messageHash in client.futures)) {
|
|
902
|
+
client.future(messageHash);
|
|
903
|
+
this.spawn(this.loadBalanceSnapshot, client, messageHash);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
async loadBalanceSnapshot(client, messageHash) {
|
|
908
|
+
const params = {
|
|
909
|
+
'type': 'swap',
|
|
910
|
+
};
|
|
911
|
+
const response = await this.fetchBalance(params);
|
|
912
|
+
this.balance = this.extend(response, this.balance);
|
|
913
|
+
// don't remove the future from the .futures cache
|
|
914
|
+
const future = client.futures[messageHash];
|
|
915
|
+
future.resolve();
|
|
916
|
+
client.resolve(this.balance, 'balance');
|
|
917
|
+
}
|
|
918
|
+
handleBalance(client, message) {
|
|
919
|
+
//
|
|
920
|
+
// {
|
|
921
|
+
// "a": {
|
|
922
|
+
// "B": [
|
|
923
|
+
// {
|
|
924
|
+
// "a": "USDC",
|
|
925
|
+
// "ba": "0",
|
|
926
|
+
// "im": "1.46282986",
|
|
927
|
+
// "om": "0",
|
|
928
|
+
// "tfm": "1.46282986",
|
|
929
|
+
// "wb": "109.86879703"
|
|
930
|
+
// }
|
|
931
|
+
// ],
|
|
932
|
+
// "m": "ORDER",
|
|
933
|
+
// "p": [
|
|
934
|
+
// {
|
|
935
|
+
// "S": "1",
|
|
936
|
+
// "ap": "2925.81666667",
|
|
937
|
+
// "c": "USDC",
|
|
938
|
+
// "ct": "FUTURE",
|
|
939
|
+
// "l": 2,
|
|
940
|
+
// "lq": "1471.1840621072728637",
|
|
941
|
+
// "lv": "0",
|
|
942
|
+
// "ma": "0",
|
|
943
|
+
// "mt": "ISOLATED",
|
|
944
|
+
// "pm": "1.4628298566666665",
|
|
945
|
+
// "pt": "ONEWAY",
|
|
946
|
+
// "rp": "-0.00036721",
|
|
947
|
+
// "s": "ETH-USDC",
|
|
948
|
+
// "t": "0",
|
|
949
|
+
// "uq": "0.001",
|
|
950
|
+
// "v": "1"
|
|
951
|
+
// }
|
|
952
|
+
// ]
|
|
953
|
+
// },
|
|
954
|
+
// "T": 1766592694451,
|
|
955
|
+
// "E": 1766592694554,
|
|
956
|
+
// "e": "ACCOUNT_UPDATE"
|
|
957
|
+
// }
|
|
958
|
+
//
|
|
959
|
+
const messageHash = 'balance';
|
|
960
|
+
if (messageHash in client.futures) {
|
|
961
|
+
const data = this.safeDict(message, 'a', {});
|
|
962
|
+
const balances = this.safeList(data, 'B', []);
|
|
963
|
+
const timestamp = this.safeInteger(message, 'T');
|
|
964
|
+
const result = {
|
|
965
|
+
'info': message,
|
|
966
|
+
'timestamp': timestamp,
|
|
967
|
+
'datetime': this.iso8601(timestamp),
|
|
968
|
+
};
|
|
969
|
+
for (let i = 0; i < balances.length; i++) {
|
|
970
|
+
const balance = balances[i];
|
|
971
|
+
const currencyId = this.safeString(balance, 'a');
|
|
972
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
973
|
+
const account = this.account();
|
|
974
|
+
account['total'] = this.safeString(balance, 'wb');
|
|
975
|
+
account['used'] = this.safeString(balance, 'tfm');
|
|
976
|
+
result[code] = account;
|
|
977
|
+
}
|
|
978
|
+
const parsedBalance = this.safeBalance(result);
|
|
979
|
+
this.balance = this.extend(this.balance, parsedBalance);
|
|
980
|
+
client.resolve(this.balance, messageHash);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
handleSubscriptionStatus(client, message) {
|
|
984
|
+
//
|
|
985
|
+
// {
|
|
986
|
+
// "result": true,
|
|
987
|
+
// "id": 1
|
|
988
|
+
// }
|
|
989
|
+
//
|
|
990
|
+
const id = this.safeString(message, 'id');
|
|
991
|
+
const subscriptionsById = this.indexBy(client.subscriptions, 'id');
|
|
992
|
+
const subscription = this.safeDict(subscriptionsById, id, {});
|
|
993
|
+
const isUnSubMessage = this.safeBool(subscription, 'unsubscribe', false);
|
|
994
|
+
if (isUnSubMessage) {
|
|
995
|
+
this.handleUnSubscription(client, subscription);
|
|
996
|
+
}
|
|
997
|
+
return message;
|
|
998
|
+
}
|
|
999
|
+
handleUnSubscription(client, subscription) {
|
|
1000
|
+
const messageHashes = this.safeList(subscription, 'messageHashes', []);
|
|
1001
|
+
const subHashIsPrefix = this.safeBool(subscription, 'subHashIsPrefix', false);
|
|
1002
|
+
for (let i = 0; i < messageHashes.length; i++) {
|
|
1003
|
+
const unsubHash = messageHashes[i];
|
|
1004
|
+
const subHash = unsubHash.replace('unsubscribe::', '');
|
|
1005
|
+
this.cleanUnsubscription(client, subHash, unsubHash, subHashIsPrefix);
|
|
1006
|
+
}
|
|
1007
|
+
this.cleanCache(subscription);
|
|
1008
|
+
}
|
|
1009
|
+
handlePong(client, message) {
|
|
1010
|
+
//
|
|
1011
|
+
// {
|
|
1012
|
+
// "id": 1,
|
|
1013
|
+
// "result": "pong"
|
|
1014
|
+
// }
|
|
1015
|
+
//
|
|
1016
|
+
client.lastPong = this.milliseconds();
|
|
1017
|
+
return message;
|
|
1018
|
+
}
|
|
1019
|
+
handleErrorMessage(client, message) {
|
|
1020
|
+
//
|
|
1021
|
+
// {
|
|
1022
|
+
// "msg": "Service error",
|
|
1023
|
+
// "code": "-1"
|
|
1024
|
+
// }
|
|
1025
|
+
//
|
|
1026
|
+
const code = this.safeString(message, 'code');
|
|
1027
|
+
const msg = this.safeString(message, 'msg');
|
|
1028
|
+
const feedback = this.id + ' ' + this.json(message);
|
|
1029
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], msg, feedback);
|
|
1030
|
+
this.throwBroadlyMatchedException(this.exceptions['broad'], msg, feedback);
|
|
1031
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
|
|
1032
|
+
throw new errors.ExchangeError(feedback);
|
|
1033
|
+
}
|
|
1034
|
+
handleMessage(client, message) {
|
|
1035
|
+
const code = this.safeString(message, 'code');
|
|
1036
|
+
if (code !== undefined && (code !== '0')) {
|
|
1037
|
+
this.handleErrorMessage(client, message);
|
|
1038
|
+
}
|
|
1039
|
+
const result = this.safeString(message, 'result');
|
|
1040
|
+
if (result === 'pong') {
|
|
1041
|
+
this.handlePong(client, message);
|
|
1042
|
+
}
|
|
1043
|
+
else if (result !== undefined) {
|
|
1044
|
+
this.handleSubscriptionStatus(client, message);
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
const event = this.safeString(message, 'e');
|
|
1048
|
+
if (event === '24hrTicker') {
|
|
1049
|
+
this.handleTicker(client, message);
|
|
1050
|
+
}
|
|
1051
|
+
else if (event === 'kline') {
|
|
1052
|
+
this.handleOHLCV(client, message);
|
|
1053
|
+
}
|
|
1054
|
+
else if (event === 'depthUpdate') {
|
|
1055
|
+
this.handleOrderBook(client, message);
|
|
1056
|
+
}
|
|
1057
|
+
else if (event === 'ORDER_TRADE_UPDATE') {
|
|
1058
|
+
this.handleOrder(client, message);
|
|
1059
|
+
}
|
|
1060
|
+
else if (event === 'ACCOUNT_UPDATE') {
|
|
1061
|
+
const account = this.safeDict(message, 'a', {});
|
|
1062
|
+
const balances = this.safeList(account, 'B', []);
|
|
1063
|
+
const balancesLength = balances.length;
|
|
1064
|
+
if (balancesLength > 0) {
|
|
1065
|
+
this.handleBalance(client, message);
|
|
1066
|
+
}
|
|
1067
|
+
const positions = this.safeList(account, 'p', []);
|
|
1068
|
+
const positionsLength = positions.length;
|
|
1069
|
+
if (positionsLength > 0) {
|
|
1070
|
+
this.handlePositions(client, message);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
exports["default"] = bydfi;
|