bfx-api-node-ws1 1.0.0 → 1.0.4
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/.eslintrc +3 -0
- package/.eslintrc.json +26 -0
- package/.github/ISSUE_TEMPLATE +13 -0
- package/.github/PULL_REQUEST_TEMPLATE +17 -0
- package/.travis.yml +7 -0
- package/CHANGELOG +14 -0
- package/README.md +41 -1
- package/docs/.keep +0 -0
- package/docs/ws1_docs.md +114 -0
- package/lib/ws.js +65 -7
- package/package.json +17 -11
- package/test/lib/ws-1-handle-channel.js +14 -14
- package/test/lib/ws-1-parsing.js +24 -8
- package/test/lib/ws-1-test.js +165 -158
package/.eslintrc
ADDED
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"parser": "babel-eslint",
|
|
3
|
+
"extends": [
|
|
4
|
+
"standard"
|
|
5
|
+
],
|
|
6
|
+
"rules": {
|
|
7
|
+
"jsx-quotes": ["error", "prefer-single"],
|
|
8
|
+
"semi": [1, "never"],
|
|
9
|
+
"max-len": 0,
|
|
10
|
+
"import/no-named-as-default": 0,
|
|
11
|
+
"import/no-named-as-default-member": 0
|
|
12
|
+
},
|
|
13
|
+
"settings": {
|
|
14
|
+
"import/resolver": {
|
|
15
|
+
"node": {
|
|
16
|
+
"moduleDirectory": [
|
|
17
|
+
"node_modules",
|
|
18
|
+
"lib"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"env": {
|
|
24
|
+
"jest": true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
### Description:
|
|
2
|
+
...
|
|
3
|
+
|
|
4
|
+
### Breaking changes:
|
|
5
|
+
- [ ]
|
|
6
|
+
|
|
7
|
+
### New features:
|
|
8
|
+
- [ ]
|
|
9
|
+
|
|
10
|
+
### Fixes:
|
|
11
|
+
- [ ]
|
|
12
|
+
|
|
13
|
+
### PR status:
|
|
14
|
+
- [ ] Version bumped
|
|
15
|
+
- [ ] Change-log updated
|
|
16
|
+
- [ ] Tests added or updated
|
|
17
|
+
- [ ] Documentation updated
|
package/.travis.yml
CHANGED
package/CHANGELOG
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 1.0.3
|
|
2
|
+
- fix: use relative paths to allow generic mocha execution
|
|
3
|
+
- feature: add isOpen() method
|
|
4
|
+
|
|
5
|
+
# 1.0.2
|
|
6
|
+
- docs: create/update
|
|
7
|
+
|
|
8
|
+
# 1.0.1
|
|
9
|
+
- manifest: bump deps
|
|
10
|
+
- meta: add github issue/pr templates
|
|
11
|
+
- meta: standardize travis config
|
|
12
|
+
|
|
13
|
+
# 1.0.0
|
|
14
|
+
- Initial version
|
package/README.md
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
|
-
# Bitfinex WSv1 Reference Implementation
|
|
1
|
+
# Bitfinex WSv1 Reference Implementation for Node.JS
|
|
2
2
|
|
|
3
3
|
[](https://travis-ci.org/bitfinexcom/bfx-api-node-ws1)
|
|
4
4
|
|
|
5
5
|
This repo contains the reference implementation for version 1 of the websocket Bitfinex API. It is deprecated in favour of version 2, and should no longer be used.
|
|
6
6
|
|
|
7
7
|
For the version 2 API library, see [bitfinex-api-node](https://github.com/bitfinexcom/bitfinex-api-node)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Emits API data as events from the class instance
|
|
12
|
+
* Provides methods for channel management & listening to incoming data
|
|
13
|
+
|
|
14
|
+
### Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm i --save bfx-api-node-ws1
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Quickstart & Example
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
const WSv1 = require('bfx-api-node-ws1')
|
|
24
|
+
const ws = new WSv1()
|
|
25
|
+
|
|
26
|
+
ws.open()
|
|
27
|
+
|
|
28
|
+
ws.on('open', () => {
|
|
29
|
+
ws.subscribeTrades('BTCUSD')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
ws.on('trades', (pair, trade) => {
|
|
33
|
+
console.log(JSON.stringify({ pair, trade }, null, 2))
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Docs
|
|
38
|
+
|
|
39
|
+
For JSDoc-generated API documentation, [see `docs/ws1.md`](/docs/ws1.md)
|
|
40
|
+
|
|
41
|
+
### Contributing
|
|
42
|
+
|
|
43
|
+
1. Fork it
|
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
47
|
+
5. Create a new Pull Request
|
package/docs/.keep
ADDED
|
File without changes
|
package/docs/ws1_docs.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<a name="WSv1"></a>
|
|
2
|
+
|
|
3
|
+
## WSv1
|
|
4
|
+
Communicates with v1 of the Bitfinex WebSocket API
|
|
5
|
+
|
|
6
|
+
**Kind**: global class
|
|
7
|
+
|
|
8
|
+
* [WSv1](#WSv1)
|
|
9
|
+
* [new WSv1()](#new_WSv1_new)
|
|
10
|
+
* [.open()](#WSv1+open)
|
|
11
|
+
* [.close()](#WSv1+close)
|
|
12
|
+
* [.send(msg)](#WSv1+send)
|
|
13
|
+
* [.subscribeOrderBook(pair, precision, length)](#WSv1+subscribeOrderBook)
|
|
14
|
+
* [.subscribeTrades(pair)](#WSv1+subscribeTrades)
|
|
15
|
+
* [.subscribeTicker(pair)](#WSv1+subscribeTicker)
|
|
16
|
+
* [.unsubscribe(chanId)](#WSv1+unsubscribe)
|
|
17
|
+
* [.auth()](#WSv1+auth)
|
|
18
|
+
|
|
19
|
+
<a name="new_WSv1_new"></a>
|
|
20
|
+
|
|
21
|
+
### new WSv1()
|
|
22
|
+
|
|
23
|
+
| Param | Type | Description |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| opts.apiKey | <code>sting</code> | |
|
|
26
|
+
| opts.apiSecret | <code>string</code> | |
|
|
27
|
+
| opts.url | <code>string</code> | ws connection url |
|
|
28
|
+
|
|
29
|
+
<a name="WSv1+open"></a>
|
|
30
|
+
|
|
31
|
+
### wSv1.open()
|
|
32
|
+
Opens a new websocket conection to the configured URL
|
|
33
|
+
|
|
34
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
35
|
+
<a name="WSv1+close"></a>
|
|
36
|
+
|
|
37
|
+
### wSv1.close()
|
|
38
|
+
Close the websocket connection
|
|
39
|
+
|
|
40
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
41
|
+
<a name="WSv1+send"></a>
|
|
42
|
+
|
|
43
|
+
### wSv1.send(msg)
|
|
44
|
+
Send a packet via the ws connection; automatically converted to a JSON
|
|
45
|
+
string.
|
|
46
|
+
|
|
47
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
48
|
+
|
|
49
|
+
| Param | Type |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| msg | <code>\*</code> |
|
|
52
|
+
|
|
53
|
+
<a name="WSv1+subscribeOrderBook"></a>
|
|
54
|
+
|
|
55
|
+
### wSv1.subscribeOrderBook(pair, precision, length)
|
|
56
|
+
Subscribe to order book updates. Snapshot will be sent as multiple updates.
|
|
57
|
+
Event will be emited as `PAIRNAME_book`.
|
|
58
|
+
|
|
59
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
60
|
+
**See**: http://docs.bitfinex.com/#order-books
|
|
61
|
+
|
|
62
|
+
| Param | Type | Default | Description |
|
|
63
|
+
| --- | --- | --- | --- |
|
|
64
|
+
| pair | <code>string</code> | <code>"BTCUSD"</code> | |
|
|
65
|
+
| precision | <code>string</code> | | price aggregation level (P0 (def), P1, P2, P3) |
|
|
66
|
+
| length | <code>string</code> | | number of price points. 25 (default) or 100. |
|
|
67
|
+
|
|
68
|
+
<a name="WSv1+subscribeTrades"></a>
|
|
69
|
+
|
|
70
|
+
### wSv1.subscribeTrades(pair)
|
|
71
|
+
Subscribe to trades. Snapshot will be sent as multiple updates.
|
|
72
|
+
Event will be emited as `PAIRNAME_trades`.
|
|
73
|
+
|
|
74
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
75
|
+
**See**: http://docs.bitfinex.com/#trades75
|
|
76
|
+
|
|
77
|
+
| Param | Type | Default |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| pair | <code>string</code> | <code>"BTCUSD"</code> |
|
|
80
|
+
|
|
81
|
+
<a name="WSv1+subscribeTicker"></a>
|
|
82
|
+
|
|
83
|
+
### wSv1.subscribeTicker(pair)
|
|
84
|
+
Subscribe to ticker updates. The ticker is a high level overview of the
|
|
85
|
+
state of the market. It shows you the current best bid and ask, as well as
|
|
86
|
+
the last trade price.
|
|
87
|
+
|
|
88
|
+
Event will be emited as `PAIRNAME_ticker`.
|
|
89
|
+
|
|
90
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
91
|
+
**See**: http://docs.bitfinex.com/#ticker76
|
|
92
|
+
|
|
93
|
+
| Param | Type | Default | Description |
|
|
94
|
+
| --- | --- | --- | --- |
|
|
95
|
+
| pair | <code>string</code> | <code>"BTCUSD"</code> | pair |
|
|
96
|
+
|
|
97
|
+
<a name="WSv1+unsubscribe"></a>
|
|
98
|
+
|
|
99
|
+
### wSv1.unsubscribe(chanId)
|
|
100
|
+
Unsubscribe from a channel.
|
|
101
|
+
|
|
102
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
103
|
+
|
|
104
|
+
| Param | Type | Description |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
| chanId | <code>number</code> | ID of the channel received on `subscribed` event |
|
|
107
|
+
|
|
108
|
+
<a name="WSv1+auth"></a>
|
|
109
|
+
|
|
110
|
+
### wSv1.auth()
|
|
111
|
+
Authenticate the user. Will receive executed traded updates.
|
|
112
|
+
|
|
113
|
+
**Kind**: instance method of [<code>WSv1</code>](#WSv1)
|
|
114
|
+
**See**: http://docs.bitfinex.com/#wallet-updates
|
package/lib/ws.js
CHANGED
|
@@ -11,11 +11,11 @@ const WS_URL = 'wss://api.bitfinex.com/ws/'
|
|
|
11
11
|
/**
|
|
12
12
|
* Communicates with v1 of the Bitfinex WebSocket API
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
class WSv1 extends EventEmitter {
|
|
15
15
|
/**
|
|
16
16
|
* @param {sting} opts.apiKey
|
|
17
17
|
* @param {string} opts.apiSecret
|
|
18
|
-
* @param {string} opts.url - ws connection url
|
|
18
|
+
* @param {string?} opts.url - ws connection url
|
|
19
19
|
*/
|
|
20
20
|
constructor (opts = { apiKey: '', apiSecret: '', url: WS_URL }) {
|
|
21
21
|
super()
|
|
@@ -26,15 +26,31 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
26
26
|
this._channelMap = {} // map channel IDs to events
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Returns status of websocket
|
|
31
|
+
*
|
|
32
|
+
* @return {boolean} open
|
|
33
|
+
*/
|
|
34
|
+
isOpen () {
|
|
35
|
+
return this._ws.isOpen()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Opens a new websocket conection to the configured URL
|
|
40
|
+
*/
|
|
29
41
|
open () {
|
|
30
42
|
this._ws = new WebSocket(this._url)
|
|
31
|
-
|
|
32
43
|
this._ws.on('message', this._onWSMessage.bind(this))
|
|
33
44
|
this._ws.on('open', this._onWSOpen.bind(this))
|
|
34
45
|
this._ws.on('error', this._onWSError.bind(this))
|
|
35
46
|
this._ws.on('close', this._onWSClose.bind(this))
|
|
36
47
|
}
|
|
37
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} msgJSON
|
|
51
|
+
* @param {number} flags
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
38
54
|
_onWSMessage (msgJSON, flags) {
|
|
39
55
|
let msg
|
|
40
56
|
|
|
@@ -72,6 +88,10 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
72
88
|
this.emit(msg.event, msg)
|
|
73
89
|
}
|
|
74
90
|
|
|
91
|
+
/**
|
|
92
|
+
* @param {Array|Array[]} msg
|
|
93
|
+
* @private
|
|
94
|
+
*/
|
|
75
95
|
_handleChannel (msg) {
|
|
76
96
|
// First element of Array is the channelId, the rest is the info.
|
|
77
97
|
const channelId = msg.shift() // Pop the first element
|
|
@@ -98,6 +118,10 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
98
118
|
}
|
|
99
119
|
}
|
|
100
120
|
|
|
121
|
+
/**
|
|
122
|
+
* @param {Array} msg
|
|
123
|
+
* @private
|
|
124
|
+
*/
|
|
101
125
|
_processUserEvent (msg) {
|
|
102
126
|
const event = msg[0]
|
|
103
127
|
const data = msg[1]
|
|
@@ -113,6 +137,11 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
113
137
|
}
|
|
114
138
|
}
|
|
115
139
|
|
|
140
|
+
/**
|
|
141
|
+
* @param {Array} msg
|
|
142
|
+
* @param {Object} event
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
116
145
|
_processTickerEvent (msg, event) {
|
|
117
146
|
if (msg.length > 9) { // Update
|
|
118
147
|
// All values are numbers
|
|
@@ -134,6 +163,11 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
134
163
|
}
|
|
135
164
|
}
|
|
136
165
|
|
|
166
|
+
/**
|
|
167
|
+
* @param {Array[]} msg
|
|
168
|
+
* @param {Object} event
|
|
169
|
+
* @private
|
|
170
|
+
*/
|
|
137
171
|
_processTradeEvent (msg, event) {
|
|
138
172
|
if (isSnapshot(msg)) {
|
|
139
173
|
const snapshot = msg[0].map(el => ({
|
|
@@ -169,8 +203,12 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
169
203
|
this.emit('trade', event.pair, update)
|
|
170
204
|
}
|
|
171
205
|
|
|
206
|
+
/**
|
|
207
|
+
* @param {Array[]} msg
|
|
208
|
+
* @param {Object} event
|
|
209
|
+
* @private
|
|
210
|
+
*/
|
|
172
211
|
_processBookEvent (msg, event) {
|
|
173
|
-
// TODO: Maybe break this up into snapshot/normal handlers? Also trade event
|
|
174
212
|
if (!isSnapshot(msg[0]) && msg.length > 2) {
|
|
175
213
|
let update
|
|
176
214
|
|
|
@@ -217,23 +255,41 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
217
255
|
}
|
|
218
256
|
}
|
|
219
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Close the websocket connection
|
|
260
|
+
*/
|
|
220
261
|
close () {
|
|
221
262
|
this._ws.close()
|
|
222
263
|
}
|
|
223
264
|
|
|
265
|
+
/**
|
|
266
|
+
* @private
|
|
267
|
+
*/
|
|
224
268
|
_onWSOpen () {
|
|
225
269
|
this._channelMap = {}
|
|
226
270
|
this.emit('open')
|
|
227
271
|
}
|
|
228
272
|
|
|
273
|
+
/**
|
|
274
|
+
* @private
|
|
275
|
+
*/
|
|
229
276
|
_onWSError (error) {
|
|
230
277
|
this.emit('error', error)
|
|
231
278
|
}
|
|
232
279
|
|
|
280
|
+
/**
|
|
281
|
+
* @private
|
|
282
|
+
*/
|
|
233
283
|
_onWSClose () {
|
|
234
284
|
this.emit('close')
|
|
235
285
|
}
|
|
236
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Send a packet via the ws connection; automatically converted to a JSON
|
|
289
|
+
* string.
|
|
290
|
+
*
|
|
291
|
+
* @param {*} msg
|
|
292
|
+
*/
|
|
237
293
|
send (msg) {
|
|
238
294
|
debug('Sending %j', msg)
|
|
239
295
|
this._ws.send(JSON.stringify(msg))
|
|
@@ -243,7 +299,7 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
243
299
|
* Subscribe to order book updates. Snapshot will be sent as multiple updates.
|
|
244
300
|
* Event will be emited as `PAIRNAME_book`.
|
|
245
301
|
*
|
|
246
|
-
* @param {string} pair
|
|
302
|
+
* @param {string} pair
|
|
247
303
|
* @param {string} precision - price aggregation level (P0 (def), P1, P2, P3)
|
|
248
304
|
* @param {string} length - number of price points. 25 (default) or 100.
|
|
249
305
|
* @see http://docs.bitfinex.com/#order-books
|
|
@@ -262,7 +318,7 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
262
318
|
* Subscribe to trades. Snapshot will be sent as multiple updates.
|
|
263
319
|
* Event will be emited as `PAIRNAME_trades`.
|
|
264
320
|
*
|
|
265
|
-
* @param {string} pair
|
|
321
|
+
* @param {string} pair
|
|
266
322
|
* @see http://docs.bitfinex.com/#trades75
|
|
267
323
|
*/
|
|
268
324
|
subscribeTrades (pair = 'BTCUSD') {
|
|
@@ -280,7 +336,7 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
280
336
|
*
|
|
281
337
|
* Event will be emited as `PAIRNAME_ticker`.
|
|
282
338
|
*
|
|
283
|
-
* @param {string} - pair
|
|
339
|
+
* @param {string} - pair
|
|
284
340
|
* @see http://docs.bitfinex.com/#ticker76
|
|
285
341
|
*/
|
|
286
342
|
subscribeTicker (pair = 'BTCUSD') {
|
|
@@ -319,3 +375,5 @@ module.exports = class WSv1 extends EventEmitter {
|
|
|
319
375
|
})
|
|
320
376
|
}
|
|
321
377
|
}
|
|
378
|
+
|
|
379
|
+
module.exports = WSv1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bfx-api-node-ws1",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Legacy WSv1 transport for the Bitfinex Node API",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=7"
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"lint": "standard",
|
|
11
11
|
"test": "npm run lint && npm run unit",
|
|
12
|
-
"unit": "NODE_ENV=test mocha -b --recursive"
|
|
12
|
+
"unit": "NODE_ENV=test mocha -b --recursive",
|
|
13
|
+
"docs": "npm run ws1_docs",
|
|
14
|
+
"ws1_docs": "node_modules/jsdoc-to-markdown/bin/cli.js lib/ws.js > docs/ws1_docs.md"
|
|
13
15
|
},
|
|
14
16
|
"repository": {
|
|
15
17
|
"type": "git",
|
|
@@ -20,27 +22,31 @@
|
|
|
20
22
|
"bitcoin",
|
|
21
23
|
"BTC"
|
|
22
24
|
],
|
|
25
|
+
"author": "Bitfinex",
|
|
23
26
|
"contributors": [
|
|
24
27
|
"Josh Rossi <josh@bitfinex.com> (https://www.bitfinex.com)",
|
|
25
28
|
"Cris Mihalache <cris.m@bitfinex.com> (https://www.bitfinex.com)",
|
|
26
29
|
"Robert Kowalski <robert@bitfinex.com> (https://www.bitfinex.com)",
|
|
27
30
|
"Simone Poggi <simone@bitfinex.com> (https://www.bitfinex.com)",
|
|
28
|
-
"Paolo Ardoino <paolo@bitfinex.com> (https://www.bitfinex.com)"
|
|
31
|
+
"Paolo Ardoino <paolo@bitfinex.com> (https://www.bitfinex.com)",
|
|
32
|
+
"Jacob Plaster <jacob.plaster@bitfinex.com> (https://www.bitfinex.com)"
|
|
29
33
|
],
|
|
30
34
|
"license": "MIT",
|
|
31
35
|
"bugs": {
|
|
32
36
|
"url": "https://github.com/bitfinexcom/bfx-api-node-ws1/issues"
|
|
33
37
|
},
|
|
34
38
|
"devDependencies": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
39
|
+
"babel-eslint": "^10.0.3",
|
|
40
|
+
"chai": "^4.2.0",
|
|
41
|
+
"jsdoc-to-markdown": "^5.0.1",
|
|
42
|
+
"mocha": "^6.2.0",
|
|
43
|
+
"standard": "^14.1.0"
|
|
38
44
|
},
|
|
39
45
|
"dependencies": {
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
46
|
+
"bfx-api-node-util": "^1.0.10",
|
|
47
|
+
"bluebird": "3.5.5",
|
|
48
|
+
"debug": "4.1.1",
|
|
49
|
+
"lodash": "^4.17.15",
|
|
50
|
+
"ws": "3.0.0"
|
|
45
51
|
}
|
|
46
52
|
}
|
|
@@ -16,11 +16,11 @@ describe('ws1 channel msg handling', () => {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
bfxWs.once('orderbook', (symbol, data) => {
|
|
19
|
-
assert.
|
|
19
|
+
assert.deepStrictEqual(data, { price: 2477.1, orderId: 2919111002, amount: 0.0125 })
|
|
20
20
|
done()
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
bfxWs._handleChannel([
|
|
23
|
+
bfxWs._handleChannel([32755, 2919111002, 2477.1, 0.0125])
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
it('ws1 transforms & normalizes well - P1 update', (done) => {
|
|
@@ -29,11 +29,11 @@ describe('ws1 channel msg handling', () => {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
bfxWs.once('orderbook', (symbol, data) => {
|
|
32
|
-
assert.
|
|
32
|
+
assert.deepStrictEqual(data, { price: 2494, count: 2, amount: 5.9895 })
|
|
33
33
|
done()
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
bfxWs._handleChannel([
|
|
36
|
+
bfxWs._handleChannel([182, 2494, 2, 5.9895])
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
it('ws1 transforms & normalizes well - P1 snap', (done) => {
|
|
@@ -42,14 +42,14 @@ describe('ws1 channel msg handling', () => {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
bfxWs.once('orderbook', (symbol, data) => {
|
|
45
|
-
assert.
|
|
45
|
+
assert.deepStrictEqual(data[1], { price: 2494, count: 3, amount: 0.14606853 })
|
|
46
46
|
done()
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
const snap = [
|
|
50
|
-
[
|
|
51
|
-
[
|
|
52
|
-
[
|
|
49
|
+
const snap = [39, [
|
|
50
|
+
[2495, 2, 0.8744],
|
|
51
|
+
[2494, 3, 0.14606853],
|
|
52
|
+
[2492, 1, 0.4]
|
|
53
53
|
]]
|
|
54
54
|
|
|
55
55
|
bfxWs._handleChannel(snap)
|
|
@@ -61,17 +61,17 @@ describe('ws1 channel msg handling', () => {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
bfxWs.once('orderbook', (symbol, data) => {
|
|
64
|
-
assert.
|
|
64
|
+
assert.deepStrictEqual(
|
|
65
65
|
data[1],
|
|
66
66
|
{ price: 2494.5, orderId: 2919279471, amount: 0.07288 }
|
|
67
67
|
)
|
|
68
68
|
done()
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
-
const snap = [
|
|
72
|
-
[
|
|
73
|
-
[
|
|
74
|
-
[
|
|
71
|
+
const snap = [34513, [
|
|
72
|
+
[2919278474, 2494.5, 0.07901704],
|
|
73
|
+
[2919279471, 2494.5, 0.07288],
|
|
74
|
+
[2919280093, 2494.5, 0.03644]
|
|
75
75
|
]]
|
|
76
76
|
|
|
77
77
|
bfxWs._handleChannel(snap)
|
package/test/lib/ws-1-parsing.js
CHANGED
|
@@ -8,16 +8,35 @@ const WebSocket = require('ws')
|
|
|
8
8
|
const WSv1 = require('../../lib/ws')
|
|
9
9
|
|
|
10
10
|
describe('websocket1 parsing non json', () => {
|
|
11
|
+
let ws = null
|
|
12
|
+
let wss = null
|
|
13
|
+
|
|
14
|
+
afterEach(async () => {
|
|
15
|
+
try { // may fail due to being modified by a test, it's not a problem
|
|
16
|
+
if (ws && ws.isOpen()) {
|
|
17
|
+
await new Promise(resolve => ws.close(resolve))
|
|
18
|
+
}
|
|
19
|
+
} catch (e) {}
|
|
20
|
+
|
|
21
|
+
ws = null
|
|
22
|
+
|
|
23
|
+
if (wss) {
|
|
24
|
+
await new Promise(resolve => wss.close(resolve))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
wss = null
|
|
28
|
+
})
|
|
29
|
+
|
|
11
30
|
it('should not crash the client', (done) => {
|
|
12
|
-
|
|
31
|
+
ws = new WSv1({
|
|
13
32
|
apiKey: 'dummy',
|
|
14
33
|
apiSecret: 'dummy',
|
|
15
34
|
url: `ws://localhost:${PORT}`
|
|
16
35
|
})
|
|
17
36
|
|
|
18
|
-
|
|
37
|
+
ws.open()
|
|
19
38
|
|
|
20
|
-
|
|
39
|
+
wss = new WebSocket.Server({
|
|
21
40
|
perMessageDeflate: false,
|
|
22
41
|
port: PORT
|
|
23
42
|
})
|
|
@@ -25,16 +44,13 @@ describe('websocket1 parsing non json', () => {
|
|
|
25
44
|
wss.on('connection', function connection (ws) {
|
|
26
45
|
ws.on('message', function incoming (msg) {
|
|
27
46
|
msg = JSON.parse(msg)
|
|
28
|
-
assert.
|
|
29
|
-
wss.close()
|
|
47
|
+
assert.strictEqual(msg.len, '25')
|
|
30
48
|
done()
|
|
31
49
|
})
|
|
32
50
|
|
|
33
51
|
ws.send("HTTP Code 408 - I'm a Tea Pot")
|
|
34
52
|
})
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
bws.subscribeOrderBook('BTCUSD', 'R0')
|
|
38
|
-
})
|
|
54
|
+
ws.on('open', () => ws.subscribeOrderBook('BTCUSD', 'R0'))
|
|
39
55
|
})
|
|
40
56
|
})
|
package/test/lib/ws-1-test.js
CHANGED
|
@@ -1,112 +1,121 @@
|
|
|
1
1
|
/* eslint-env mocha */
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
|
-
const PORT = 1337
|
|
5
|
-
|
|
6
4
|
const assert = require('assert')
|
|
7
|
-
|
|
8
5
|
const WebSocket = require('ws')
|
|
9
|
-
const
|
|
6
|
+
const _isObject = require('lodash/isObject')
|
|
10
7
|
|
|
8
|
+
const WSv1 = require('../../lib/ws')
|
|
11
9
|
const orderbookR0 = require('../fixtures/response-ws-1-orderbook-R0.json')
|
|
12
10
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
const PORT = 1334
|
|
12
|
+
const getWSInstance = (args) => (
|
|
13
|
+
new WSv1({
|
|
14
|
+
url: `ws://localhost:${PORT}`,
|
|
15
|
+
...args
|
|
18
16
|
})
|
|
19
|
-
|
|
17
|
+
)
|
|
20
18
|
|
|
21
19
|
describe('WebSocket v1 integration', () => {
|
|
20
|
+
let ws = null
|
|
21
|
+
let wss = null
|
|
22
|
+
|
|
23
|
+
afterEach(async () => {
|
|
24
|
+
try { // may fail due to being modified by a test, it's not a problem
|
|
25
|
+
if (ws && ws.isOpen()) {
|
|
26
|
+
ws.close()
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {}
|
|
29
|
+
|
|
30
|
+
ws = null
|
|
31
|
+
|
|
32
|
+
if (wss) {
|
|
33
|
+
await new Promise(resolve => wss.close(resolve))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
wss = null
|
|
37
|
+
})
|
|
38
|
+
|
|
22
39
|
it('plays ping pong', (done) => {
|
|
23
|
-
|
|
40
|
+
wss = new WebSocket.Server({
|
|
24
41
|
perMessageDeflate: false,
|
|
25
42
|
port: PORT
|
|
26
43
|
})
|
|
27
44
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
wss.on('connection', function connection (ws) {
|
|
32
|
-
ws.on('message', function incoming (msg) {
|
|
45
|
+
ws = getWSInstance()
|
|
46
|
+
wss.on('connection', (ws) => {
|
|
47
|
+
ws.on('message', (msg) => {
|
|
33
48
|
ws.send('{"event":"pong"}')
|
|
34
49
|
})
|
|
35
50
|
})
|
|
36
51
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
bws.on('pong', () => {
|
|
42
|
-
bws.close()
|
|
43
|
-
wss.close(done)
|
|
44
|
-
})
|
|
52
|
+
ws.on('open', () => ws.send({ event: 'ping' }))
|
|
53
|
+
ws.on('pong', () => done())
|
|
54
|
+
ws.open()
|
|
45
55
|
})
|
|
46
56
|
|
|
47
57
|
it('should receive info message', (done) => {
|
|
48
|
-
|
|
58
|
+
wss = new WebSocket.Server({
|
|
49
59
|
perMessageDeflate: false,
|
|
50
60
|
port: PORT
|
|
51
61
|
})
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
bws.open()
|
|
63
|
+
ws = getWSInstance()
|
|
55
64
|
|
|
56
|
-
wss.on('connection',
|
|
57
|
-
ws.send(
|
|
65
|
+
wss.on('connection', (ws) => {
|
|
66
|
+
ws.send(JSON.stringify({
|
|
67
|
+
event: 'info',
|
|
68
|
+
version: 1.1,
|
|
69
|
+
platform: {
|
|
70
|
+
status: 1
|
|
71
|
+
}
|
|
72
|
+
}))
|
|
58
73
|
})
|
|
59
74
|
|
|
60
|
-
|
|
61
|
-
assert.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
)
|
|
68
|
-
bws.close()
|
|
69
|
-
wss.close(done)
|
|
75
|
+
ws.on('info', (data) => {
|
|
76
|
+
assert(_isObject(data.platform))
|
|
77
|
+
assert.strictEqual(data.event, 'info')
|
|
78
|
+
assert.strictEqual(data.version, 1.1)
|
|
79
|
+
assert.strictEqual(data.platform.status, 1)
|
|
80
|
+
done()
|
|
70
81
|
})
|
|
82
|
+
|
|
83
|
+
ws.open()
|
|
71
84
|
})
|
|
72
85
|
|
|
73
86
|
it('should emit an error when authorization fails', (done) => {
|
|
74
|
-
|
|
87
|
+
wss = new WebSocket.Server({
|
|
75
88
|
perMessageDeflate: false,
|
|
76
89
|
port: PORT
|
|
77
90
|
})
|
|
78
91
|
|
|
79
|
-
|
|
80
|
-
bws.open()
|
|
92
|
+
ws = getWSInstance()
|
|
81
93
|
|
|
82
|
-
wss.on('connection',
|
|
83
|
-
ws.on('message',
|
|
94
|
+
wss.on('connection', (ws) => {
|
|
95
|
+
ws.on('message', (msg) => {
|
|
84
96
|
ws.send('{"event":"auth","status":"FAILED","chanId":0,"code":10100,"msg":"apikey: invalid"}')
|
|
85
97
|
})
|
|
86
98
|
})
|
|
87
99
|
|
|
88
|
-
|
|
89
|
-
assert.
|
|
90
|
-
|
|
91
|
-
wss.close(done)
|
|
100
|
+
ws.on('error', (err) => {
|
|
101
|
+
assert.strictEqual(err.event, 'auth')
|
|
102
|
+
done()
|
|
92
103
|
})
|
|
93
104
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
})
|
|
105
|
+
ws.on('open', ws.auth.bind(ws))
|
|
106
|
+
ws.open()
|
|
97
107
|
})
|
|
98
108
|
|
|
99
|
-
it('should unsubscribe by channelId',
|
|
100
|
-
|
|
109
|
+
it('should unsubscribe by channelId', (done) => {
|
|
110
|
+
wss = new WebSocket.Server({
|
|
101
111
|
perMessageDeflate: false,
|
|
102
112
|
port: PORT
|
|
103
113
|
})
|
|
104
114
|
|
|
105
|
-
|
|
106
|
-
bws.open()
|
|
115
|
+
ws = getWSInstance()
|
|
107
116
|
|
|
108
|
-
wss.on('connection',
|
|
109
|
-
ws.on('message',
|
|
117
|
+
wss.on('connection', (ws) => {
|
|
118
|
+
ws.on('message', (msg) => {
|
|
110
119
|
msg = JSON.parse(msg)
|
|
111
120
|
if (msg.event === 'unsubscribe') {
|
|
112
121
|
ws.send('{"event":"unsubscribed","status":"OK","chanId":4}')
|
|
@@ -117,159 +126,157 @@ describe('WebSocket v1 integration', () => {
|
|
|
117
126
|
})
|
|
118
127
|
})
|
|
119
128
|
|
|
120
|
-
|
|
129
|
+
ws.once('subscribed', (data) => {
|
|
121
130
|
const channelId = data.chanId
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
assert.
|
|
125
|
-
assert.
|
|
126
|
-
|
|
127
|
-
wss.close(done)
|
|
132
|
+
ws.once('unsubscribed', (data) => {
|
|
133
|
+
assert.strictEqual(data.status, 'OK')
|
|
134
|
+
assert.strictEqual(data.chanId, channelId)
|
|
135
|
+
done()
|
|
128
136
|
})
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
bws.on('open', () => {
|
|
132
|
-
bws.subscribeTicker('BTCUSD')
|
|
137
|
+
|
|
138
|
+
ws.unsubscribe(channelId)
|
|
133
139
|
})
|
|
140
|
+
|
|
141
|
+
ws.on('open', () => ws.subscribeTicker('BTCUSD'))
|
|
142
|
+
ws.open()
|
|
134
143
|
})
|
|
135
144
|
|
|
136
145
|
it('should receive a subscribed success messages', (done) => {
|
|
137
|
-
|
|
146
|
+
wss = new WebSocket.Server({
|
|
138
147
|
perMessageDeflate: false,
|
|
139
148
|
port: PORT
|
|
140
149
|
})
|
|
141
150
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
wss.on('connection', function connection (ws) {
|
|
146
|
-
ws.on('message', function incoming (msg) {
|
|
151
|
+
ws = getWSInstance()
|
|
152
|
+
wss.on('connection', (ws) => {
|
|
153
|
+
ws.on('message', (msg) => {
|
|
147
154
|
ws.send('{"event":"subscribed","channel":"trades","chanId":4,"pair":"BTCUSD"}')
|
|
148
155
|
})
|
|
149
156
|
})
|
|
150
157
|
|
|
151
|
-
|
|
152
|
-
assert.
|
|
153
|
-
assert.
|
|
154
|
-
|
|
155
|
-
wss.close(done)
|
|
156
|
-
})
|
|
157
|
-
bws.on('open', () => {
|
|
158
|
-
bws.subscribeTrades('BTCUSD')
|
|
158
|
+
ws.on('subscribed', (data) => {
|
|
159
|
+
assert.strictEqual(data.channel, 'trades')
|
|
160
|
+
assert.strictEqual(data.pair, 'BTCUSD')
|
|
161
|
+
done()
|
|
159
162
|
})
|
|
163
|
+
|
|
164
|
+
ws.on('open', () => ws.subscribeTrades('BTCUSD'))
|
|
165
|
+
ws.open()
|
|
160
166
|
})
|
|
161
167
|
|
|
162
168
|
it('#orderBook data should have the defined fields', (done) => {
|
|
163
|
-
|
|
169
|
+
wss = new WebSocket.Server({
|
|
164
170
|
perMessageDeflate: false,
|
|
165
171
|
port: PORT
|
|
166
172
|
})
|
|
167
173
|
|
|
168
|
-
wss.on('connection',
|
|
169
|
-
ws.on('message',
|
|
170
|
-
ws.send(
|
|
174
|
+
wss.on('connection', (ws) => {
|
|
175
|
+
ws.on('message', (msg) => {
|
|
176
|
+
ws.send(JSON.stringify({
|
|
177
|
+
event: 'subscribed',
|
|
178
|
+
channel: 'book',
|
|
179
|
+
chanId: 13242,
|
|
180
|
+
prec: 'R0',
|
|
181
|
+
freq: 'F0',
|
|
182
|
+
len: '25',
|
|
183
|
+
pair: 'BTCUSD'
|
|
184
|
+
}))
|
|
185
|
+
|
|
171
186
|
ws.send(JSON.stringify(orderbookR0))
|
|
172
187
|
})
|
|
173
188
|
})
|
|
174
189
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
assert.
|
|
180
|
-
assert.
|
|
181
|
-
assert.
|
|
182
|
-
|
|
183
|
-
assert.equal(data.length, 50)
|
|
184
|
-
bws.close()
|
|
185
|
-
wss.close(done)
|
|
190
|
+
ws = getWSInstance({ transform: true })
|
|
191
|
+
ws.once('orderbook', (pair, data) => {
|
|
192
|
+
assert.strictEqual(pair, 'BTCUSD')
|
|
193
|
+
assert.strictEqual(typeof data[0].price, 'number')
|
|
194
|
+
assert.strictEqual(typeof data[0].orderId, 'number')
|
|
195
|
+
assert.strictEqual(typeof data[0].amount, 'number')
|
|
196
|
+
assert.strictEqual(data.length, 50)
|
|
197
|
+
done()
|
|
186
198
|
})
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
})
|
|
199
|
+
|
|
200
|
+
ws.on('open', () => ws.subscribeOrderBook('BTCUSD'))
|
|
201
|
+
ws.open()
|
|
202
|
+
}).timeout(10 * 1000)
|
|
191
203
|
|
|
192
204
|
it('#ticker data should have the defined fields', (done) => {
|
|
193
|
-
|
|
205
|
+
wss = new WebSocket.Server({
|
|
194
206
|
perMessageDeflate: false,
|
|
195
207
|
port: PORT
|
|
196
208
|
})
|
|
197
209
|
|
|
198
|
-
wss.on('connection',
|
|
210
|
+
wss.on('connection', (ws) => {
|
|
199
211
|
ws.send('{"event":"info","version":1.1}')
|
|
200
|
-
ws.on('message',
|
|
212
|
+
ws.on('message', (msg) => {
|
|
201
213
|
ws.send('{"event":"subscribed","channel":"ticker","chanId":4,"pair":"BTCUSD"}')
|
|
202
214
|
ws.send('[4,2169.6,1.93,2169.8,0.0349,100.9,0.0488,2169.6,25479.40978657,2196,2000.1]')
|
|
203
215
|
})
|
|
204
216
|
})
|
|
205
217
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
assert.
|
|
211
|
-
assert.
|
|
212
|
-
assert.
|
|
213
|
-
assert.
|
|
214
|
-
assert.
|
|
215
|
-
assert.
|
|
216
|
-
assert.
|
|
217
|
-
assert.
|
|
218
|
-
assert.
|
|
219
|
-
assert.
|
|
220
|
-
|
|
221
|
-
bws.close()
|
|
222
|
-
wss.close(done)
|
|
223
|
-
})
|
|
224
|
-
bws.on('open', () => {
|
|
225
|
-
bws.subscribeTicker('BTCUSD')
|
|
218
|
+
ws = getWSInstance()
|
|
219
|
+
|
|
220
|
+
ws.once('ticker', (pair, data) => {
|
|
221
|
+
assert.strictEqual(pair, 'BTCUSD')
|
|
222
|
+
assert.strictEqual(typeof data.bid, 'number')
|
|
223
|
+
assert.strictEqual(typeof data.bidSize, 'number')
|
|
224
|
+
assert.strictEqual(typeof data.ask, 'number')
|
|
225
|
+
assert.strictEqual(typeof data.askSize, 'number')
|
|
226
|
+
assert.strictEqual(typeof data.dailyChange, 'number')
|
|
227
|
+
assert.strictEqual(typeof data.dailyChangePerc, 'number')
|
|
228
|
+
assert.strictEqual(typeof data.lastPrice, 'number')
|
|
229
|
+
assert.strictEqual(typeof data.volume, 'number')
|
|
230
|
+
assert.strictEqual(typeof data.high, 'number')
|
|
231
|
+
assert.strictEqual(typeof data.low, 'number')
|
|
232
|
+
done()
|
|
226
233
|
})
|
|
234
|
+
|
|
235
|
+
ws.on('open', () => ws.subscribeTicker('BTCUSD'))
|
|
236
|
+
ws.open()
|
|
227
237
|
})
|
|
228
238
|
|
|
229
239
|
it('#trade data should have the defined fields', (done) => {
|
|
230
|
-
|
|
240
|
+
wss = new WebSocket.Server({
|
|
231
241
|
perMessageDeflate: false,
|
|
232
242
|
port: PORT
|
|
233
243
|
})
|
|
234
244
|
|
|
235
|
-
wss.on('connection',
|
|
245
|
+
wss.on('connection', (ws) => {
|
|
236
246
|
ws.send('{"event":"info","version":1.1}')
|
|
237
|
-
ws.on('message',
|
|
247
|
+
ws.on('message', (msg) => {
|
|
238
248
|
ws.send('{"event":"subscribed","channel":"trades","chanId":33,"pair":"BTCUSD"}')
|
|
239
|
-
ws.send(
|
|
240
|
-
[33,[[32970704,1495442718,2169.1,0.03647196],[32970701,1495442718,2169.1,0.01058338],
|
|
241
|
-
[32970697,1495442717,2169,-0.0000791],[32970696,1495442717,2169,-0.01054738],
|
|
242
|
-
[32970692,1495442716,2169,-0.01063712],[32970683,1495442715,2169,-0.00191556],
|
|
243
|
-
[32970682,1495442715,2169,-0.02003456],[32970681,1495442715,2169,-0.02002811],
|
|
244
|
-
[32970680,1495442715,2169,-0.01079782],[32970679,1495442715,2169,-0.02002726],
|
|
245
|
-
[32970678,1495442715,2169,-0.01079782],[32970662,1495442714,2169,-3.68585828],
|
|
246
|
-
[32970654,1495442712,2169,-0.01413205],[32970646,1495442711,2169,-0.01066102],
|
|
247
|
-
[32970643,1495442710,2169,-0.02002146],[32970640,1495442709,2169,-0.01727607],
|
|
248
|
-
[32970631,1495442708,2169,-0.00984518],[32970629,1495442708,2169,-1.07188465],
|
|
249
|
-
[32970618,1495442706,2169,-0.0995877],[32970613,1495442706,2169,-0.015553],
|
|
250
|
-
[32970595,1495442702,2169,-0.00864857],[32970593,1495442702,2169,-0.01999732],
|
|
251
|
-
[32970592,1495442702,2169,-0.01067048],[32970591,1495442702,2169.1,0.92541262],
|
|
252
|
-
[32970590,1495442702,2169.1,0.9787866],[32970589,1495442702,2169,-0.01067048],
|
|
253
|
-
[32970573,1495442702,2169,-0.01067048],[32970572,1495442702,2169,-0.0172659],
|
|
254
|
-
[32970569,1495442701,2169,-0.02000913],[32970567,1495442701,2169,-0.01413205]]]
|
|
255
|
-
|
|
249
|
+
ws.send([
|
|
250
|
+
'[33,[[32970704,1495442718,2169.1,0.03647196],[32970701,1495442718,2169.1,0.01058338],',
|
|
251
|
+
'[32970697,1495442717,2169,-0.0000791],[32970696,1495442717,2169,-0.01054738],',
|
|
252
|
+
'[32970692,1495442716,2169,-0.01063712],[32970683,1495442715,2169,-0.00191556],',
|
|
253
|
+
'[32970682,1495442715,2169,-0.02003456],[32970681,1495442715,2169,-0.02002811],',
|
|
254
|
+
'[32970680,1495442715,2169,-0.01079782],[32970679,1495442715,2169,-0.02002726],',
|
|
255
|
+
'[32970678,1495442715,2169,-0.01079782],[32970662,1495442714,2169,-3.68585828],',
|
|
256
|
+
'[32970654,1495442712,2169,-0.01413205],[32970646,1495442711,2169,-0.01066102],',
|
|
257
|
+
'[32970643,1495442710,2169,-0.02002146],[32970640,1495442709,2169,-0.01727607],',
|
|
258
|
+
'[32970631,1495442708,2169,-0.00984518],[32970629,1495442708,2169,-1.07188465],',
|
|
259
|
+
'[32970618,1495442706,2169,-0.0995877],[32970613,1495442706,2169,-0.015553],',
|
|
260
|
+
'[32970595,1495442702,2169,-0.00864857],[32970593,1495442702,2169,-0.01999732],',
|
|
261
|
+
'[32970592,1495442702,2169,-0.01067048],[32970591,1495442702,2169.1,0.92541262],',
|
|
262
|
+
'[32970590,1495442702,2169.1,0.9787866],[32970589,1495442702,2169,-0.01067048],',
|
|
263
|
+
'[32970573,1495442702,2169,-0.01067048],[32970572,1495442702,2169,-0.0172659],',
|
|
264
|
+
'[32970569,1495442701,2169,-0.02000913],[32970567,1495442701,2169,-0.01413205]]]'
|
|
265
|
+
].join(''))
|
|
256
266
|
})
|
|
257
267
|
})
|
|
258
268
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
assert.
|
|
264
|
-
assert.
|
|
265
|
-
assert.
|
|
266
|
-
|
|
267
|
-
assert.equal(typeof data[0].amount, 'number')
|
|
268
|
-
bws.close()
|
|
269
|
-
wss.close(done)
|
|
270
|
-
})
|
|
271
|
-
bws.on('open', () => {
|
|
272
|
-
bws.subscribeTrades('BTCUSD')
|
|
269
|
+
ws = getWSInstance()
|
|
270
|
+
|
|
271
|
+
ws.once('trade', (pair, data) => {
|
|
272
|
+
assert.strictEqual(pair, 'BTCUSD')
|
|
273
|
+
assert.strictEqual(typeof data[0].timestamp, 'number')
|
|
274
|
+
assert.strictEqual(typeof data[0].price, 'number')
|
|
275
|
+
assert.strictEqual(typeof data[0].amount, 'number')
|
|
276
|
+
done()
|
|
273
277
|
})
|
|
278
|
+
|
|
279
|
+
ws.on('open', () => ws.subscribeTrades('BTCUSD'))
|
|
280
|
+
ws.open()
|
|
274
281
|
})
|
|
275
|
-
})
|
|
282
|
+
}).timeout(10 * 1000)
|