ccxt 4.5.17 → 4.5.18
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 +8 -5
- package/dist/ccxt.browser.min.js +2 -2
- package/dist/cjs/ccxt.js +6 -1
- package/dist/cjs/src/abstract/deepcoin.js +11 -0
- package/dist/cjs/src/apex.js +33 -15
- package/dist/cjs/src/base/Exchange.js +3 -3
- package/dist/cjs/src/base/ws/Client.js +8 -7
- package/dist/cjs/src/bigone.js +20 -0
- package/dist/cjs/src/binanceus.js +31 -1
- package/dist/cjs/src/blofin.js +4 -1
- package/dist/cjs/src/bybit.js +3 -0
- package/dist/cjs/src/deepcoin.js +3024 -0
- package/dist/cjs/src/pro/ascendex.js +2 -2
- package/dist/cjs/src/pro/binance.js +100 -3
- package/dist/cjs/src/pro/binanceus.js +19 -0
- package/dist/cjs/src/pro/blofin.js +11 -2
- package/dist/cjs/src/pro/deepcoin.js +1225 -0
- package/dist/cjs/src/pro/kraken.js +5 -1
- package/js/ccxt.d.ts +8 -2
- package/js/ccxt.js +6 -2
- package/js/src/abstract/bybit.d.ts +3 -0
- package/js/src/abstract/deepcoin.d.ts +60 -0
- package/js/src/abstract/deepcoin.js +11 -0
- package/js/src/apex.d.ts +2 -0
- package/js/src/apex.js +33 -15
- package/js/src/base/Exchange.js +3 -3
- package/js/src/base/ws/Client.js +8 -7
- package/js/src/bigone.js +20 -0
- package/js/src/binanceus.js +31 -1
- package/js/src/blofin.js +4 -1
- package/js/src/bybit.js +3 -0
- package/js/src/deepcoin.d.ts +498 -0
- package/js/src/deepcoin.js +3022 -0
- package/js/src/pro/ascendex.d.ts +1 -1
- package/js/src/pro/ascendex.js +2 -2
- package/js/src/pro/binance.d.ts +35 -1
- package/js/src/pro/binance.js +97 -3
- package/js/src/pro/binanceus.js +19 -0
- package/js/src/pro/blofin.d.ts +5 -0
- package/js/src/pro/blofin.js +11 -2
- package/js/src/pro/deepcoin.d.ts +169 -0
- package/js/src/pro/deepcoin.js +1224 -0
- package/js/src/pro/kraken.js +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,1224 @@
|
|
|
1
|
+
// ----------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
|
4
|
+
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
|
5
|
+
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
|
|
6
|
+
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
import deepcoinRest from '../deepcoin.js';
|
|
9
|
+
import { BadRequest, ExchangeError } from '../base/errors.js';
|
|
10
|
+
import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
export default class deepcoin extends deepcoinRest {
|
|
13
|
+
describe() {
|
|
14
|
+
return this.deepExtend(super.describe(), {
|
|
15
|
+
'has': {
|
|
16
|
+
'ws': true,
|
|
17
|
+
'watchTicker': true,
|
|
18
|
+
'watchMarkPrice': false,
|
|
19
|
+
'watchMarkPrices': false,
|
|
20
|
+
'watchTickers': false,
|
|
21
|
+
'watchBidsAsks': false,
|
|
22
|
+
'watchOrderBook': true,
|
|
23
|
+
'watchTrades': true,
|
|
24
|
+
'watchTradesForSymbols': false,
|
|
25
|
+
'watchOrderBookForSymbols': false,
|
|
26
|
+
'watchBalance': false,
|
|
27
|
+
'watchLiquidations': false,
|
|
28
|
+
'watchLiquidationsForSymbols': false,
|
|
29
|
+
'watchMyLiquidations': false,
|
|
30
|
+
'watchMyLiquidationsForSymbols': false,
|
|
31
|
+
'watchOHLCV': true,
|
|
32
|
+
'watchOHLCVForSymbols': false,
|
|
33
|
+
'watchOrders': true,
|
|
34
|
+
'watchMyTrades': true,
|
|
35
|
+
'watchPositions': true,
|
|
36
|
+
'watchFundingRate': false,
|
|
37
|
+
'watchFundingRates': false,
|
|
38
|
+
'createOrderWs': false,
|
|
39
|
+
'editOrderWs': false,
|
|
40
|
+
'cancelOrderWs': false,
|
|
41
|
+
'cancelOrdersWs': false,
|
|
42
|
+
'cancelAllOrdersWs': false,
|
|
43
|
+
'unWatchTicker': true,
|
|
44
|
+
'unWatchTrades': true,
|
|
45
|
+
'unWatchOHLCV': true,
|
|
46
|
+
'unWatchOrderBook': true,
|
|
47
|
+
},
|
|
48
|
+
'urls': {
|
|
49
|
+
'api': {
|
|
50
|
+
'ws': {
|
|
51
|
+
'public': {
|
|
52
|
+
'spot': 'wss://stream.deepcoin.com/streamlet/trade/public/spot?platform=api',
|
|
53
|
+
'swap': 'wss://stream.deepcoin.com/streamlet/trade/public/swap?platform=api',
|
|
54
|
+
},
|
|
55
|
+
'private': 'wss://stream.deepcoin.com/v1/private',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
'options': {
|
|
60
|
+
'lastRequestId': undefined,
|
|
61
|
+
'listenKey': undefined,
|
|
62
|
+
'listenKeyExpiryTimestamp': undefined,
|
|
63
|
+
'authenticate': {
|
|
64
|
+
'method': 'privateGetDeepcoinListenkeyExtend', // refresh existing listen key or 'privateGetDeepcoinListenkeyAcquire' - get a new one
|
|
65
|
+
},
|
|
66
|
+
'timeframes': {
|
|
67
|
+
'1m': '1m',
|
|
68
|
+
'5m': '5m',
|
|
69
|
+
'15m': '15m',
|
|
70
|
+
'30m': '30m',
|
|
71
|
+
'1h': '1h',
|
|
72
|
+
'4h': '4h',
|
|
73
|
+
'12h': '12h',
|
|
74
|
+
'1d': '1d',
|
|
75
|
+
'1w': '1w',
|
|
76
|
+
'1M': '1o',
|
|
77
|
+
'1y': '1y',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
'streaming': {
|
|
81
|
+
'ping': this.ping,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
ping(client) {
|
|
86
|
+
const url = client.url;
|
|
87
|
+
if (url.indexOf('private') >= 0) {
|
|
88
|
+
client.lastPong = this.milliseconds();
|
|
89
|
+
// prevent automatic disconnects on private channel
|
|
90
|
+
}
|
|
91
|
+
return 'ping';
|
|
92
|
+
}
|
|
93
|
+
handlePong(client, message) {
|
|
94
|
+
client.lastPong = this.milliseconds();
|
|
95
|
+
return message;
|
|
96
|
+
}
|
|
97
|
+
requestId() {
|
|
98
|
+
const previousValue = this.safeInteger(this.options, 'lastRequestId', 0);
|
|
99
|
+
const newValue = this.sum(previousValue, 1);
|
|
100
|
+
this.options['lastRequestId'] = newValue;
|
|
101
|
+
return newValue;
|
|
102
|
+
}
|
|
103
|
+
createPublicRequest(market, requestId, topicID, suffix = '', unWatch = false) {
|
|
104
|
+
let marketId = market['symbol']; // spot markets use symbol with slash
|
|
105
|
+
if (market['type'] === 'swap') {
|
|
106
|
+
marketId = market['baseId'] + market['quoteId']; // swap markets use symbol without slash
|
|
107
|
+
}
|
|
108
|
+
let action = '1'; // subscribe
|
|
109
|
+
if (unWatch) {
|
|
110
|
+
action = '0'; // unsubscribe
|
|
111
|
+
}
|
|
112
|
+
const request = {
|
|
113
|
+
'sendTopicAction': {
|
|
114
|
+
'Action': action,
|
|
115
|
+
'FilterValue': 'DeepCoin_' + marketId + suffix,
|
|
116
|
+
'LocalNo': requestId,
|
|
117
|
+
'ResumeNo': -1,
|
|
118
|
+
'TopicID': topicID,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
return request;
|
|
122
|
+
}
|
|
123
|
+
async watchPublic(market, messageHash, topicID, params = {}, suffix = '') {
|
|
124
|
+
const url = this.urls['api']['ws']['public'][market['type']];
|
|
125
|
+
const requestId = this.requestId();
|
|
126
|
+
const request = this.createPublicRequest(market, requestId, topicID, suffix);
|
|
127
|
+
const subscription = {
|
|
128
|
+
'subHash': messageHash,
|
|
129
|
+
'id': requestId,
|
|
130
|
+
};
|
|
131
|
+
return await this.watch(url, messageHash, this.deepExtend(request, params), messageHash, subscription);
|
|
132
|
+
}
|
|
133
|
+
async unWatchPublic(market, messageHash, topicID, params = {}, subscription = {}, suffix = '') {
|
|
134
|
+
const url = this.urls['api']['ws']['public'][market['type']];
|
|
135
|
+
const requestId = this.requestId();
|
|
136
|
+
const client = this.client(url);
|
|
137
|
+
const existingSubscription = this.safeDict(client.subscriptions, messageHash);
|
|
138
|
+
if (existingSubscription === undefined) {
|
|
139
|
+
throw new BadRequest(this.id + ' no subscription for ' + messageHash);
|
|
140
|
+
}
|
|
141
|
+
const subId = this.safeInteger(existingSubscription, 'id');
|
|
142
|
+
const request = this.createPublicRequest(market, subId, topicID, suffix, true); // unsubscribe message uses the same id as the original subscribe message
|
|
143
|
+
const unsubHash = 'unsubscribe::' + messageHash;
|
|
144
|
+
subscription = this.extend(subscription, {
|
|
145
|
+
'subHash': messageHash,
|
|
146
|
+
'unsubHash': unsubHash,
|
|
147
|
+
'symbols': [market['symbol']],
|
|
148
|
+
'id': requestId,
|
|
149
|
+
});
|
|
150
|
+
return await this.watch(url, unsubHash, this.deepExtend(request, params), unsubHash, subscription);
|
|
151
|
+
}
|
|
152
|
+
async watchPrivate(messageHash, params = {}) {
|
|
153
|
+
const listenKey = await this.authenticate();
|
|
154
|
+
const url = this.urls['api']['ws']['private'] + '?listenKey=' + listenKey;
|
|
155
|
+
return await this.watch(url, messageHash, undefined, 'private', params);
|
|
156
|
+
}
|
|
157
|
+
async authenticate(params = {}) {
|
|
158
|
+
this.checkRequiredCredentials();
|
|
159
|
+
const time = this.milliseconds();
|
|
160
|
+
let listenKeyExpiryTimestamp = this.safeInteger(this.options, 'listenKeyExpiryTimestamp', time);
|
|
161
|
+
const expired = (time - listenKeyExpiryTimestamp) > 60000; // 1 minute before expiry
|
|
162
|
+
let listenKey = this.safeString(this.options, 'listenKey');
|
|
163
|
+
let response = undefined;
|
|
164
|
+
if (listenKey === undefined) {
|
|
165
|
+
response = await this.privateGetDeepcoinListenkeyAcquire(params);
|
|
166
|
+
}
|
|
167
|
+
else if (expired) {
|
|
168
|
+
const method = this.safeString(this.options, 'method', 'privateGetDeepcoinListenkeyExtend');
|
|
169
|
+
const getNewKey = (method === 'privateGetDeepcoinListenkeyAcquire');
|
|
170
|
+
if (getNewKey) {
|
|
171
|
+
response = await this.privateGetDeepcoinListenkeyAcquire(params);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const request = {
|
|
175
|
+
'listenkey': listenKey,
|
|
176
|
+
};
|
|
177
|
+
response = await this.privateGetDeepcoinListenkeyExtend(this.extend(request, params));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (response !== undefined) {
|
|
181
|
+
const data = this.safeDict(response, 'data', {});
|
|
182
|
+
listenKey = this.safeString(data, 'listenkey');
|
|
183
|
+
listenKeyExpiryTimestamp = this.safeTimestamp(data, 'expire_time');
|
|
184
|
+
this.options['listenKey'] = listenKey;
|
|
185
|
+
this.options['listenKeyExpiryTimestamp'] = listenKeyExpiryTimestamp;
|
|
186
|
+
}
|
|
187
|
+
return listenKey;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* @method
|
|
191
|
+
* @name deepcoin#watchTicker
|
|
192
|
+
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
193
|
+
* @see https://www.deepcoin.com/docs/publicWS/latestMarketData
|
|
194
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
195
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
196
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
197
|
+
*/
|
|
198
|
+
async watchTicker(symbol, params = {}) {
|
|
199
|
+
await this.loadMarkets();
|
|
200
|
+
const market = this.market(symbol);
|
|
201
|
+
const messageHash = 'ticker' + '::' + market['symbol'];
|
|
202
|
+
return await this.watchPublic(market, messageHash, '7', params);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* @method
|
|
206
|
+
* @name deepcoin#unWatchTicker
|
|
207
|
+
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
208
|
+
* @see https://www.deepcoin.com/docs/publicWS/latestMarketData
|
|
209
|
+
* @param {string} symbol 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 unWatchTicker(symbol, params = {}) {
|
|
214
|
+
await this.loadMarkets();
|
|
215
|
+
const market = this.market(symbol);
|
|
216
|
+
const messageHash = 'ticker' + '::' + market['symbol'];
|
|
217
|
+
const subscription = {
|
|
218
|
+
'topic': 'ticker',
|
|
219
|
+
};
|
|
220
|
+
return await this.unWatchPublic(market, messageHash, '7', params, subscription);
|
|
221
|
+
}
|
|
222
|
+
handleTicker(client, message) {
|
|
223
|
+
//
|
|
224
|
+
// a: 'PO',
|
|
225
|
+
// m: 'Success',
|
|
226
|
+
// tt: 1760913034780,
|
|
227
|
+
// mt: 1760913034780,
|
|
228
|
+
// r: [
|
|
229
|
+
// {
|
|
230
|
+
// d: {
|
|
231
|
+
// I: 'BTC/USDT',
|
|
232
|
+
// U: 1760913034742,
|
|
233
|
+
// PF: 0,
|
|
234
|
+
// E: 0,
|
|
235
|
+
// O: 108479.9,
|
|
236
|
+
// H: 109449.9,
|
|
237
|
+
// L: 108238,
|
|
238
|
+
// V: 789.3424915,
|
|
239
|
+
// T: 43003872.3705223,
|
|
240
|
+
// N: 109345,
|
|
241
|
+
// M: 87294.7,
|
|
242
|
+
// D: 0,
|
|
243
|
+
// V2: 3086.4496105,
|
|
244
|
+
// T2: 332811624.339836,
|
|
245
|
+
// F: 0,
|
|
246
|
+
// C: 0,
|
|
247
|
+
// BP1: 109344.9,
|
|
248
|
+
// AP1: 109345.2
|
|
249
|
+
// }
|
|
250
|
+
// }
|
|
251
|
+
// ]
|
|
252
|
+
//
|
|
253
|
+
const response = this.safeList(message, 'r', []);
|
|
254
|
+
const first = this.safeDict(response, 0, {});
|
|
255
|
+
const data = this.safeDict(first, 'd', {});
|
|
256
|
+
const marketId = this.safeString(data, 'I');
|
|
257
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
258
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
259
|
+
const parsedTicker = this.parseWsTicker(data, market);
|
|
260
|
+
const messageHash = 'ticker' + '::' + symbol;
|
|
261
|
+
this.tickers[symbol] = parsedTicker;
|
|
262
|
+
client.resolve(parsedTicker, messageHash);
|
|
263
|
+
}
|
|
264
|
+
parseWsTicker(ticker, market = undefined) {
|
|
265
|
+
//
|
|
266
|
+
// {
|
|
267
|
+
// I: 'BTC/USDT',
|
|
268
|
+
// U: 1760913034742,
|
|
269
|
+
// PF: 0,
|
|
270
|
+
// E: 0,
|
|
271
|
+
// O: 108479.9,
|
|
272
|
+
// H: 109449.9,
|
|
273
|
+
// L: 108238,
|
|
274
|
+
// V: 789.3424915,
|
|
275
|
+
// T: 43003872.3705223,
|
|
276
|
+
// N: 109345,
|
|
277
|
+
// M: 87294.7,
|
|
278
|
+
// D: 0,
|
|
279
|
+
// V2: 3086.4496105,
|
|
280
|
+
// T2: 332811624.339836,
|
|
281
|
+
// F: 0,
|
|
282
|
+
// C: 0,
|
|
283
|
+
// BP1: 109344.9,
|
|
284
|
+
// AP1: 109345.2
|
|
285
|
+
// }
|
|
286
|
+
//
|
|
287
|
+
const timestamp = this.safeInteger(ticker, 'U');
|
|
288
|
+
const high = this.safeNumber(ticker, 'H');
|
|
289
|
+
const low = this.safeNumber(ticker, 'L');
|
|
290
|
+
const open = this.safeNumber(ticker, 'O');
|
|
291
|
+
const last = this.safeNumber(ticker, 'N');
|
|
292
|
+
const bid = this.safeNumber(ticker, 'BP1');
|
|
293
|
+
const ask = this.safeNumber(ticker, 'AP1');
|
|
294
|
+
let baseVolume = this.safeNumber(ticker, 'V');
|
|
295
|
+
let quoteVolume = this.safeNumber(ticker, 'T');
|
|
296
|
+
if (market['inverse']) {
|
|
297
|
+
const temp = baseVolume;
|
|
298
|
+
baseVolume = quoteVolume;
|
|
299
|
+
quoteVolume = temp;
|
|
300
|
+
}
|
|
301
|
+
return this.safeTicker({
|
|
302
|
+
'symbol': market['symbol'],
|
|
303
|
+
'timestamp': timestamp,
|
|
304
|
+
'datetime': this.iso8601(timestamp),
|
|
305
|
+
'high': high,
|
|
306
|
+
'low': low,
|
|
307
|
+
'bid': bid,
|
|
308
|
+
'bidVolume': undefined,
|
|
309
|
+
'ask': ask,
|
|
310
|
+
'askVolume': undefined,
|
|
311
|
+
'vwap': undefined,
|
|
312
|
+
'open': open,
|
|
313
|
+
'close': last,
|
|
314
|
+
'last': last,
|
|
315
|
+
'previousClose': undefined,
|
|
316
|
+
'change': undefined,
|
|
317
|
+
'percentage': undefined,
|
|
318
|
+
'average': undefined,
|
|
319
|
+
'baseVolume': baseVolume,
|
|
320
|
+
'quoteVolume': quoteVolume,
|
|
321
|
+
'info': ticker,
|
|
322
|
+
}, market);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* @method
|
|
326
|
+
* @name deepcoin#watchTrades
|
|
327
|
+
* @description watches information on multiple trades made in a market
|
|
328
|
+
* @see https://www.deepcoin.com/docs/publicWS/lastTransactions
|
|
329
|
+
* @param {string} symbol unified market symbol of the market trades were made in
|
|
330
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
331
|
+
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
332
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
333
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
334
|
+
*/
|
|
335
|
+
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
336
|
+
await this.loadMarkets();
|
|
337
|
+
const market = this.market(symbol);
|
|
338
|
+
const messageHash = 'trades' + '::' + market['symbol'];
|
|
339
|
+
const trades = await this.watchPublic(market, messageHash, '2', params);
|
|
340
|
+
if (this.newUpdates) {
|
|
341
|
+
limit = trades.getLimit(symbol, limit);
|
|
342
|
+
}
|
|
343
|
+
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* @method
|
|
347
|
+
* @name deepcoin#unWatchTrades
|
|
348
|
+
* @description unWatches the list of most recent trades for a particular symbol
|
|
349
|
+
* @see https://www.deepcoin.com/docs/publicWS/lastTransactions
|
|
350
|
+
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
351
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
352
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
353
|
+
*/
|
|
354
|
+
async unWatchTrades(symbol, params = {}) {
|
|
355
|
+
await this.loadMarkets();
|
|
356
|
+
const market = this.market(symbol);
|
|
357
|
+
const messageHash = 'trades' + '::' + market['symbol'];
|
|
358
|
+
const subscription = {
|
|
359
|
+
'topic': 'trades',
|
|
360
|
+
};
|
|
361
|
+
return await this.unWatchPublic(market, messageHash, '2', params, subscription);
|
|
362
|
+
}
|
|
363
|
+
handleTrades(client, message) {
|
|
364
|
+
//
|
|
365
|
+
// {
|
|
366
|
+
// "a": "PMT",
|
|
367
|
+
// "b": 0,
|
|
368
|
+
// "tt": 1760968672380,
|
|
369
|
+
// "mt": 1760968672380,
|
|
370
|
+
// "r": [
|
|
371
|
+
// {
|
|
372
|
+
// "d": {
|
|
373
|
+
// "TradeID": "1001056452325378",
|
|
374
|
+
// "I": "BTC/USDT",
|
|
375
|
+
// "D": "1",
|
|
376
|
+
// "P": 111061,
|
|
377
|
+
// "V": 0.00137,
|
|
378
|
+
// "T": 1760968672
|
|
379
|
+
// }
|
|
380
|
+
// }
|
|
381
|
+
// ]
|
|
382
|
+
// }
|
|
383
|
+
//
|
|
384
|
+
const response = this.safeList(message, 'r', []);
|
|
385
|
+
const first = this.safeDict(response, 0, {});
|
|
386
|
+
const data = this.safeDict(first, 'd', {});
|
|
387
|
+
const marketId = this.safeString(data, 'I');
|
|
388
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
389
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
390
|
+
if (!(symbol in this.trades)) {
|
|
391
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
392
|
+
this.trades[symbol] = new ArrayCache(limit);
|
|
393
|
+
}
|
|
394
|
+
const strored = this.trades[symbol];
|
|
395
|
+
if (data !== undefined) {
|
|
396
|
+
const trade = this.parseWsTrade(data, market);
|
|
397
|
+
strored.append(trade);
|
|
398
|
+
}
|
|
399
|
+
const messageHash = 'trades' + '::' + symbol;
|
|
400
|
+
client.resolve(strored, messageHash);
|
|
401
|
+
}
|
|
402
|
+
parseWsTrade(trade, market = undefined) {
|
|
403
|
+
//
|
|
404
|
+
// watchTrades
|
|
405
|
+
// {
|
|
406
|
+
// "TradeID": "1001056452325378",
|
|
407
|
+
// "I": "BTC/USDT",
|
|
408
|
+
// "D": "1",
|
|
409
|
+
// "P": 111061,
|
|
410
|
+
// "V": 0.00137,
|
|
411
|
+
// "T": 1760968672
|
|
412
|
+
// }
|
|
413
|
+
//
|
|
414
|
+
// watchMyTrades
|
|
415
|
+
// {
|
|
416
|
+
// "A": "9256245",
|
|
417
|
+
// "CC": "USDT",
|
|
418
|
+
// "CP": 0,
|
|
419
|
+
// "D": "0",
|
|
420
|
+
// "F": 0.152,
|
|
421
|
+
// "I": "DOGE/USDT",
|
|
422
|
+
// "IT": 1761048103,
|
|
423
|
+
// "M": "9256245",
|
|
424
|
+
// "OS": "1001437462198486",
|
|
425
|
+
// "P": 0.19443,
|
|
426
|
+
// "T": 14.77668,
|
|
427
|
+
// "TI": "1001056459096708",
|
|
428
|
+
// "TT": 1761048103,
|
|
429
|
+
// "V": 76,
|
|
430
|
+
// "f": "DOGE",
|
|
431
|
+
// "l": 1,
|
|
432
|
+
// "m": "1",
|
|
433
|
+
// "o": "0"
|
|
434
|
+
// }
|
|
435
|
+
//
|
|
436
|
+
const direction = this.safeString(trade, 'D');
|
|
437
|
+
const timestamp = this.safeTimestamp2(trade, 'TT', 'T');
|
|
438
|
+
const matchRole = this.safeString(trade, 'm');
|
|
439
|
+
let fee = undefined;
|
|
440
|
+
const feeCost = this.safeString(trade, 'F');
|
|
441
|
+
if (feeCost !== undefined) {
|
|
442
|
+
fee = {
|
|
443
|
+
'cost': feeCost,
|
|
444
|
+
'currency': this.safeCurrencyCode(this.safeString(trade, 'f')),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
return this.safeTrade({
|
|
448
|
+
'info': trade,
|
|
449
|
+
'timestamp': timestamp,
|
|
450
|
+
'datetime': this.iso8601(timestamp),
|
|
451
|
+
'symbol': market['symbol'],
|
|
452
|
+
'id': this.safeString2(trade, 'TradeID', 'TI'),
|
|
453
|
+
'order': this.safeString(trade, 'OS'),
|
|
454
|
+
'type': undefined,
|
|
455
|
+
'takerOrMaker': this.handleTakerOrMaker(matchRole),
|
|
456
|
+
'side': this.parseTradeSide(direction),
|
|
457
|
+
'price': this.safeString(trade, 'P'),
|
|
458
|
+
'amount': this.safeString(trade, 'V'),
|
|
459
|
+
'cost': this.safeString(trade, 'T'),
|
|
460
|
+
'fee': fee,
|
|
461
|
+
}, market);
|
|
462
|
+
}
|
|
463
|
+
parseTradeSide(direction) {
|
|
464
|
+
const sides = {
|
|
465
|
+
'0': 'buy',
|
|
466
|
+
'1': 'sell',
|
|
467
|
+
};
|
|
468
|
+
return this.safeString(sides, direction, direction);
|
|
469
|
+
}
|
|
470
|
+
handleTakerOrMaker(matchRole) {
|
|
471
|
+
const roles = {
|
|
472
|
+
'0': 'maker',
|
|
473
|
+
'1': 'taker',
|
|
474
|
+
};
|
|
475
|
+
return this.safeString(roles, matchRole, matchRole);
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* @method
|
|
479
|
+
* @name deepcoin#watchOHLCV
|
|
480
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
481
|
+
* @see https://www.deepcoin.com/docs/publicWS/KLines
|
|
482
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
483
|
+
* @param {string} [timeframe] the length of time each candle represents
|
|
484
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
485
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
486
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
487
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
488
|
+
*/
|
|
489
|
+
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
490
|
+
await this.loadMarkets();
|
|
491
|
+
const market = this.market(symbol);
|
|
492
|
+
symbol = market['symbol'];
|
|
493
|
+
const timeframes = this.safeDict(this.options, 'timeframes', {});
|
|
494
|
+
const interval = this.safeString(timeframes, timeframe, timeframe);
|
|
495
|
+
const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe;
|
|
496
|
+
const suffix = '_' + interval;
|
|
497
|
+
const ohlcv = await this.watchPublic(market, messageHash, '11', params, suffix);
|
|
498
|
+
if (this.newUpdates) {
|
|
499
|
+
limit = ohlcv.getLimit(symbol, limit);
|
|
500
|
+
}
|
|
501
|
+
return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* @method
|
|
505
|
+
* @name deepcoin#unWatchOHLCV
|
|
506
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
507
|
+
* @see https://docs.backpack.exchange/#tag/Streams/Public/K-Line
|
|
508
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
509
|
+
* @param {string} [timeframe] the length of time each candle represents
|
|
510
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
511
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
512
|
+
*/
|
|
513
|
+
async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
|
|
514
|
+
await this.loadMarkets();
|
|
515
|
+
const market = this.market(symbol);
|
|
516
|
+
symbol = market['symbol'];
|
|
517
|
+
const timeframes = this.safeDict(this.options, 'timeframes', {});
|
|
518
|
+
const interval = this.safeString(timeframes, timeframe, timeframe);
|
|
519
|
+
const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe;
|
|
520
|
+
const suffix = '_' + interval;
|
|
521
|
+
const subscription = {
|
|
522
|
+
'topic': 'ohlcv',
|
|
523
|
+
'symbolsAndTimeframes': [[symbol, timeframe]],
|
|
524
|
+
};
|
|
525
|
+
return await this.unWatchPublic(market, messageHash, '11', params, subscription, suffix);
|
|
526
|
+
}
|
|
527
|
+
handleOHLCV(client, message) {
|
|
528
|
+
//
|
|
529
|
+
// {
|
|
530
|
+
// "a": "PK",
|
|
531
|
+
// "tt": 1760972831580,
|
|
532
|
+
// "mt": 1760972831580,
|
|
533
|
+
// "r": [
|
|
534
|
+
// {
|
|
535
|
+
// "d": {
|
|
536
|
+
// "I": "BTC/USDT",
|
|
537
|
+
// "P": "1m",
|
|
538
|
+
// "B": 1760972820,
|
|
539
|
+
// "O": 111373,
|
|
540
|
+
// "C": 111382.9,
|
|
541
|
+
// "H": 111382.9,
|
|
542
|
+
// "L": 111373,
|
|
543
|
+
// "V": 0.2414172,
|
|
544
|
+
// "M": 26888.19693324
|
|
545
|
+
// },
|
|
546
|
+
// "t": "LK"
|
|
547
|
+
// }
|
|
548
|
+
// ]
|
|
549
|
+
// }
|
|
550
|
+
//
|
|
551
|
+
const response = this.safeList(message, 'r', []);
|
|
552
|
+
const first = this.safeDict(response, 0, {});
|
|
553
|
+
const data = this.safeDict(first, 'd', {});
|
|
554
|
+
const marketId = this.safeString(data, 'I');
|
|
555
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
556
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
557
|
+
const interval = this.safeString(data, 'P');
|
|
558
|
+
const timeframe = this.findTimeframe(interval);
|
|
559
|
+
if (!(symbol in this.ohlcvs)) {
|
|
560
|
+
this.ohlcvs[symbol] = {};
|
|
561
|
+
}
|
|
562
|
+
if (!(timeframe in this.ohlcvs[symbol])) {
|
|
563
|
+
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
564
|
+
this.ohlcvs[symbol][timeframe] = new ArrayCacheByTimestamp(limit);
|
|
565
|
+
}
|
|
566
|
+
const stored = this.ohlcvs[symbol][timeframe];
|
|
567
|
+
if (data !== undefined) {
|
|
568
|
+
const ohlcv = this.parseWsOHLCV(data, market);
|
|
569
|
+
stored.append(ohlcv);
|
|
570
|
+
}
|
|
571
|
+
const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe;
|
|
572
|
+
client.resolve(stored, messageHash);
|
|
573
|
+
}
|
|
574
|
+
parseWsOHLCV(ohlcv, market = undefined) {
|
|
575
|
+
//
|
|
576
|
+
// {
|
|
577
|
+
// "I": "BTC/USDT",
|
|
578
|
+
// "P": "1m",
|
|
579
|
+
// "B": 1760972820,
|
|
580
|
+
// "O": 111373,
|
|
581
|
+
// "C": 111382.9,
|
|
582
|
+
// "H": 111382.9,
|
|
583
|
+
// "L": 111373,
|
|
584
|
+
// "V": 0.2414172,
|
|
585
|
+
// "M": 26888.19693324
|
|
586
|
+
// }
|
|
587
|
+
//
|
|
588
|
+
return [
|
|
589
|
+
this.safeTimestamp(ohlcv, 'B'),
|
|
590
|
+
this.safeNumber(ohlcv, 'O'),
|
|
591
|
+
this.safeNumber(ohlcv, 'H'),
|
|
592
|
+
this.safeNumber(ohlcv, 'L'),
|
|
593
|
+
this.safeNumber(ohlcv, 'C'),
|
|
594
|
+
this.safeNumber(ohlcv, 'V'),
|
|
595
|
+
];
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* @method
|
|
599
|
+
* @name deepcoin#watchOrderBook
|
|
600
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
601
|
+
* @see https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData
|
|
602
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
603
|
+
* @param {int} [limit] the maximum amount of order book entries to return.
|
|
604
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
605
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
606
|
+
*/
|
|
607
|
+
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
608
|
+
await this.loadMarkets();
|
|
609
|
+
const market = this.market(symbol);
|
|
610
|
+
const messageHash = 'orderbook' + '::' + market['symbol'];
|
|
611
|
+
const suffix = '_0.1';
|
|
612
|
+
const orderbook = await this.watchPublic(market, messageHash, '25', params, suffix);
|
|
613
|
+
return orderbook.limit();
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* @method
|
|
617
|
+
* @name deepcoin#unWatchOrderBook
|
|
618
|
+
* @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
619
|
+
* @see https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData
|
|
620
|
+
* @param {string} symbol unified array of symbols
|
|
621
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
622
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
623
|
+
*/
|
|
624
|
+
async unWatchOrderBook(symbol, params = {}) {
|
|
625
|
+
await this.loadMarkets();
|
|
626
|
+
const market = this.market(symbol);
|
|
627
|
+
const messageHash = 'orderbook' + '::' + market['symbol'];
|
|
628
|
+
const suffix = '_0.1';
|
|
629
|
+
const subscription = {
|
|
630
|
+
'topic': 'orderbook',
|
|
631
|
+
};
|
|
632
|
+
return await this.unWatchPublic(market, messageHash, '25', params, subscription, suffix);
|
|
633
|
+
}
|
|
634
|
+
handleOrderBook(client, message) {
|
|
635
|
+
//
|
|
636
|
+
// {
|
|
637
|
+
// "a": "PMO",
|
|
638
|
+
// "t": "i", // i - update, f - snapshot
|
|
639
|
+
// "r": [
|
|
640
|
+
// {
|
|
641
|
+
// "d": { "I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979 }
|
|
642
|
+
// },
|
|
643
|
+
// {
|
|
644
|
+
// "d": { "I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724 }
|
|
645
|
+
// }
|
|
646
|
+
// ],
|
|
647
|
+
// "tt": 1760975816446,
|
|
648
|
+
// "mt": 1760975816446
|
|
649
|
+
// }
|
|
650
|
+
//
|
|
651
|
+
const response = this.safeList(message, 'r', []);
|
|
652
|
+
const first = this.safeDict(response, 0, {});
|
|
653
|
+
const data = this.safeDict(first, 'd', {});
|
|
654
|
+
const marketId = this.safeString(data, 'I');
|
|
655
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
656
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
657
|
+
if (!(symbol in this.orderbooks)) {
|
|
658
|
+
this.orderbooks[symbol] = this.orderBook();
|
|
659
|
+
}
|
|
660
|
+
const orderbook = this.orderbooks[symbol];
|
|
661
|
+
const type = this.safeString(message, 't');
|
|
662
|
+
if (orderbook['timestamp'] === undefined) {
|
|
663
|
+
if (type === 'f') {
|
|
664
|
+
// snapshot
|
|
665
|
+
this.handleOrderBookSnapshot(client, message);
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
// cache the updates until the snapshot is received
|
|
669
|
+
orderbook.cache.push(message);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
this.handleOrderBookMessage(client, message, orderbook);
|
|
674
|
+
const messageHash = 'orderbook' + '::' + symbol;
|
|
675
|
+
client.resolve(orderbook, messageHash);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
handleOrderBookSnapshot(client, message) {
|
|
679
|
+
const entries = this.safeList(message, 'r', []);
|
|
680
|
+
const first = this.safeDict(entries, 0, {});
|
|
681
|
+
const data = this.safeDict(first, 'd', {});
|
|
682
|
+
const marketId = this.safeString(data, 'I');
|
|
683
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
684
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
685
|
+
const orderbook = this.orderbooks[symbol];
|
|
686
|
+
const orderedEntries = {
|
|
687
|
+
'bids': [],
|
|
688
|
+
'asks': [],
|
|
689
|
+
};
|
|
690
|
+
for (let i = 0; i < entries.length; i++) {
|
|
691
|
+
const entry = entries[i];
|
|
692
|
+
const entryData = this.safeDict(entry, 'd', {});
|
|
693
|
+
const side = this.safeString(entryData, 'D');
|
|
694
|
+
const price = this.safeNumber(entryData, 'P');
|
|
695
|
+
const volume = this.safeNumber(entryData, 'V');
|
|
696
|
+
if (side === '0') {
|
|
697
|
+
// bid
|
|
698
|
+
orderedEntries['bids'].push([price, volume]);
|
|
699
|
+
}
|
|
700
|
+
else if (side === '1') {
|
|
701
|
+
// ask
|
|
702
|
+
orderedEntries['asks'].push([price, volume]);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
const timestamp = this.safeInteger(message, 'mt');
|
|
706
|
+
const snapshot = this.parseOrderBook(orderedEntries, symbol, timestamp);
|
|
707
|
+
orderbook.reset(snapshot);
|
|
708
|
+
const cachedMessages = orderbook.cache;
|
|
709
|
+
for (let j = 0; j < cachedMessages.length; j++) {
|
|
710
|
+
const cachedMessage = cachedMessages[j];
|
|
711
|
+
this.handleOrderBookMessage(client, cachedMessage, orderbook);
|
|
712
|
+
}
|
|
713
|
+
orderbook.cache = [];
|
|
714
|
+
const messageHash = 'orderbook' + '::' + symbol;
|
|
715
|
+
client.resolve(orderbook, messageHash);
|
|
716
|
+
}
|
|
717
|
+
handleOrderBookMessage(client, message, orderbook) {
|
|
718
|
+
// {
|
|
719
|
+
// "a": "PMO",
|
|
720
|
+
// "t": "i", // i - update, f - snapshot
|
|
721
|
+
// "r": [
|
|
722
|
+
// {
|
|
723
|
+
// "d": { "I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979 }
|
|
724
|
+
// },
|
|
725
|
+
// {
|
|
726
|
+
// "d": { "I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724 }
|
|
727
|
+
// }
|
|
728
|
+
// ],
|
|
729
|
+
// "tt": 1760975816446,
|
|
730
|
+
// "mt": 1760975816446
|
|
731
|
+
// }
|
|
732
|
+
//
|
|
733
|
+
const timestamp = this.safeInteger(message, 'mt');
|
|
734
|
+
if (timestamp > orderbook['timestamp']) {
|
|
735
|
+
const response = this.safeList(message, 'r', []);
|
|
736
|
+
this.handleDeltas(orderbook, response);
|
|
737
|
+
orderbook['timestamp'] = timestamp;
|
|
738
|
+
orderbook['datetime'] = this.iso8601(timestamp);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
handleDelta(orderbook, entry) {
|
|
742
|
+
const data = this.safeDict(entry, 'd', {});
|
|
743
|
+
const bids = orderbook['bids'];
|
|
744
|
+
const asks = orderbook['asks'];
|
|
745
|
+
const side = this.safeString(data, 'D');
|
|
746
|
+
const price = this.safeNumber(data, 'P');
|
|
747
|
+
const volume = this.safeNumber(data, 'V');
|
|
748
|
+
if (side === '0') {
|
|
749
|
+
// bid
|
|
750
|
+
bids.store(price, volume);
|
|
751
|
+
}
|
|
752
|
+
else if (side === '1') {
|
|
753
|
+
// ask
|
|
754
|
+
asks.store(price, volume);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* @method
|
|
759
|
+
* @name deepcoin#watchMyTrades
|
|
760
|
+
* @description watches information on multiple trades made by the user
|
|
761
|
+
* @see https://www.deepcoin.com/docs/privateWS/Trade
|
|
762
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
763
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
764
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
765
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
766
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
767
|
+
*/
|
|
768
|
+
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
769
|
+
let messageHash = 'myTrades';
|
|
770
|
+
await this.loadMarkets();
|
|
771
|
+
if (symbol !== undefined) {
|
|
772
|
+
symbol = this.symbol(symbol);
|
|
773
|
+
messageHash += '::' + symbol;
|
|
774
|
+
}
|
|
775
|
+
const trades = await this.watchPrivate(messageHash, params);
|
|
776
|
+
if (this.newUpdates) {
|
|
777
|
+
limit = trades.getLimit(symbol, limit);
|
|
778
|
+
}
|
|
779
|
+
return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
|
|
780
|
+
}
|
|
781
|
+
handleMyTrade(client, message) {
|
|
782
|
+
//
|
|
783
|
+
// {
|
|
784
|
+
// "action": "PushTrade",
|
|
785
|
+
// "result": [
|
|
786
|
+
// {
|
|
787
|
+
// "table": "Trade",
|
|
788
|
+
// "data": {
|
|
789
|
+
// "A": "9256245",
|
|
790
|
+
// "CC": "USDT",
|
|
791
|
+
// "CP": 0,
|
|
792
|
+
// "D": "0",
|
|
793
|
+
// "F": 0.152,
|
|
794
|
+
// "I": "DOGE/USDT",
|
|
795
|
+
// "IT": 1761048103,
|
|
796
|
+
// "M": "9256245",
|
|
797
|
+
// "OS": "1001437462198486",
|
|
798
|
+
// "P": 0.19443,
|
|
799
|
+
// "T": 14.77668,
|
|
800
|
+
// "TI": "1001056459096708",
|
|
801
|
+
// "TT": 1761048103,
|
|
802
|
+
// "V": 76,
|
|
803
|
+
// "f": "DOGE",
|
|
804
|
+
// "l": 1,
|
|
805
|
+
// "m": "1",
|
|
806
|
+
// "o": "0"
|
|
807
|
+
// }
|
|
808
|
+
// }
|
|
809
|
+
// ]
|
|
810
|
+
// }
|
|
811
|
+
//
|
|
812
|
+
const result = this.safeList(message, 'result', []);
|
|
813
|
+
const first = this.safeDict(result, 0, {});
|
|
814
|
+
const data = this.safeDict(first, 'data', {});
|
|
815
|
+
const marketId = this.safeString(data, 'I');
|
|
816
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
817
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
818
|
+
const messageHash = 'myTrades';
|
|
819
|
+
const symbolMessageHash = messageHash + '::' + symbol;
|
|
820
|
+
if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) {
|
|
821
|
+
if (this.myTrades === undefined) {
|
|
822
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
823
|
+
this.myTrades = new ArrayCacheBySymbolById(limit);
|
|
824
|
+
}
|
|
825
|
+
const stored = this.myTrades;
|
|
826
|
+
const parsed = this.parseWsTrade(data, market);
|
|
827
|
+
stored.append(parsed);
|
|
828
|
+
client.resolve(stored, messageHash);
|
|
829
|
+
client.resolve(stored, symbolMessageHash);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* @method
|
|
834
|
+
* @name deepcoin#watchOrders
|
|
835
|
+
* @description watches information on multiple orders made by the user
|
|
836
|
+
* @see https://www.deepcoin.com/docs/privateWS/order
|
|
837
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
838
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
839
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
840
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
841
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
842
|
+
*/
|
|
843
|
+
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
844
|
+
let messageHash = 'orders';
|
|
845
|
+
await this.loadMarkets();
|
|
846
|
+
if (symbol !== undefined) {
|
|
847
|
+
symbol = this.symbol(symbol);
|
|
848
|
+
messageHash += '::' + symbol;
|
|
849
|
+
}
|
|
850
|
+
const orders = await this.watchPrivate(messageHash, params);
|
|
851
|
+
if (this.newUpdates) {
|
|
852
|
+
limit = orders.getLimit(symbol, limit);
|
|
853
|
+
}
|
|
854
|
+
return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
|
|
855
|
+
}
|
|
856
|
+
handleOrder(client, message) {
|
|
857
|
+
//
|
|
858
|
+
// {
|
|
859
|
+
// "action": "PushOrder",
|
|
860
|
+
// "result": [
|
|
861
|
+
// {
|
|
862
|
+
// "table": "Order",
|
|
863
|
+
// "data": {
|
|
864
|
+
// "D": "0",
|
|
865
|
+
// "I": "DOGE/USDT",
|
|
866
|
+
// "IT": 1761051006,
|
|
867
|
+
// "L": "1001437480817468",
|
|
868
|
+
// "OPT": "4",
|
|
869
|
+
// "OS": "1001437480817468",
|
|
870
|
+
// "OT": "0",
|
|
871
|
+
// "Or": "1",
|
|
872
|
+
// "P": 0.19537,
|
|
873
|
+
// "T": 14.84128,
|
|
874
|
+
// "U": 1761051006,
|
|
875
|
+
// "V": 76,
|
|
876
|
+
// "VT": 76,
|
|
877
|
+
// "i": 1,
|
|
878
|
+
// "l": 1,
|
|
879
|
+
// "o": "0",
|
|
880
|
+
// "p": "0",
|
|
881
|
+
// "t": 0.19528
|
|
882
|
+
// }
|
|
883
|
+
// }
|
|
884
|
+
// ]
|
|
885
|
+
// }
|
|
886
|
+
//
|
|
887
|
+
const result = this.safeList(message, 'result', []);
|
|
888
|
+
const first = this.safeDict(result, 0, {});
|
|
889
|
+
const data = this.safeDict(first, 'data', {});
|
|
890
|
+
const marketId = this.safeString(data, 'I');
|
|
891
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
892
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
893
|
+
const messageHash = 'orders';
|
|
894
|
+
const symbolMessageHash = messageHash + '::' + symbol;
|
|
895
|
+
if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) {
|
|
896
|
+
if (this.orders === undefined) {
|
|
897
|
+
const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
|
|
898
|
+
this.orders = new ArrayCacheBySymbolById(limit);
|
|
899
|
+
}
|
|
900
|
+
const parsed = this.parseWsOrder(data, market);
|
|
901
|
+
this.orders.append(parsed);
|
|
902
|
+
client.resolve(this.orders, messageHash);
|
|
903
|
+
client.resolve(this.orders, symbolMessageHash);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
parseWsOrder(order, market = undefined) {
|
|
907
|
+
//
|
|
908
|
+
// {
|
|
909
|
+
// "D": "0",
|
|
910
|
+
// "I": "DOGE/USDT",
|
|
911
|
+
// "IT": 1761051006,
|
|
912
|
+
// "L": "1001437480817468",
|
|
913
|
+
// "OPT": "4",
|
|
914
|
+
// "OS": "1001437480817468",
|
|
915
|
+
// "OT": "0",
|
|
916
|
+
// "Or": "1",
|
|
917
|
+
// "P": 0.19537,
|
|
918
|
+
// "T": 14.84128,
|
|
919
|
+
// "U": 1761051006,
|
|
920
|
+
// "V": 76,
|
|
921
|
+
// "VT": 76,
|
|
922
|
+
// "i": 1,
|
|
923
|
+
// "l": 1,
|
|
924
|
+
// "o": "0",
|
|
925
|
+
// "p": "0",
|
|
926
|
+
// "t": 0.19528
|
|
927
|
+
// }
|
|
928
|
+
//
|
|
929
|
+
const state = this.safeString(order, 'Or');
|
|
930
|
+
const timestamp = this.safeTimestamp(order, 'IT');
|
|
931
|
+
const direction = this.safeString(order, 'D');
|
|
932
|
+
return this.safeOrder({
|
|
933
|
+
'id': this.safeString(order, 'OS'),
|
|
934
|
+
'clientOrderId': undefined,
|
|
935
|
+
'datetime': this.iso8601(timestamp),
|
|
936
|
+
'timestamp': timestamp,
|
|
937
|
+
'lastTradeTimestamp': undefined,
|
|
938
|
+
'lastUpdateTimestamp': this.safeTimestamp(order, 'U'),
|
|
939
|
+
'status': this.parseWsOrderStatus(state),
|
|
940
|
+
'symbol': market['symbol'],
|
|
941
|
+
'type': undefined,
|
|
942
|
+
'timeInForce': undefined,
|
|
943
|
+
'side': this.parseTradeSide(direction),
|
|
944
|
+
'price': this.safeString(order, 'P'),
|
|
945
|
+
'average': this.safeString(order, 't'),
|
|
946
|
+
'amount': this.safeString(order, 'V'),
|
|
947
|
+
'filled': this.safeString(order, 'VT'),
|
|
948
|
+
'remaining': undefined,
|
|
949
|
+
'triggerPrice': undefined,
|
|
950
|
+
'takeProfitPrice': this.safeString(order, 'TPT'),
|
|
951
|
+
'stopLossPrice': this.safeString(order, 'SLT'),
|
|
952
|
+
'cost': this.safeString(order, 'T'),
|
|
953
|
+
'trades': undefined,
|
|
954
|
+
'fee': undefined,
|
|
955
|
+
'reduceOnly': undefined,
|
|
956
|
+
'postOnly': undefined,
|
|
957
|
+
'info': order,
|
|
958
|
+
}, market);
|
|
959
|
+
}
|
|
960
|
+
parseWsOrderStatus(status) {
|
|
961
|
+
const statuses = {
|
|
962
|
+
'1': 'closed',
|
|
963
|
+
'4': 'open',
|
|
964
|
+
'6': 'canceled',
|
|
965
|
+
};
|
|
966
|
+
return this.safeString(statuses, status, status);
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* @method
|
|
970
|
+
* @name deepcoin#watchPositions
|
|
971
|
+
* @description watch all open positions
|
|
972
|
+
* @see https://www.deepcoin.com/docs/privateWS/Position
|
|
973
|
+
* @param {string[]} [symbols] list of unified market symbols to watch positions for
|
|
974
|
+
* @param {int} [since] the earliest time in ms to fetch positions for
|
|
975
|
+
* @param {int} [limit] the maximum number of positions to retrieve
|
|
976
|
+
* @param {object} params extra parameters specific to the exchange API endpoint
|
|
977
|
+
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
|
|
978
|
+
*/
|
|
979
|
+
async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
|
|
980
|
+
await this.loadMarkets();
|
|
981
|
+
const listenKey = await this.authenticate();
|
|
982
|
+
symbols = this.marketSymbols(symbols);
|
|
983
|
+
const messageHash = 'positions';
|
|
984
|
+
const messageHashes = [];
|
|
985
|
+
if (symbols !== undefined) {
|
|
986
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
987
|
+
const symbol = symbols[i];
|
|
988
|
+
const symbolMessageHash = messageHash + '::' + symbol;
|
|
989
|
+
messageHashes.push(symbolMessageHash);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
else {
|
|
993
|
+
messageHashes.push(messageHash);
|
|
994
|
+
}
|
|
995
|
+
const url = this.urls['api']['ws']['private'] + '?listenKey=' + listenKey;
|
|
996
|
+
const positions = await this.watchMultiple(url, messageHashes, params, ['private']);
|
|
997
|
+
if (this.newUpdates) {
|
|
998
|
+
return positions;
|
|
999
|
+
}
|
|
1000
|
+
return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
|
|
1001
|
+
}
|
|
1002
|
+
handlePosition(client, message) {
|
|
1003
|
+
//
|
|
1004
|
+
// {
|
|
1005
|
+
// "action": "PushPosition",
|
|
1006
|
+
// "result": [
|
|
1007
|
+
// {
|
|
1008
|
+
// "table": "Position",
|
|
1009
|
+
// "data": {
|
|
1010
|
+
// "A": "9256245",
|
|
1011
|
+
// "CP": 0,
|
|
1012
|
+
// "I": "DOGE/USDT",
|
|
1013
|
+
// "M": "9256245",
|
|
1014
|
+
// "OP": 0.198845,
|
|
1015
|
+
// "Po": 151.696,
|
|
1016
|
+
// "U": 1761058213,
|
|
1017
|
+
// "i": 1,
|
|
1018
|
+
// "l": 1,
|
|
1019
|
+
// "p": "0",
|
|
1020
|
+
// "u": 0
|
|
1021
|
+
// }
|
|
1022
|
+
// }
|
|
1023
|
+
// ]
|
|
1024
|
+
// }
|
|
1025
|
+
//
|
|
1026
|
+
const result = this.safeList(message, 'result', []);
|
|
1027
|
+
const first = this.safeDict(result, 0, {});
|
|
1028
|
+
const data = this.safeDict(first, 'data', {});
|
|
1029
|
+
const marketId = this.safeString(data, 'I');
|
|
1030
|
+
const market = this.safeMarket(marketId, undefined, '/');
|
|
1031
|
+
const symbol = this.safeSymbol(marketId, market);
|
|
1032
|
+
const messageHash = 'positions';
|
|
1033
|
+
const symbolMessageHash = messageHash + '::' + symbol;
|
|
1034
|
+
if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) {
|
|
1035
|
+
if (this.positions === undefined) {
|
|
1036
|
+
this.positions = new ArrayCacheBySymbolBySide();
|
|
1037
|
+
}
|
|
1038
|
+
const parsed = this.parseWsPosition(data, market);
|
|
1039
|
+
this.positions.append(parsed);
|
|
1040
|
+
client.resolve(this.positions, messageHash);
|
|
1041
|
+
client.resolve(this.positions, symbolMessageHash);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
parseWsPosition(position, market = undefined) {
|
|
1045
|
+
//
|
|
1046
|
+
// {
|
|
1047
|
+
// "A": "9256245",
|
|
1048
|
+
// "CP": 0,
|
|
1049
|
+
// "I": "DOGE/USDT",
|
|
1050
|
+
// "M": "9256245",
|
|
1051
|
+
// "OP": 0.198845,
|
|
1052
|
+
// "Po": 151.696,
|
|
1053
|
+
// "U": 1761058213,
|
|
1054
|
+
// "i": 1,
|
|
1055
|
+
// "l": 1,
|
|
1056
|
+
// "p": "0",
|
|
1057
|
+
// "u": 0
|
|
1058
|
+
// }
|
|
1059
|
+
//
|
|
1060
|
+
const timestamp = this.safeInteger(position, 'U');
|
|
1061
|
+
const direction = this.safeString(position, 'p');
|
|
1062
|
+
const marginMode = this.safeString(position, 'i');
|
|
1063
|
+
return this.safePosition({
|
|
1064
|
+
'symbol': market['symbol'],
|
|
1065
|
+
'id': undefined,
|
|
1066
|
+
'timestamp': timestamp,
|
|
1067
|
+
'datetime': this.iso8601(timestamp),
|
|
1068
|
+
'contracts': this.safeString(position, 'Po'),
|
|
1069
|
+
'contractSize': undefined,
|
|
1070
|
+
'side': this.parsePositionSide(direction),
|
|
1071
|
+
'notional': undefined,
|
|
1072
|
+
'leverage': this.omitZero(this.safeString(position, 'l')),
|
|
1073
|
+
'unrealizedPnl': undefined,
|
|
1074
|
+
'realizedPnl': undefined,
|
|
1075
|
+
'collateral': undefined,
|
|
1076
|
+
'entryPrice': this.safeString(position, 'OP'),
|
|
1077
|
+
'markPrice': undefined,
|
|
1078
|
+
'liquidationPrice': undefined,
|
|
1079
|
+
'marginMode': this.parseWsMarginMode(marginMode),
|
|
1080
|
+
'hedged': true,
|
|
1081
|
+
'maintenanceMargin': this.safeString(position, 'u'),
|
|
1082
|
+
'maintenanceMarginPercentage': undefined,
|
|
1083
|
+
'initialMargin': undefined,
|
|
1084
|
+
'initialMarginPercentage': undefined,
|
|
1085
|
+
'marginRatio': undefined,
|
|
1086
|
+
'lastUpdateTimestamp': undefined,
|
|
1087
|
+
'lastPrice': undefined,
|
|
1088
|
+
'stopLossPrice': undefined,
|
|
1089
|
+
'takeProfitPrice': undefined,
|
|
1090
|
+
'percentage': undefined,
|
|
1091
|
+
'info': position,
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
parsePositionSide(direction) {
|
|
1095
|
+
if (direction === undefined) {
|
|
1096
|
+
return direction;
|
|
1097
|
+
}
|
|
1098
|
+
const directions = {
|
|
1099
|
+
'0': 'long',
|
|
1100
|
+
'1': 'short',
|
|
1101
|
+
};
|
|
1102
|
+
return this.safeString(directions, direction, direction);
|
|
1103
|
+
}
|
|
1104
|
+
parseWsMarginMode(marginMode) {
|
|
1105
|
+
if (marginMode === undefined) {
|
|
1106
|
+
return marginMode;
|
|
1107
|
+
}
|
|
1108
|
+
const modes = {
|
|
1109
|
+
'0': 'isolated',
|
|
1110
|
+
'1': 'cross',
|
|
1111
|
+
};
|
|
1112
|
+
return this.safeString(modes, marginMode, marginMode);
|
|
1113
|
+
}
|
|
1114
|
+
handleMessage(client, message) {
|
|
1115
|
+
if (message === 'pong') {
|
|
1116
|
+
this.handlePong(client, message);
|
|
1117
|
+
}
|
|
1118
|
+
else {
|
|
1119
|
+
const m = this.safeString(message, 'm');
|
|
1120
|
+
if ((m !== undefined) && (m !== 'Success')) {
|
|
1121
|
+
this.handleErrorMessage(client, message);
|
|
1122
|
+
}
|
|
1123
|
+
const action = this.safeString2(message, 'a', 'action');
|
|
1124
|
+
if (action === 'RecvTopicAction') {
|
|
1125
|
+
this.handleSubscriptionStatus(client, message);
|
|
1126
|
+
}
|
|
1127
|
+
else if (action === 'PO') {
|
|
1128
|
+
this.handleTicker(client, message);
|
|
1129
|
+
}
|
|
1130
|
+
else if (action === 'PMT') {
|
|
1131
|
+
this.handleTrades(client, message);
|
|
1132
|
+
}
|
|
1133
|
+
else if (action === 'PK') {
|
|
1134
|
+
this.handleOHLCV(client, message);
|
|
1135
|
+
}
|
|
1136
|
+
else if (action === 'PMO') {
|
|
1137
|
+
this.handleOrderBook(client, message);
|
|
1138
|
+
}
|
|
1139
|
+
else if (action === 'PushTrade') {
|
|
1140
|
+
this.handleMyTrade(client, message);
|
|
1141
|
+
}
|
|
1142
|
+
else if (action === 'PushOrder') {
|
|
1143
|
+
this.handleOrder(client, message);
|
|
1144
|
+
}
|
|
1145
|
+
else if (action === 'PushPosition') {
|
|
1146
|
+
this.handlePosition(client, message);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
handleSubscriptionStatus(client, message) {
|
|
1151
|
+
//
|
|
1152
|
+
// {
|
|
1153
|
+
// "a": "RecvTopicAction",
|
|
1154
|
+
// "m": "Success",
|
|
1155
|
+
// "r": [
|
|
1156
|
+
// {
|
|
1157
|
+
// "d": {
|
|
1158
|
+
// "A": "0",
|
|
1159
|
+
// "L": 1,
|
|
1160
|
+
// "T": "7",
|
|
1161
|
+
// "F": "DeepCoin_BTC/USDT",
|
|
1162
|
+
// "R": -1
|
|
1163
|
+
// }
|
|
1164
|
+
// }
|
|
1165
|
+
// ]
|
|
1166
|
+
// }
|
|
1167
|
+
//
|
|
1168
|
+
const response = this.safeList(message, 'r', []);
|
|
1169
|
+
const first = this.safeDict(response, 0, {});
|
|
1170
|
+
const data = this.safeDict(first, 'd', {});
|
|
1171
|
+
const action = this.safeString(data, 'A'); // 1 = subscribe, 0 = unsubscribe
|
|
1172
|
+
if (action === '0') {
|
|
1173
|
+
const subscriptionsById = this.indexBy(client.subscriptions, 'id');
|
|
1174
|
+
const subId = this.safeInteger(data, 'L');
|
|
1175
|
+
const subscription = this.safeDict(subscriptionsById, subId, {}); // original watch subscription
|
|
1176
|
+
const subHash = this.safeString(subscription, 'subHash');
|
|
1177
|
+
const unsubHash = 'unsubscribe::' + subHash;
|
|
1178
|
+
const unsubsciption = this.safeDict(client.subscriptions, unsubHash, {}); // unWatch subscription
|
|
1179
|
+
this.handleUnSubscription(client, unsubsciption);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
handleUnSubscription(client, subscription) {
|
|
1183
|
+
const subHash = this.safeString(subscription, 'subHash');
|
|
1184
|
+
const unsubHash = this.safeString(subscription, 'unsubHash');
|
|
1185
|
+
this.cleanUnsubscription(client, subHash, unsubHash);
|
|
1186
|
+
this.cleanCache(subscription);
|
|
1187
|
+
}
|
|
1188
|
+
handleErrorMessage(client, message) {
|
|
1189
|
+
//
|
|
1190
|
+
// {
|
|
1191
|
+
// "a": "RecvTopicAction",
|
|
1192
|
+
// "m": "subscription cluster does not "exist": BTC/USD",
|
|
1193
|
+
// "r": [
|
|
1194
|
+
// {
|
|
1195
|
+
// "d": {
|
|
1196
|
+
// "A": "1",
|
|
1197
|
+
// "L": 1,
|
|
1198
|
+
// "T": "7",
|
|
1199
|
+
// "F": "DeepCoin_BTC/USD",
|
|
1200
|
+
// "R": -1
|
|
1201
|
+
// }
|
|
1202
|
+
// }
|
|
1203
|
+
// ]
|
|
1204
|
+
// }
|
|
1205
|
+
//
|
|
1206
|
+
const messageText = this.safeString(message, 'm', '');
|
|
1207
|
+
const response = this.safeList(message, 'r', []);
|
|
1208
|
+
const first = this.safeDict(response, 0, {});
|
|
1209
|
+
const data = this.safeDict(first, 'd', {});
|
|
1210
|
+
const requestId = this.safeInteger(data, 'L');
|
|
1211
|
+
const subscriptionsById = this.indexBy(client.subscriptions, 'id');
|
|
1212
|
+
const subscription = this.safeDict(subscriptionsById, requestId, {});
|
|
1213
|
+
const messageHash = this.safeString(subscription, 'subHash');
|
|
1214
|
+
const feedback = this.id + ' ' + this.json(message);
|
|
1215
|
+
try {
|
|
1216
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], messageText, feedback);
|
|
1217
|
+
this.throwBroadlyMatchedException(this.exceptions['broad'], messageText, feedback);
|
|
1218
|
+
throw new ExchangeError(feedback);
|
|
1219
|
+
}
|
|
1220
|
+
catch (e) {
|
|
1221
|
+
client.reject(e, messageHash);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
}
|