ccxt 4.4.74 → 4.4.77
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 +3 -3
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/base/Exchange.js +16 -9
- package/dist/cjs/src/binance.js +43 -219
- package/dist/cjs/src/bitget.js +1 -1
- package/dist/cjs/src/bitopro.js +37 -0
- package/dist/cjs/src/bitrue.js +48 -0
- package/dist/cjs/src/coinex.js +3 -0
- package/dist/cjs/src/coinlist.js +90 -1
- package/dist/cjs/src/okx.js +47 -33
- package/dist/cjs/src/paradex.js +3 -12
- package/dist/cjs/src/pro/hyperliquid.js +1 -1
- package/dist/cjs/src/upbit.js +64 -46
- package/dist/cjs/src/xt.js +122 -4
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/abstract/coinlist.d.ts +3 -0
- package/js/src/abstract/myokx.d.ts +4 -0
- package/js/src/abstract/okx.d.ts +4 -0
- package/js/src/abstract/upbit.d.ts +15 -1
- package/js/src/abstract/xt.d.ts +3 -0
- package/js/src/base/Exchange.d.ts +1 -0
- package/js/src/base/Exchange.js +16 -9
- package/js/src/binance.d.ts +2 -0
- package/js/src/binance.js +43 -219
- package/js/src/bitget.js +1 -1
- package/js/src/bitopro.js +37 -0
- package/js/src/bitrue.js +48 -0
- package/js/src/coinex.js +3 -0
- package/js/src/coinlist.d.ts +12 -1
- package/js/src/coinlist.js +90 -1
- package/js/src/okx.js +47 -33
- package/js/src/paradex.js +3 -12
- package/js/src/pro/hyperliquid.js +1 -1
- package/js/src/upbit.js +64 -46
- package/js/src/xt.d.ts +19 -0
- package/js/src/xt.js +122 -4
- package/package.json +1 -1
- package/js/src/abstract/bitcoincom.d.ts +0 -118
- package/js/src/abstract/bitcoincom.js +0 -11
- package/js/src/abstract/bitfinex1.d.ts +0 -72
- package/js/src/abstract/bitfinex1.js +0 -11
- package/js/src/abstract/bitpanda.d.ts +0 -26
- package/js/src/abstract/bitpanda.js +0 -5
- package/js/src/abstract/poloniexfutures.d.ts +0 -51
- package/js/src/abstract/poloniexfutures.js +0 -11
- package/js/src/abstract/wazirx.d.ts +0 -33
- package/js/src/abstract/wazirx.js +0 -11
- package/js/src/bitcoincom.d.ts +0 -4
- package/js/src/bitcoincom.js +0 -18
- package/js/src/bitpanda.d.ts +0 -4
- package/js/src/bitpanda.js +0 -17
- package/js/src/poloniexfutures.d.ts +0 -321
- package/js/src/poloniexfutures.js +0 -1941
- package/js/src/pro/bitcoincom.d.ts +0 -4
- package/js/src/pro/bitcoincom.js +0 -34
- package/js/src/pro/bitpanda.d.ts +0 -4
- package/js/src/pro/bitpanda.js +0 -17
- package/js/src/pro/poloniexfutures.d.ts +0 -108
- package/js/src/pro/poloniexfutures.js +0 -1042
- package/js/src/pro/wazirx.d.ts +0 -102
- package/js/src/pro/wazirx.js +0 -784
- package/js/src/static_dependencies/starknet/utils/json.d.ts +0 -24
- package/js/src/static_dependencies/starknet/utils/json.js +0 -43
|
@@ -1,1042 +0,0 @@
|
|
|
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 poloniexfuturesRest from '../poloniexfutures.js';
|
|
9
|
-
import { AuthenticationError, BadRequest, ChecksumError } from '../base/errors.js';
|
|
10
|
-
import { ArrayCache, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
export default class poloniexfutures extends poloniexfuturesRest {
|
|
13
|
-
describe() {
|
|
14
|
-
return this.deepExtend(super.describe(), {
|
|
15
|
-
'has': {
|
|
16
|
-
'ws': true,
|
|
17
|
-
'cancelAllOrdersWs': false,
|
|
18
|
-
'cancelOrdersWs': false,
|
|
19
|
-
'cancelOrderWs': false,
|
|
20
|
-
'createOrderWs': false,
|
|
21
|
-
'editOrderWs': false,
|
|
22
|
-
'fetchBalanceWs': false,
|
|
23
|
-
'fetchOpenOrdersWs': false,
|
|
24
|
-
'fetchOrderWs': false,
|
|
25
|
-
'fetchTradesWs': false,
|
|
26
|
-
'watchOHLCV': false,
|
|
27
|
-
'watchOrderBook': true,
|
|
28
|
-
'watchTicker': true,
|
|
29
|
-
'watchTickers': false,
|
|
30
|
-
'watchTrades': true,
|
|
31
|
-
'watchTradesForSymbols': false,
|
|
32
|
-
'watchBalance': true,
|
|
33
|
-
'watchOrders': true,
|
|
34
|
-
'watchMyTrades': false,
|
|
35
|
-
'watchPosition': undefined,
|
|
36
|
-
'watchPositions': false,
|
|
37
|
-
},
|
|
38
|
-
'urls': {
|
|
39
|
-
'api': {
|
|
40
|
-
'ws': 'wss://futures-apiws.poloniex.com/endpoint',
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
'options': {
|
|
44
|
-
'tradesLimit': 1000,
|
|
45
|
-
'ordersLimit': 1000,
|
|
46
|
-
'watchTicker': {
|
|
47
|
-
'method': '/contractMarket/ticker', // can also be /contractMarket/snapshot
|
|
48
|
-
},
|
|
49
|
-
'watchOrders': {
|
|
50
|
-
'method': '/contractMarket/tradeOrders', // can also be /contractMarket/advancedOrders
|
|
51
|
-
},
|
|
52
|
-
'watchOrderBook': {
|
|
53
|
-
'method': '/contractMarket/level2',
|
|
54
|
-
'snapshotDelay': 5,
|
|
55
|
-
'snapshotMaxRetries': 3,
|
|
56
|
-
'checksum': true,
|
|
57
|
-
},
|
|
58
|
-
'streamLimit': 5,
|
|
59
|
-
'streamBySubscriptionsHash': {},
|
|
60
|
-
'streamIndex': -1,
|
|
61
|
-
},
|
|
62
|
-
'streaming': {
|
|
63
|
-
'keepAlive': 30000,
|
|
64
|
-
'maxPingPongMisses': 2.0,
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
async negotiate(privateChannel, params = {}) {
|
|
69
|
-
const connectId = privateChannel ? 'private' : 'public';
|
|
70
|
-
const urls = this.safeValue(this.options, 'urls', {});
|
|
71
|
-
if (connectId in urls) {
|
|
72
|
-
// return urls[connectId];
|
|
73
|
-
const storedFuture = urls[connectId];
|
|
74
|
-
return await storedFuture;
|
|
75
|
-
}
|
|
76
|
-
// we store an awaitable to the url
|
|
77
|
-
// so that multiple calls don't asynchronously
|
|
78
|
-
// fetch different urls and overwrite each other
|
|
79
|
-
urls[connectId] = this.spawn(this.negotiateHelper, privateChannel, params);
|
|
80
|
-
this.options['urls'] = urls;
|
|
81
|
-
const future = urls[connectId];
|
|
82
|
-
return await future;
|
|
83
|
-
}
|
|
84
|
-
async negotiateHelper(privateChannel, params = {}) {
|
|
85
|
-
let response = undefined;
|
|
86
|
-
const connectId = privateChannel ? 'private' : 'public';
|
|
87
|
-
try {
|
|
88
|
-
if (privateChannel) {
|
|
89
|
-
response = await this.privatePostBulletPrivate(params);
|
|
90
|
-
//
|
|
91
|
-
// {
|
|
92
|
-
// "code": "200000",
|
|
93
|
-
// "data": {
|
|
94
|
-
// "instanceServers": [
|
|
95
|
-
// {
|
|
96
|
-
// "pingInterval": 50000,
|
|
97
|
-
// "endpoint": "wss://push-private.kucoin.com/endpoint",
|
|
98
|
-
// "protocol": "websocket",
|
|
99
|
-
// "encrypt": true,
|
|
100
|
-
// "pingTimeout": 10000
|
|
101
|
-
// }
|
|
102
|
-
// ],
|
|
103
|
-
// "token": "2neAiuYvAU61ZDXANAGAsiL4-iAExhsBXZxftpOeh_55i3Ysy2q2LEsEWU64mdzUOPusi34M_wGoSf7iNyEWJ1UQy47YbpY4zVdzilNP-Bj3iXzrjjGlWtiYB9J6i9GjsxUuhPw3BlrzazF6ghq4Lzf7scStOz3KkxjwpsOBCH4=.WNQmhZQeUKIkh97KYgU0Lg=="
|
|
104
|
-
// }
|
|
105
|
-
// }
|
|
106
|
-
//
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
response = await this.publicPostBulletPublic(params);
|
|
110
|
-
}
|
|
111
|
-
const data = this.safeValue(response, 'data', {});
|
|
112
|
-
const instanceServers = this.safeValue(data, 'instanceServers', []);
|
|
113
|
-
const firstInstanceServer = this.safeValue(instanceServers, 0);
|
|
114
|
-
const pingInterval = this.safeInteger(firstInstanceServer, 'pingInterval');
|
|
115
|
-
const endpoint = this.safeString(firstInstanceServer, 'endpoint');
|
|
116
|
-
const token = this.safeString(data, 'token');
|
|
117
|
-
const result = endpoint + '?' + this.urlencode({
|
|
118
|
-
'token': token,
|
|
119
|
-
'privateChannel': privateChannel,
|
|
120
|
-
'connectId': connectId,
|
|
121
|
-
});
|
|
122
|
-
const client = this.client(result);
|
|
123
|
-
client.keepAlive = pingInterval;
|
|
124
|
-
return result;
|
|
125
|
-
}
|
|
126
|
-
catch (e) {
|
|
127
|
-
const future = this.safeValue(this.options['urls'], connectId);
|
|
128
|
-
future.reject(e);
|
|
129
|
-
delete this.options['urls'][connectId];
|
|
130
|
-
}
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
requestId() {
|
|
134
|
-
const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
|
|
135
|
-
this.options['requestId'] = requestId;
|
|
136
|
-
return requestId;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* @ignore
|
|
140
|
-
* @method
|
|
141
|
-
* @description Connects to a websocket channel
|
|
142
|
-
* @param {string} name name of the channel and suscriptionHash
|
|
143
|
-
* @param {bool} isPrivate true for the authenticated url, false for the public url
|
|
144
|
-
* @param {string} symbol is required for all public channels, not required for private channels (except position)
|
|
145
|
-
* @param {object} subscription subscription parameters
|
|
146
|
-
* @param {object} [params] extra parameters specific to the poloniex api
|
|
147
|
-
* @returns {object} data from the websocket stream
|
|
148
|
-
*/
|
|
149
|
-
async subscribe(name, isPrivate, symbol = undefined, subscription = undefined, params = {}) {
|
|
150
|
-
const url = await this.negotiate(isPrivate);
|
|
151
|
-
if (symbol !== undefined) {
|
|
152
|
-
const market = this.market(symbol);
|
|
153
|
-
const marketId = market['id'];
|
|
154
|
-
name += ':' + marketId;
|
|
155
|
-
}
|
|
156
|
-
const messageHash = name;
|
|
157
|
-
const tunnelId = await this.stream(url, messageHash);
|
|
158
|
-
const requestId = this.requestId();
|
|
159
|
-
const subscribe = {
|
|
160
|
-
'id': requestId,
|
|
161
|
-
'type': 'subscribe',
|
|
162
|
-
'topic': name,
|
|
163
|
-
'privateChannel': isPrivate,
|
|
164
|
-
'response': true,
|
|
165
|
-
'tunnelId': tunnelId,
|
|
166
|
-
};
|
|
167
|
-
const subscriptionRequest = {
|
|
168
|
-
'id': requestId,
|
|
169
|
-
};
|
|
170
|
-
if (subscription === undefined) {
|
|
171
|
-
subscription = subscriptionRequest;
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
subscription = this.extend(subscriptionRequest, subscription);
|
|
175
|
-
}
|
|
176
|
-
const request = this.extend(subscribe, params);
|
|
177
|
-
return await this.watch(url, messageHash, request, name, subscriptionRequest);
|
|
178
|
-
}
|
|
179
|
-
onClose(client, error) {
|
|
180
|
-
this.options['streamBySubscriptionsHash'] = {};
|
|
181
|
-
super.onClose(client, error);
|
|
182
|
-
}
|
|
183
|
-
async stream(url, subscriptionHash) {
|
|
184
|
-
const streamBySubscriptionsHash = this.safeValue(this.options, 'streamBySubscriptionsHash', {});
|
|
185
|
-
let stream = this.safeString(streamBySubscriptionsHash, subscriptionHash);
|
|
186
|
-
if (stream === undefined) {
|
|
187
|
-
let streamIndex = this.safeInteger(this.options, 'streamIndex', -1);
|
|
188
|
-
const streamLimit = this.safeValue(this.options, 'streamLimit');
|
|
189
|
-
streamIndex = streamIndex + 1;
|
|
190
|
-
const normalizedIndex = streamIndex % streamLimit;
|
|
191
|
-
this.options['streamIndex'] = streamIndex;
|
|
192
|
-
const streamIndexString = this.numberToString(normalizedIndex);
|
|
193
|
-
stream = 'stream-' + streamIndexString;
|
|
194
|
-
this.options['streamBySubscriptionsHash'][subscriptionHash] = stream;
|
|
195
|
-
const messageHash = 'tunnel:' + stream;
|
|
196
|
-
const request = {
|
|
197
|
-
'id': messageHash,
|
|
198
|
-
'type': 'openTunnel',
|
|
199
|
-
'newTunnelId': stream,
|
|
200
|
-
'response': true,
|
|
201
|
-
};
|
|
202
|
-
const subscription = {
|
|
203
|
-
'id': messageHash,
|
|
204
|
-
'method': this.handleNewStream,
|
|
205
|
-
};
|
|
206
|
-
await this.watch(url, messageHash, request, messageHash, subscription);
|
|
207
|
-
}
|
|
208
|
-
return stream;
|
|
209
|
-
}
|
|
210
|
-
handleOrderBookSubscription(client, message, subscription) {
|
|
211
|
-
const symbol = this.safeString(subscription, 'symbol');
|
|
212
|
-
const limit = this.safeInteger(subscription, 'limit');
|
|
213
|
-
this.orderbooks[symbol] = this.orderBook({}, limit);
|
|
214
|
-
}
|
|
215
|
-
handleSubscriptionStatus(client, message) {
|
|
216
|
-
//
|
|
217
|
-
// {
|
|
218
|
-
// "id": "1578090438322",
|
|
219
|
-
// "type": "ack"
|
|
220
|
-
// }
|
|
221
|
-
//
|
|
222
|
-
const id = this.safeString(message, 'id');
|
|
223
|
-
const subscriptionsById = this.indexBy(client.subscriptions, 'id');
|
|
224
|
-
const subscription = this.safeValue(subscriptionsById, id, {});
|
|
225
|
-
const method = this.safeValue(subscription, 'method');
|
|
226
|
-
if (method !== undefined) {
|
|
227
|
-
method.call(this, client, message, subscription);
|
|
228
|
-
}
|
|
229
|
-
return message;
|
|
230
|
-
}
|
|
231
|
-
handleNewStream(client, message, subscription) {
|
|
232
|
-
//
|
|
233
|
-
// {
|
|
234
|
-
// "id": "1545910840805",
|
|
235
|
-
// "type": "ack"
|
|
236
|
-
// }
|
|
237
|
-
//
|
|
238
|
-
const messageHash = this.safeString(message, 'id');
|
|
239
|
-
client.resolve(message, messageHash);
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* @method
|
|
243
|
-
* @name poloniexfutures#watchTicker
|
|
244
|
-
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
245
|
-
* @see https://api-docs.poloniex.com/futures/websocket/public#get-real-time-symbol-ticker
|
|
246
|
-
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
247
|
-
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
248
|
-
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
249
|
-
*/
|
|
250
|
-
async watchTicker(symbol, params = {}) {
|
|
251
|
-
await this.loadMarkets();
|
|
252
|
-
symbol = this.symbol(symbol);
|
|
253
|
-
const name = '/contractMarket/ticker';
|
|
254
|
-
return await this.subscribe(name, false, symbol, undefined, params);
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* @method
|
|
258
|
-
* @name poloniexfutures#watchTrades
|
|
259
|
-
* @description get the list of most recent trades for a particular symbol
|
|
260
|
-
* @see https://api-docs.poloniex.com/futures/websocket/public#full-matching-engine-datalevel-3
|
|
261
|
-
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
262
|
-
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
263
|
-
* @param {int} [limit] the maximum amount of trades to fetch
|
|
264
|
-
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
265
|
-
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
266
|
-
*/
|
|
267
|
-
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
268
|
-
await this.loadMarkets();
|
|
269
|
-
const options = this.safeValue(this.options, 'watchTrades');
|
|
270
|
-
let name = this.safeString(options, 'method', '/contractMarket/execution'); // can also be /contractMarket/snapshot
|
|
271
|
-
[name, params] = this.handleOptionAndParams(params, 'method', 'name', name);
|
|
272
|
-
symbol = this.symbol(symbol);
|
|
273
|
-
const trades = await this.subscribe(name, false, symbol, undefined, params);
|
|
274
|
-
if (this.newUpdates) {
|
|
275
|
-
limit = trades.getLimit(symbol, limit);
|
|
276
|
-
}
|
|
277
|
-
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* @method
|
|
281
|
-
* @name poloniexfutures#watchOrderBook
|
|
282
|
-
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
283
|
-
* @see https://api-docs.poloniex.com/futures/websocket/public#level-2-market-data
|
|
284
|
-
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
285
|
-
* @param {int} [limit] not used by poloniexfutures watchOrderBook
|
|
286
|
-
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
287
|
-
* @param {string} [params.method] the method to use. Defaults to /contractMarket/level2 can also be /contractMarket/level3v2 to receive the raw stream of orders
|
|
288
|
-
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
289
|
-
*/
|
|
290
|
-
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
291
|
-
await this.loadMarkets();
|
|
292
|
-
const options = this.safeValue(this.options, 'watchOrderBook');
|
|
293
|
-
let name = this.safeString(options, 'method', '/contractMarket/level2'); // can also be /contractMarket/level2, /contractMarket/level2Depth5:{symbol}, /contractMarket/level2Depth50:{symbol}
|
|
294
|
-
[name, params] = this.handleOptionAndParams(params, 'method', 'name', name);
|
|
295
|
-
if (name === '/contractMarket/level2' && limit !== undefined) {
|
|
296
|
-
if (limit !== 5 && limit !== 50) {
|
|
297
|
-
throw new BadRequest(this.id + ' watchOrderBook limit argument must be none, 5 or 50 if using method /contractMarket/level2');
|
|
298
|
-
}
|
|
299
|
-
name += 'Depth' + this.numberToString(limit);
|
|
300
|
-
}
|
|
301
|
-
const subscription = {
|
|
302
|
-
'symbol': symbol,
|
|
303
|
-
'limit': limit,
|
|
304
|
-
'method': this.handleOrderBookSubscription,
|
|
305
|
-
};
|
|
306
|
-
const orderbook = await this.subscribe(name, false, symbol, subscription, params);
|
|
307
|
-
return orderbook.limit();
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* @method
|
|
311
|
-
* @name poloniexfutures#watchOrders
|
|
312
|
-
* @description watches information on multiple orders made by the user
|
|
313
|
-
* @see https://api-docs.poloniex.com/futures/websocket/user-messages#private-messages
|
|
314
|
-
* @param {string} symbol filter by unified market symbol of the market orders were made in
|
|
315
|
-
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
316
|
-
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
317
|
-
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
318
|
-
* @param {string} [params.method] the method to use will default to /contractMarket/tradeOrders. Set to /contractMarket/advancedOrders to watch stop orders
|
|
319
|
-
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
320
|
-
*/
|
|
321
|
-
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
322
|
-
await this.loadMarkets();
|
|
323
|
-
const options = this.safeValue(this.options, 'watchOrders');
|
|
324
|
-
const name = this.safeString(options, 'method', '/contractMarket/tradeOrders');
|
|
325
|
-
let orders = await this.subscribe(name, true, undefined, undefined, params);
|
|
326
|
-
if (this.newUpdates) {
|
|
327
|
-
limit = orders.getLimit(symbol, limit);
|
|
328
|
-
}
|
|
329
|
-
orders = this.filterBySymbolSinceLimit(orders, symbol, since, limit);
|
|
330
|
-
const length = orders.length;
|
|
331
|
-
if (length === 0) {
|
|
332
|
-
return await this.watchOrders(symbol, since, limit, params);
|
|
333
|
-
}
|
|
334
|
-
return orders;
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* @method
|
|
338
|
-
* @name poloniexfutures#watchBalance
|
|
339
|
-
* @description watch balance and get the amount of funds available for trading or funds locked in orders
|
|
340
|
-
* @see https://api-docs.poloniex.com/futures/websocket/user-messages#account-balance-events
|
|
341
|
-
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
342
|
-
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
343
|
-
*/
|
|
344
|
-
async watchBalance(params = {}) {
|
|
345
|
-
await this.loadMarkets();
|
|
346
|
-
const name = '/contractAccount/wallet';
|
|
347
|
-
return await this.subscribe(name, true, undefined, undefined, params);
|
|
348
|
-
}
|
|
349
|
-
handleTrade(client, message) {
|
|
350
|
-
//
|
|
351
|
-
// {
|
|
352
|
-
// "data": {
|
|
353
|
-
// "makerUserId": "1410336",
|
|
354
|
-
// "symbol": "BTCUSDTPERP",
|
|
355
|
-
// "sequence": 267913,
|
|
356
|
-
// "side": "buy",
|
|
357
|
-
// "size": 2,
|
|
358
|
-
// "price": 28409.5,
|
|
359
|
-
// "takerOrderId": "6426f9f15782c8000776995f",
|
|
360
|
-
// "makerOrderId": "6426f9f141406b0008df976e",
|
|
361
|
-
// "takerUserId": "1410880",
|
|
362
|
-
// "tradeId": "6426f9f1de029f0001e334dd",
|
|
363
|
-
// "ts": 1680275953739092500,
|
|
364
|
-
// },
|
|
365
|
-
// "subject": "match",
|
|
366
|
-
// "topic": "/contractMarket/execution:BTCUSDTPERP",
|
|
367
|
-
// "type": "message",
|
|
368
|
-
// }
|
|
369
|
-
//
|
|
370
|
-
const data = this.safeValue(message, 'data', {});
|
|
371
|
-
const marketId = this.safeString(data, 'symbol');
|
|
372
|
-
if (marketId !== undefined) {
|
|
373
|
-
const trade = this.parseWsTrade(data);
|
|
374
|
-
const symbol = trade['symbol'];
|
|
375
|
-
const messageHash = '/contractMarket/execution:' + marketId;
|
|
376
|
-
let stored = this.safeValue(this.trades, symbol);
|
|
377
|
-
if (stored === undefined) {
|
|
378
|
-
const tradesLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
379
|
-
stored = new ArrayCache(tradesLimit);
|
|
380
|
-
this.trades[symbol] = stored;
|
|
381
|
-
}
|
|
382
|
-
stored.append(trade);
|
|
383
|
-
client.resolve(stored, messageHash);
|
|
384
|
-
}
|
|
385
|
-
return message;
|
|
386
|
-
}
|
|
387
|
-
parseWsTrade(trade, market = undefined) {
|
|
388
|
-
//
|
|
389
|
-
// handleTrade
|
|
390
|
-
//
|
|
391
|
-
// {
|
|
392
|
-
// "makerUserId": "1410880",
|
|
393
|
-
// "symbol": "BTCUSDTPERP",
|
|
394
|
-
// "sequence": 731390,
|
|
395
|
-
// "side": "sell",
|
|
396
|
-
// "size": 2,
|
|
397
|
-
// "price": 29372.4,
|
|
398
|
-
// "takerOrderId": "644ef0fdd64748000759218a",
|
|
399
|
-
// "makerOrderId": "644ef0fd25f4a50007f12fc5",
|
|
400
|
-
// "takerUserId": "1410880",
|
|
401
|
-
// "tradeId": "644ef0fdde029f0001eec346",
|
|
402
|
-
// "ts": 1682895101923194000
|
|
403
|
-
// }
|
|
404
|
-
//
|
|
405
|
-
const marketId = this.safeString(trade, 'symbol');
|
|
406
|
-
market = this.safeMarket(marketId, market);
|
|
407
|
-
const timestamp = this.safeIntegerProduct(trade, 'ts', 0.000001);
|
|
408
|
-
return this.safeTrade({
|
|
409
|
-
'info': trade,
|
|
410
|
-
'id': this.safeString(trade, 'tradeId'),
|
|
411
|
-
'symbol': this.safeString(market, 'symbol'),
|
|
412
|
-
'timestamp': timestamp,
|
|
413
|
-
'datetime': this.iso8601(timestamp),
|
|
414
|
-
'order': this.safeString2(trade, 'takerOrderId', 'makerOrderId'),
|
|
415
|
-
'type': undefined,
|
|
416
|
-
'side': this.safeString(trade, 'side'),
|
|
417
|
-
'takerOrMaker': undefined,
|
|
418
|
-
'price': this.safeString(trade, 'price'),
|
|
419
|
-
'amount': this.safeString2(trade, 'matchSize', 'size'),
|
|
420
|
-
'cost': undefined,
|
|
421
|
-
'fee': undefined,
|
|
422
|
-
}, market);
|
|
423
|
-
}
|
|
424
|
-
parseWsOrderTrade(trade, market = undefined) {
|
|
425
|
-
//
|
|
426
|
-
// {
|
|
427
|
-
// "symbol": "BTC_USDT",
|
|
428
|
-
// "type": "LIMIT",
|
|
429
|
-
// "quantity": "1",
|
|
430
|
-
// "orderId": "32471407854219264",
|
|
431
|
-
// "tradeFee": "0",
|
|
432
|
-
// "clientOrderId": "",
|
|
433
|
-
// "accountType": "SPOT",
|
|
434
|
-
// "feeCurrency": "",
|
|
435
|
-
// "eventType": "place",
|
|
436
|
-
// "source": "API",
|
|
437
|
-
// "side": "BUY",
|
|
438
|
-
// "filledQuantity": "0",
|
|
439
|
-
// "filledAmount": "0",
|
|
440
|
-
// "matchRole": "MAKER",
|
|
441
|
-
// "state": "NEW",
|
|
442
|
-
// "tradeTime": 0,
|
|
443
|
-
// "tradeAmount": "0",
|
|
444
|
-
// "orderAmount": "0",
|
|
445
|
-
// "createTime": 1648708186922,
|
|
446
|
-
// "price": "47112.1",
|
|
447
|
-
// "tradeQty": "0",
|
|
448
|
-
// "tradePrice": "0",
|
|
449
|
-
// "tradeId": "0",
|
|
450
|
-
// "ts": 1648708187469
|
|
451
|
-
// }
|
|
452
|
-
//
|
|
453
|
-
const timestamp = this.safeInteger(trade, 'tradeTime');
|
|
454
|
-
const marketId = this.safeString(trade, 'symbol');
|
|
455
|
-
return this.safeTrade({
|
|
456
|
-
'info': trade,
|
|
457
|
-
'id': this.safeString(trade, 'tradeId'),
|
|
458
|
-
'symbol': this.safeSymbol(marketId, market),
|
|
459
|
-
'timestamp': timestamp,
|
|
460
|
-
'datetime': this.iso8601(timestamp),
|
|
461
|
-
'order': this.safeString(trade, 'orderId'),
|
|
462
|
-
'type': this.safeStringLower(trade, 'type'),
|
|
463
|
-
'side': this.safeString(trade, 'side'),
|
|
464
|
-
'takerOrMaker': this.safeStringLower(trade, 'matchRole'),
|
|
465
|
-
'price': this.safeString(trade, 'price'),
|
|
466
|
-
'amount': this.safeString(trade, 'tradeAmount'),
|
|
467
|
-
'cost': undefined,
|
|
468
|
-
'fee': {
|
|
469
|
-
'rate': undefined,
|
|
470
|
-
'cost': this.safeString(trade, 'tradeFee'),
|
|
471
|
-
'currency': this.safeString(trade, 'feeCurrency'),
|
|
472
|
-
},
|
|
473
|
-
}, market);
|
|
474
|
-
}
|
|
475
|
-
handleOrder(client, message) {
|
|
476
|
-
//
|
|
477
|
-
// {
|
|
478
|
-
// "data": {
|
|
479
|
-
// "symbol": "ADAUSDTPERP",
|
|
480
|
-
// "orderType": "limit",
|
|
481
|
-
// "side": "buy",
|
|
482
|
-
// "canceledSize": "1",
|
|
483
|
-
// "orderId": "642b4d4c0494cd0007c76813",
|
|
484
|
-
// "type": "canceled",
|
|
485
|
-
// "orderTime": "1680559436101909048",
|
|
486
|
-
// "size": "1",
|
|
487
|
-
// "filledSize": "0",
|
|
488
|
-
// "marginType": 1,
|
|
489
|
-
// "price": "0.25",
|
|
490
|
-
// "remainSize": "0",
|
|
491
|
-
// "clientOid": "112cbbf1-95a3-4917-957c-d3a87d81f853",
|
|
492
|
-
// "status": "done",
|
|
493
|
-
// "ts": 1680559677560686600
|
|
494
|
-
// },
|
|
495
|
-
// "subject": "orderChange",
|
|
496
|
-
// "topic": "/contractMarket/tradeOrders",
|
|
497
|
-
// "channelType": "private",
|
|
498
|
-
// "type": "message",
|
|
499
|
-
// "userId": "1139790"
|
|
500
|
-
// }
|
|
501
|
-
// stop order
|
|
502
|
-
// {
|
|
503
|
-
// "data": {
|
|
504
|
-
// "orderType": "stop",
|
|
505
|
-
// "symbol": "BTCUSDTPERP",
|
|
506
|
-
// "side": "buy",
|
|
507
|
-
// "stopPriceType": "TP",
|
|
508
|
-
// "orderId": "64514fe1850d2100074378f6",
|
|
509
|
-
// "type": "open",
|
|
510
|
-
// "createdAt": 1683050465847,
|
|
511
|
-
// "stopPrice": "29000",
|
|
512
|
-
// "size": 2,
|
|
513
|
-
// "stop": "up",
|
|
514
|
-
// "marginType": 0,
|
|
515
|
-
// "orderPrice": "28552.9",
|
|
516
|
-
// "ts": 1683050465847597300
|
|
517
|
-
// },
|
|
518
|
-
// "subject": "stopOrder",
|
|
519
|
-
// "topic": "/contractMarket/advancedOrders",
|
|
520
|
-
// "channelType": "private",
|
|
521
|
-
// "id": "64514fe1850d2100074378fa",
|
|
522
|
-
// "type": "message",
|
|
523
|
-
// "userId": "1160396"
|
|
524
|
-
// }
|
|
525
|
-
//
|
|
526
|
-
const data = this.safeValue(message, 'data', {});
|
|
527
|
-
let orders = this.orders;
|
|
528
|
-
if (orders === undefined) {
|
|
529
|
-
const limit = this.safeInteger(this.options, 'ordersLimit');
|
|
530
|
-
orders = new ArrayCacheBySymbolById(limit);
|
|
531
|
-
this.orders = orders;
|
|
532
|
-
}
|
|
533
|
-
const messageHash = '/contractMarket/tradeOrders';
|
|
534
|
-
const parsed = this.parseWsOrder(data);
|
|
535
|
-
orders.append(parsed);
|
|
536
|
-
client.resolve(orders, messageHash);
|
|
537
|
-
return message;
|
|
538
|
-
}
|
|
539
|
-
parseOrderStatus(status, type) {
|
|
540
|
-
/**
|
|
541
|
-
* @ignore
|
|
542
|
-
* @method
|
|
543
|
-
* @param {string} status "match", "open", "done"
|
|
544
|
-
* @param {string} type "open", "match", "filled", "canceled", "update"
|
|
545
|
-
* @returns {string}
|
|
546
|
-
*/
|
|
547
|
-
const types = {
|
|
548
|
-
'canceled': 'canceled',
|
|
549
|
-
'cancel': 'canceled',
|
|
550
|
-
'filled': 'closed',
|
|
551
|
-
};
|
|
552
|
-
let parsedStatus = this.safeString(types, type);
|
|
553
|
-
if (parsedStatus === undefined) {
|
|
554
|
-
const statuses = {
|
|
555
|
-
'open': 'open',
|
|
556
|
-
'match': 'open',
|
|
557
|
-
'done': 'closed',
|
|
558
|
-
};
|
|
559
|
-
parsedStatus = this.safeString(statuses, status, status);
|
|
560
|
-
}
|
|
561
|
-
return parsedStatus;
|
|
562
|
-
}
|
|
563
|
-
parseWsOrder(order, market = undefined) {
|
|
564
|
-
//
|
|
565
|
-
// {
|
|
566
|
-
// "symbol": "ADAUSDTPERP",
|
|
567
|
-
// "orderType": "limit",
|
|
568
|
-
// "side": "buy",
|
|
569
|
-
// "canceledSize": "1",
|
|
570
|
-
// "orderId": "642b4d4c0494cd0007c76813",
|
|
571
|
-
// "type": "canceled",
|
|
572
|
-
// "orderTime": "1680559436101909048",
|
|
573
|
-
// "size": "1",
|
|
574
|
-
// "filledSize": "0",
|
|
575
|
-
// "marginType": 1,
|
|
576
|
-
// "price": "0.25",
|
|
577
|
-
// "remainSize": "0",
|
|
578
|
-
// "clientOid": "112cbbf1-95a3-4917-957c-d3a87d81f853",
|
|
579
|
-
// "status": "done",
|
|
580
|
-
// "ts": 1680559677560686600
|
|
581
|
-
// }
|
|
582
|
-
// stop
|
|
583
|
-
// {
|
|
584
|
-
// "orderType": "stop",
|
|
585
|
-
// "symbol": "BTCUSDTPERP",
|
|
586
|
-
// "side": "buy",
|
|
587
|
-
// "stopPriceType": "TP",
|
|
588
|
-
// "orderId": "64514fe1850d2100074378f6",
|
|
589
|
-
// "type": "open",
|
|
590
|
-
// "createdAt": 1683050465847,
|
|
591
|
-
// "stopPrice": "29000",
|
|
592
|
-
// "size": 2,
|
|
593
|
-
// "stop": "up",
|
|
594
|
-
// "marginType": 0,
|
|
595
|
-
// "orderPrice": "28552.9",
|
|
596
|
-
// "ts": 1683050465847597300
|
|
597
|
-
// }
|
|
598
|
-
//
|
|
599
|
-
const id = this.safeString(order, 'orderId');
|
|
600
|
-
const clientOrderId = this.safeString(order, 'clientOid');
|
|
601
|
-
const marketId = this.safeString(order, 'symbol');
|
|
602
|
-
const timestamp = this.safeIntegerProduct2(order, 'orderTime', 'ts', 0.000001);
|
|
603
|
-
const status = this.safeString(order, 'status');
|
|
604
|
-
const messageType = this.safeString(order, 'type');
|
|
605
|
-
return this.safeOrder({
|
|
606
|
-
'info': order,
|
|
607
|
-
'symbol': this.safeSymbol(marketId, market),
|
|
608
|
-
'id': id,
|
|
609
|
-
'clientOrderId': clientOrderId,
|
|
610
|
-
'timestamp': timestamp,
|
|
611
|
-
'datetime': this.iso8601(timestamp),
|
|
612
|
-
'lastTradeTimestamp': undefined,
|
|
613
|
-
'type': this.safeString(order, 'orderType'),
|
|
614
|
-
'timeInForce': undefined,
|
|
615
|
-
'postOnly': undefined,
|
|
616
|
-
'side': this.safeString(order, 'side'),
|
|
617
|
-
'price': this.safeString2(order, 'price', 'orderPrice'),
|
|
618
|
-
'stopPrice': this.safeString(order, 'stopPrice'),
|
|
619
|
-
'triggerPrice': undefined,
|
|
620
|
-
'amount': this.safeString(order, 'size'),
|
|
621
|
-
'cost': undefined,
|
|
622
|
-
'average': undefined,
|
|
623
|
-
'filled': this.safeString(order, 'filledSize'),
|
|
624
|
-
'remaining': this.safeString(order, 'remainSize'),
|
|
625
|
-
'status': this.parseOrderStatus(status, messageType),
|
|
626
|
-
'fee': undefined,
|
|
627
|
-
'trades': undefined,
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
handleTicker(client, message) {
|
|
631
|
-
//
|
|
632
|
-
// {
|
|
633
|
-
// "subject": "ticker",
|
|
634
|
-
// "topic": "/contractMarket/ticker:BTCUSDTPERP",
|
|
635
|
-
// "data": {
|
|
636
|
-
// "symbol": "BTCUSDTPERP", // Market of the symbol
|
|
637
|
-
// "sequence": 45, // Sequence number which is used to judge the continuity of the pushed messages
|
|
638
|
-
// "side": "sell", // Transaction side of the last traded taker order
|
|
639
|
-
// "price": 3600.00, // Filled price
|
|
640
|
-
// "size": 16, // Filled quantity
|
|
641
|
-
// "tradeId": "5c9dcf4170744d6f5a3d32fb", // Order ID
|
|
642
|
-
// "bestBidSize": 795, // Best bid size
|
|
643
|
-
// "bestBidPrice": 3200.00, // Best bid
|
|
644
|
-
// "bestAskPrice": 3600.00, // Best ask size
|
|
645
|
-
// "bestAskSize": 284, // Best ask
|
|
646
|
-
// "ts": 1553846081210004941 // Filled time - nanosecond
|
|
647
|
-
// },
|
|
648
|
-
// "type": "message",
|
|
649
|
-
// }
|
|
650
|
-
//
|
|
651
|
-
// {
|
|
652
|
-
// "topic": "/contractMarket/snapshot:BTCUSDTPERP",
|
|
653
|
-
// "subject": "snapshot.24h",
|
|
654
|
-
// "data": {
|
|
655
|
-
// "volume": 30449670, //24h Volume
|
|
656
|
-
// "turnover": 845169919063, //24h Turnover
|
|
657
|
-
// "lastPrice": 3551, //Last price
|
|
658
|
-
// "priceChgPct": 0.0043, //24h Change
|
|
659
|
-
// "ts": 1547697294838004923 //Snapshot time (nanosecond)
|
|
660
|
-
// }
|
|
661
|
-
// }
|
|
662
|
-
//
|
|
663
|
-
const data = this.safeValue(message, 'data', {});
|
|
664
|
-
const messageHash = this.safeString(message, 'topic');
|
|
665
|
-
const symbol = this.getSymbolFromTopic(messageHash);
|
|
666
|
-
if (symbol !== undefined) {
|
|
667
|
-
const ticker = this.parseTicker(data);
|
|
668
|
-
this.tickers[symbol] = ticker;
|
|
669
|
-
client.resolve(ticker, messageHash);
|
|
670
|
-
}
|
|
671
|
-
return message;
|
|
672
|
-
}
|
|
673
|
-
handleL3OrderBook(client, message) {
|
|
674
|
-
//
|
|
675
|
-
// {
|
|
676
|
-
// "data": {
|
|
677
|
-
// "symbol": "BTCUSDTPERP",
|
|
678
|
-
// "sequence": 1679593048010,
|
|
679
|
-
// "orderId": "6426fec8586b9500089d64d8",
|
|
680
|
-
// "clientOid": "14e6ee8e-8757-462c-84db-ed12c2b62f55",
|
|
681
|
-
// "ts": 1680277192127513900
|
|
682
|
-
// },
|
|
683
|
-
// "subject": "received",
|
|
684
|
-
// "topic": "/contractMarket/level3v2:BTCUSDTPERP",
|
|
685
|
-
// "type": "message"
|
|
686
|
-
// }
|
|
687
|
-
//
|
|
688
|
-
// {
|
|
689
|
-
// "data": {
|
|
690
|
-
// "symbol": "BTCUSDTPERP",
|
|
691
|
-
// "sequence": 1679593047982,
|
|
692
|
-
// "side": "sell",
|
|
693
|
-
// "orderTime": "1680277191900131371",
|
|
694
|
-
// "size": "1",
|
|
695
|
-
// "orderId": "6426fec7d32b6e000790268b",
|
|
696
|
-
// "price": "28376.4",
|
|
697
|
-
// "ts": 1680277191939042300
|
|
698
|
-
// },
|
|
699
|
-
// "subject": "open",
|
|
700
|
-
// "topic": "/contractMarket/level3v2:BTCUSDTPERP",
|
|
701
|
-
// "type": "message"
|
|
702
|
-
// }
|
|
703
|
-
//
|
|
704
|
-
// {
|
|
705
|
-
// "data": {
|
|
706
|
-
// "symbol": "BTCUSDTPERP",
|
|
707
|
-
// "reason": "canceled", // or "filled"
|
|
708
|
-
// "sequence": 1679593047983,
|
|
709
|
-
// "orderId": "6426fec74026fa0008e7046f",
|
|
710
|
-
// "ts": 1680277191949842000
|
|
711
|
-
// },
|
|
712
|
-
// "subject": "done",
|
|
713
|
-
// "topic": "/contractMarket/level3v2:BTCUSDTPERP",
|
|
714
|
-
// "type": "message"
|
|
715
|
-
// }
|
|
716
|
-
//
|
|
717
|
-
const messageHash = this.safeString(message, 'topic');
|
|
718
|
-
const subject = this.safeString(message, 'subject');
|
|
719
|
-
if (subject === 'received') {
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
// At the time of writting this, there is no implementation to easily convert each order into the orderbook so raw messages are returned
|
|
723
|
-
client.resolve(message, messageHash);
|
|
724
|
-
}
|
|
725
|
-
handleLevel2(client, message) {
|
|
726
|
-
// {
|
|
727
|
-
// "subject": "level2",
|
|
728
|
-
// "topic": "/contractMarket/level2:BTCUSDTPERP",
|
|
729
|
-
// "type": "message",
|
|
730
|
-
// "data": {
|
|
731
|
-
// "sequence": 18, // Sequence number which is used to judge the continuity of pushed messages
|
|
732
|
-
// "change": "5000.0,sell,83" // Price, side, quantity
|
|
733
|
-
// "timestamp": 1551770400000
|
|
734
|
-
// }
|
|
735
|
-
// }
|
|
736
|
-
const topic = this.safeString(message, 'topic');
|
|
737
|
-
const isSnapshot = topic.indexOf('Depth') >= 0;
|
|
738
|
-
if (isSnapshot) {
|
|
739
|
-
this.handeL2Snapshot(client, message);
|
|
740
|
-
return;
|
|
741
|
-
}
|
|
742
|
-
this.handleL2OrderBook(client, message);
|
|
743
|
-
}
|
|
744
|
-
handleL2OrderBook(client, message) {
|
|
745
|
-
//
|
|
746
|
-
// {
|
|
747
|
-
// "id": 1545910660740,
|
|
748
|
-
// "type": "subscribe",
|
|
749
|
-
// "topic": "/contractMarket/level2:BTCUSDTPERP",
|
|
750
|
-
// "response": true
|
|
751
|
-
// }
|
|
752
|
-
//
|
|
753
|
-
// {
|
|
754
|
-
// "subject": "level2",
|
|
755
|
-
// "topic": "/contractMarket/level2:BTCUSDTPERP",
|
|
756
|
-
// "type": "message",
|
|
757
|
-
// "data": {
|
|
758
|
-
// "sequence": 18, // Sequence number which is used to judge the continuity of pushed messages
|
|
759
|
-
// "change": "5000.0,sell,83" // Price, side, quantity
|
|
760
|
-
// "timestamp": 1551770400000
|
|
761
|
-
// }
|
|
762
|
-
// }
|
|
763
|
-
//
|
|
764
|
-
const data = this.safeValue(message, 'data', {});
|
|
765
|
-
const messageHash = this.safeString(message, 'topic', '');
|
|
766
|
-
const symbol = this.getSymbolFromTopic(messageHash);
|
|
767
|
-
let orderBook = this.safeValue(this.orderbooks, symbol);
|
|
768
|
-
if (orderBook === undefined) {
|
|
769
|
-
this.orderbooks[symbol] = this.orderBook({});
|
|
770
|
-
orderBook = this.orderbooks[symbol];
|
|
771
|
-
orderBook['symbol'] = symbol;
|
|
772
|
-
}
|
|
773
|
-
const nonce = this.safeInteger(orderBook, 'nonce');
|
|
774
|
-
if (nonce === undefined) {
|
|
775
|
-
const cacheLength = orderBook.cache.length;
|
|
776
|
-
const snapshotDelay = this.handleOption('watchOrderBook', 'snapshotDelay', 5);
|
|
777
|
-
if (cacheLength === snapshotDelay) {
|
|
778
|
-
const limit = 0;
|
|
779
|
-
this.spawn(this.loadOrderBook, client, messageHash, symbol, limit, {});
|
|
780
|
-
}
|
|
781
|
-
orderBook.cache.push(data);
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
try {
|
|
785
|
-
this.handleDelta(orderBook, data);
|
|
786
|
-
client.resolve(orderBook, messageHash);
|
|
787
|
-
}
|
|
788
|
-
catch (e) {
|
|
789
|
-
delete this.orderbooks[symbol];
|
|
790
|
-
client.reject(e, messageHash);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
handeL2Snapshot(client, message) {
|
|
794
|
-
//
|
|
795
|
-
// {
|
|
796
|
-
// "type": "message",
|
|
797
|
-
// "topic": "/contractMarket/level2Depth5:BTCUSDTPERP",
|
|
798
|
-
// "subject": "level2",
|
|
799
|
-
// "data": {
|
|
800
|
-
// "asks": [
|
|
801
|
-
// ["9993", "3"],
|
|
802
|
-
// ["9992", "3"],
|
|
803
|
-
// ["9991", "47"],
|
|
804
|
-
// ["9990", "32"],
|
|
805
|
-
// ["9989", "8"]
|
|
806
|
-
// ],
|
|
807
|
-
// "bids": [
|
|
808
|
-
// ["9988", "56"],
|
|
809
|
-
// ["9987", "15"],
|
|
810
|
-
// ["9986", "100"],
|
|
811
|
-
// ["9985", "10"],
|
|
812
|
-
// ["9984", "10"]
|
|
813
|
-
// ],
|
|
814
|
-
// "timestamp": 1682993050531,
|
|
815
|
-
// }
|
|
816
|
-
// }
|
|
817
|
-
//
|
|
818
|
-
const data = this.safeValue(message, 'data', {});
|
|
819
|
-
const messageHash = this.safeString(message, 'topic', '');
|
|
820
|
-
const symbol = this.getSymbolFromTopic(messageHash);
|
|
821
|
-
const timestamp = this.safeInteger(data, 'timestamp');
|
|
822
|
-
const snapshot = this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks');
|
|
823
|
-
const orderbook = this.orderBook(snapshot);
|
|
824
|
-
this.orderbooks[symbol] = orderbook;
|
|
825
|
-
client.resolve(orderbook, messageHash);
|
|
826
|
-
}
|
|
827
|
-
getSymbolFromTopic(topic) {
|
|
828
|
-
const splitTopic = topic.split(':');
|
|
829
|
-
const marketId = this.safeString(splitTopic, 1);
|
|
830
|
-
return this.safeSymbol(marketId);
|
|
831
|
-
}
|
|
832
|
-
getCacheIndex(orderbook, cache) {
|
|
833
|
-
const firstDelta = this.safeValue(cache, 0);
|
|
834
|
-
const nonce = this.safeInteger(orderbook, 'nonce');
|
|
835
|
-
const firstDeltaSequence = this.safeInteger(firstDelta, 'sequence');
|
|
836
|
-
if (firstDeltaSequence > nonce + 1) {
|
|
837
|
-
return -1;
|
|
838
|
-
}
|
|
839
|
-
for (let i = 0; i < cache.length; i++) {
|
|
840
|
-
const delta = cache[i];
|
|
841
|
-
const sequence = this.safeInteger(delta, 'sequence');
|
|
842
|
-
if (nonce === sequence - 1) {
|
|
843
|
-
return i;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
return cache.length;
|
|
847
|
-
}
|
|
848
|
-
handleDelta(orderbook, delta) {
|
|
849
|
-
//
|
|
850
|
-
// {
|
|
851
|
-
// sequence: 123677914,
|
|
852
|
-
// lastSequence: 123677913,
|
|
853
|
-
// change: '80.36,buy,4924',
|
|
854
|
-
// changes: [ '80.19,buy,0',"80.15,buy,10794" ],
|
|
855
|
-
// timestamp: 1715643483528
|
|
856
|
-
// },
|
|
857
|
-
//
|
|
858
|
-
const sequence = this.safeInteger(delta, 'sequence');
|
|
859
|
-
const lastSequence = this.safeInteger(delta, 'lastSequence');
|
|
860
|
-
const nonce = this.safeInteger(orderbook, 'nonce');
|
|
861
|
-
if (nonce > sequence) {
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
if (nonce !== lastSequence) {
|
|
865
|
-
const checksum = this.handleOption('watchOrderBook', 'checksum', true);
|
|
866
|
-
if (checksum) {
|
|
867
|
-
throw new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(''));
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
const changes = this.safeList(delta, 'changes');
|
|
871
|
-
for (let i = 0; i < changes.length; i++) {
|
|
872
|
-
const change = changes[i];
|
|
873
|
-
const splitChange = change.split(',');
|
|
874
|
-
const price = this.safeNumber(splitChange, 0);
|
|
875
|
-
const side = this.safeString(splitChange, 1);
|
|
876
|
-
const size = this.safeNumber(splitChange, 2);
|
|
877
|
-
const orderBookSide = (side === 'buy') ? orderbook['bids'] : orderbook['asks'];
|
|
878
|
-
orderBookSide.store(price, size);
|
|
879
|
-
}
|
|
880
|
-
const timestamp = this.safeInteger(delta, 'timestamp');
|
|
881
|
-
orderbook['timestamp'] = timestamp;
|
|
882
|
-
orderbook['datetime'] = this.iso8601(timestamp);
|
|
883
|
-
orderbook['nonce'] = sequence;
|
|
884
|
-
}
|
|
885
|
-
handleBalance(client, message) {
|
|
886
|
-
//
|
|
887
|
-
// {
|
|
888
|
-
// "data": {
|
|
889
|
-
// "currency": "USDT",
|
|
890
|
-
// "availableBalance": "4.0000000000",
|
|
891
|
-
// "timestamp": "1680557568670"
|
|
892
|
-
// },
|
|
893
|
-
// "subject": "availableBalance.change",
|
|
894
|
-
// "topic": "/contractAccount/wallet",
|
|
895
|
-
// "channelType": "private",
|
|
896
|
-
// "id": "642b4600cae86800074b5ab7",
|
|
897
|
-
// "type": "message",
|
|
898
|
-
// "userId": "1139790"
|
|
899
|
-
// }
|
|
900
|
-
//
|
|
901
|
-
// {
|
|
902
|
-
// "data": {
|
|
903
|
-
// "currency": "USDT",
|
|
904
|
-
// "orderMargin": "0.0000000000",
|
|
905
|
-
// "timestamp": "1680558743307"
|
|
906
|
-
// },
|
|
907
|
-
// "subject": "orderMargin.change",
|
|
908
|
-
// "topic": "/contractAccount/wallet",
|
|
909
|
-
// "channelType": "private",
|
|
910
|
-
// "id": "642b4a97b58e360007c3a237",
|
|
911
|
-
// "type": "message",
|
|
912
|
-
// "userId": "1139790"
|
|
913
|
-
// }
|
|
914
|
-
//
|
|
915
|
-
const data = this.safeValue(message, 'data', []);
|
|
916
|
-
const messageHash = '/contractAccount/wallet';
|
|
917
|
-
const currencyId = this.safeString(data, 'currency');
|
|
918
|
-
const currency = this.currency(currencyId);
|
|
919
|
-
const code = currency['code'];
|
|
920
|
-
this.balance[code] = this.parseWsBalance(data);
|
|
921
|
-
client.resolve(this.balance[code], messageHash);
|
|
922
|
-
return message;
|
|
923
|
-
}
|
|
924
|
-
parseWsBalance(response) {
|
|
925
|
-
//
|
|
926
|
-
// {
|
|
927
|
-
// "currency": "USDT",
|
|
928
|
-
// "availableBalance": "4.0000000000",
|
|
929
|
-
// "timestamp": "1680557568670"
|
|
930
|
-
// }
|
|
931
|
-
//
|
|
932
|
-
// {
|
|
933
|
-
// "currency": "USDT",
|
|
934
|
-
// "orderMargin": "0.0000000000",
|
|
935
|
-
// "timestamp": "1680558743307"
|
|
936
|
-
// }
|
|
937
|
-
//
|
|
938
|
-
const timestamp = this.safeInteger(response, 'timestamp');
|
|
939
|
-
const result = {
|
|
940
|
-
'info': response,
|
|
941
|
-
'timestamp': timestamp,
|
|
942
|
-
'datetime': this.iso8601(timestamp),
|
|
943
|
-
};
|
|
944
|
-
const currencyId = this.safeString(response, 'currency');
|
|
945
|
-
const code = this.safeCurrencyCode(currencyId);
|
|
946
|
-
const newAccount = this.account();
|
|
947
|
-
newAccount['free'] = this.safeString(response, 'availableBalance');
|
|
948
|
-
result[code] = newAccount;
|
|
949
|
-
return this.safeBalance(result);
|
|
950
|
-
}
|
|
951
|
-
handleSystemStatus(client, message) {
|
|
952
|
-
//
|
|
953
|
-
// {
|
|
954
|
-
// "id": "1578090234088", // connectId
|
|
955
|
-
// "type": "welcome",
|
|
956
|
-
// }
|
|
957
|
-
//
|
|
958
|
-
return message;
|
|
959
|
-
}
|
|
960
|
-
handleSubject(client, message) {
|
|
961
|
-
const subject = this.safeString(message, 'subject');
|
|
962
|
-
const methods = {
|
|
963
|
-
'auth': this.handleAuthenticate,
|
|
964
|
-
'received': this.handleL3OrderBook,
|
|
965
|
-
'open': this.handleL3OrderBook,
|
|
966
|
-
'update': this.handleL3OrderBook,
|
|
967
|
-
'done': this.handleL3OrderBook,
|
|
968
|
-
'level2': this.handleLevel2,
|
|
969
|
-
'ticker': this.handleTicker,
|
|
970
|
-
'snapshot.24h': this.handleTicker,
|
|
971
|
-
'match': this.handleTrade,
|
|
972
|
-
'orderChange': this.handleOrder,
|
|
973
|
-
'stopOrder': this.handleOrder,
|
|
974
|
-
'availableBalance.change': this.handleBalance,
|
|
975
|
-
'orderMargin.change': this.handleBalance,
|
|
976
|
-
};
|
|
977
|
-
const method = this.safeValue(methods, subject);
|
|
978
|
-
if (method !== undefined) {
|
|
979
|
-
method.call(this, client, message);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
ping(client) {
|
|
983
|
-
const id = this.requestId().toString();
|
|
984
|
-
return {
|
|
985
|
-
'id': id,
|
|
986
|
-
'type': 'ping',
|
|
987
|
-
};
|
|
988
|
-
}
|
|
989
|
-
handlePong(client, message) {
|
|
990
|
-
client.lastPong = this.milliseconds();
|
|
991
|
-
return message;
|
|
992
|
-
}
|
|
993
|
-
handleErrorMessage(client, message) {
|
|
994
|
-
//
|
|
995
|
-
// {
|
|
996
|
-
// "code": 404,
|
|
997
|
-
// "data": "tunnel stream-0 is not exist",
|
|
998
|
-
// "id": "3",
|
|
999
|
-
// "type": "error"
|
|
1000
|
-
// }
|
|
1001
|
-
//
|
|
1002
|
-
client.reject(message);
|
|
1003
|
-
}
|
|
1004
|
-
handleMessage(client, message) {
|
|
1005
|
-
const type = this.safeString(message, 'type');
|
|
1006
|
-
const methods = {
|
|
1007
|
-
'welcome': this.handleSystemStatus,
|
|
1008
|
-
'ack': this.handleSubscriptionStatus,
|
|
1009
|
-
'message': this.handleSubject,
|
|
1010
|
-
'pong': this.handlePong,
|
|
1011
|
-
'error': this.handleErrorMessage,
|
|
1012
|
-
};
|
|
1013
|
-
const method = this.safeValue(methods, type);
|
|
1014
|
-
if (method !== undefined) {
|
|
1015
|
-
method.call(this, client, message);
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
handleAuthenticate(client, message) {
|
|
1019
|
-
//
|
|
1020
|
-
// {
|
|
1021
|
-
// "success": true,
|
|
1022
|
-
// "ret_msg": '',
|
|
1023
|
-
// "op": "auth",
|
|
1024
|
-
// "conn_id": "ce3dpomvha7dha97tvp0-2xh"
|
|
1025
|
-
// }
|
|
1026
|
-
//
|
|
1027
|
-
const data = this.safeValue(message, 'data');
|
|
1028
|
-
const success = this.safeValue(data, 'success');
|
|
1029
|
-
const messageHash = 'authenticated';
|
|
1030
|
-
if (success) {
|
|
1031
|
-
client.resolve(message, messageHash);
|
|
1032
|
-
}
|
|
1033
|
-
else {
|
|
1034
|
-
const error = new AuthenticationError(this.id + ' ' + this.json(message));
|
|
1035
|
-
client.reject(error, messageHash);
|
|
1036
|
-
if (messageHash in client.subscriptions) {
|
|
1037
|
-
delete client.subscriptions[messageHash];
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
return message;
|
|
1041
|
-
}
|
|
1042
|
-
}
|