btc-api-node 1.12.7

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.

Potentially problematic release.


This version of btc-api-node might be problematic. Click here for more details.

Files changed (97) hide show
  1. package/.istanbul.yml +53 -0
  2. package/.travis.yml +5 -0
  3. package/CHANGELOG +33 -0
  4. package/LICENSE.md +21 -0
  5. package/README.md +211 -0
  6. package/doc/order.md +160 -0
  7. package/doc/rest2.md +573 -0
  8. package/doc/ws2.md +925 -0
  9. package/examples/bfx.js +26 -0
  10. package/examples/rest2/order_history.js +29 -0
  11. package/examples/rest2/symbols.js +15 -0
  12. package/examples/rest2/tickers.js +24 -0
  13. package/examples/rest2/trade_history.js +28 -0
  14. package/examples/ws2/auth.js +31 -0
  15. package/examples/ws2/calc.js +33 -0
  16. package/examples/ws2/cancel_all.js +35 -0
  17. package/examples/ws2/cancel_all_buf.js +39 -0
  18. package/examples/ws2/candles.js +36 -0
  19. package/examples/ws2/info_events.js +40 -0
  20. package/examples/ws2/oc_multi.js +50 -0
  21. package/examples/ws2/order_books.js +37 -0
  22. package/examples/ws2/orders.js +67 -0
  23. package/examples/ws2/ox_multi.js +61 -0
  24. package/examples/ws2/sequencing.js +23 -0
  25. package/examples/ws2/ticker.js +20 -0
  26. package/examples/ws2/trades.js +27 -0
  27. package/index.js +24 -0
  28. package/lib/model.js +25 -0
  29. package/lib/models/alert.js +25 -0
  30. package/lib/models/balance_info.js +21 -0
  31. package/lib/models/candle.js +33 -0
  32. package/lib/models/funding_credit.js +61 -0
  33. package/lib/models/funding_info.js +16 -0
  34. package/lib/models/funding_loan.js +64 -0
  35. package/lib/models/funding_offer.js +60 -0
  36. package/lib/models/funding_trade.js +33 -0
  37. package/lib/models/index.js +23 -0
  38. package/lib/models/margin_info.js +29 -0
  39. package/lib/models/notification.js +31 -0
  40. package/lib/models/order.js +288 -0
  41. package/lib/models/order_book.js +214 -0
  42. package/lib/models/position.js +43 -0
  43. package/lib/models/tick.js +83 -0
  44. package/lib/models/trade.js +43 -0
  45. package/lib/models/trade_tick.js +29 -0
  46. package/lib/models/wallet.js +34 -0
  47. package/lib/transports/rest.js +391 -0
  48. package/lib/transports/rest2.js +597 -0
  49. package/lib/transports/ws.js +323 -0
  50. package/lib/transports/ws2.js +1729 -0
  51. package/lib/util/gen_auth_sig.js +23 -0
  52. package/lib/util/index.js +11 -0
  53. package/lib/util/is_snapshot.js +5 -0
  54. package/lib/util/nonce.js +5 -0
  55. package/package.json +39 -0
  56. package/test/fixtures/response-ticker-funding.json +1 -0
  57. package/test/fixtures/response-ticker-pairs.json +1 -0
  58. package/test/fixtures/response-trades-funding.json +1 -0
  59. package/test/fixtures/response-trades-pairs.json +1 -0
  60. package/test/fixtures/response-ws-1-orderbook-R0.json +51 -0
  61. package/test/fixtures/response-ws2-server-order-book-P0.json +1 -0
  62. package/test/fixtures/response-ws2-server-order-book-P1.json +1 -0
  63. package/test/fixtures/response-ws2-server-order-book-R0.json +1 -0
  64. package/test/fixtures/response-ws2-server-ticker-funding.json +1 -0
  65. package/test/fixtures/response-ws2-server-trades.json +1 -0
  66. package/test/helpers/test_model.js +71 -0
  67. package/test/index.js +131 -0
  68. package/test/lib/models/alert.js +12 -0
  69. package/test/lib/models/balance_info.js +12 -0
  70. package/test/lib/models/candle.js +12 -0
  71. package/test/lib/models/funding_credit.js +17 -0
  72. package/test/lib/models/funding_info.js +7 -0
  73. package/test/lib/models/funding_loan.js +17 -0
  74. package/test/lib/models/funding_offer.js +17 -0
  75. package/test/lib/models/funding_trade.js +15 -0
  76. package/test/lib/models/margin_info.js +15 -0
  77. package/test/lib/models/notification.js +14 -0
  78. package/test/lib/models/order.js +395 -0
  79. package/test/lib/models/order_book.js +188 -0
  80. package/test/lib/models/position.js +15 -0
  81. package/test/lib/models/tick.js +34 -0
  82. package/test/lib/models/trade.js +16 -0
  83. package/test/lib/models/trade_tick.js +14 -0
  84. package/test/lib/models/wallet.js +14 -0
  85. package/test/lib/transports/rest-1-integration.js +131 -0
  86. package/test/lib/transports/rest-2-integration.js +80 -0
  87. package/test/lib/transports/rest-2-issue-80-argument-length.js +61 -0
  88. package/test/lib/transports/rest-2-smoke-test.js +49 -0
  89. package/test/lib/transports/rest-2-unit.js +26 -0
  90. package/test/lib/transports/rest1.js +152 -0
  91. package/test/lib/transports/ws-1-handle-channel.js +83 -0
  92. package/test/lib/transports/ws-1-parsing.js +40 -0
  93. package/test/lib/transports/ws-1-test.js +275 -0
  94. package/test/lib/transports/ws2-integration.js +259 -0
  95. package/test/lib/transports/ws2-unit.js +1295 -0
  96. package/test/lib/util/is_snapshot.js +20 -0
  97. package/test/lib/util/nonce.js +20 -0
@@ -0,0 +1,323 @@
1
+ 'use strict'
2
+
3
+ const { EventEmitter } = require('events')
4
+ const debug = require('debug')('bitfinex:ws')
5
+ const WebSocket = require('ws')
6
+
7
+ const { isSnapshot, genAuthSig } = require('../util')
8
+
9
+ const WS_URL = 'wss://api.bitfinex.com/ws/'
10
+
11
+ /**
12
+ * Communicates with v1 of the Bitfinex WebSocket API
13
+ */
14
+ class WSv1 extends EventEmitter {
15
+ /**
16
+ * @param {sting} opts.apiKey
17
+ * @param {string} opts.apiSecret
18
+ * @param {string} opts.url - ws connection url
19
+ */
20
+ constructor (opts = { apiKey: '', apiSecret: '', url: WS_URL }) {
21
+ super()
22
+
23
+ this._apiKey = opts.apiKey || ''
24
+ this._apiSecret = opts.apiSecret || ''
25
+ this._url = opts.url || WS_URL
26
+ this._channelMap = {} // map channel IDs to events
27
+ }
28
+
29
+ open () {
30
+ this._ws = new WebSocket(this._url)
31
+
32
+ this._ws.on('message', this._onWSMessage.bind(this))
33
+ this._ws.on('open', this._onWSOpen.bind(this))
34
+ this._ws.on('error', this._onWSError.bind(this))
35
+ this._ws.on('close', this._onWSClose.bind(this))
36
+ }
37
+
38
+ _onWSMessage (msgJSON, flags) {
39
+ let msg
40
+
41
+ try {
42
+ msg = JSON.parse(msgJSON)
43
+ } catch (e) {
44
+ debug('[bfx ws2 error] received invalid json')
45
+ debug('[bfx ws2 error] %j', msgJSON)
46
+ return
47
+ }
48
+
49
+ debug('Received message: %j', msg)
50
+ this.emit('message', msg, flags)
51
+ debug('Emmited message event')
52
+
53
+ // Drop out early if channel data
54
+ if (Array.isArray(msg) || !msg.event) {
55
+ return this._handleChannel(msg)
56
+ }
57
+
58
+ if (msg.event === 'subscribed') {
59
+ debug('Subscription report received')
60
+ this._channelMap[msg.chanId] = msg
61
+ } else if (msg.event === 'auth') {
62
+ if (msg.status !== 'OK') {
63
+ debug('Emitting \'error\' %j', msg)
64
+ this.emit('error', msg)
65
+ return
66
+ }
67
+
68
+ this._channelMap[msg.chanId] = { channel: 'auth' }
69
+ }
70
+
71
+ debug('Emitting \'%s\' %j', msg.event, msg)
72
+ this.emit(msg.event, msg)
73
+ }
74
+
75
+ _handleChannel (msg) {
76
+ // First element of Array is the channelId, the rest is the info.
77
+ const channelId = msg.shift() // Pop the first element
78
+ const event = this._channelMap[channelId]
79
+
80
+ if (msg[0] === 'hb') {
81
+ return debug(`received heartbeat in ${event.channel}`)
82
+ }
83
+
84
+ if (event) {
85
+ debug('Message in \'%s\' channel', event.channel)
86
+
87
+ if (event.channel === 'book') {
88
+ this._processBookEvent(msg, event)
89
+ } else if (event.channel === 'trades') {
90
+ this._processTradeEvent(msg, event)
91
+ } else if (event.channel === 'ticker') {
92
+ this._processTickerEvent(msg, event)
93
+ } else if (event.channel === 'auth') {
94
+ this._processUserEvent(msg)
95
+ } else {
96
+ debug('Message in unknown channel')
97
+ }
98
+ }
99
+ }
100
+
101
+ _processUserEvent (msg) {
102
+ const event = msg[0]
103
+ const data = msg[1]
104
+
105
+ if (Array.isArray(data[0])) {
106
+ data[0].forEach((ele) => {
107
+ debug('Emitting \'%s\' %j', event, ele)
108
+ this.emit(event, ele)
109
+ })
110
+ } else if (data.length) {
111
+ debug('Emitting \'%s\', %j', event, data)
112
+ this.emit(event, data)
113
+ }
114
+ }
115
+
116
+ _processTickerEvent (msg, event) {
117
+ if (msg.length > 9) { // Update
118
+ // All values are numbers
119
+ const update = {
120
+ bid: msg[0],
121
+ bidSize: msg[1],
122
+ ask: msg[2],
123
+ askSize: msg[3],
124
+ dailyChange: msg[4],
125
+ dailyChangePerc: msg[5],
126
+ lastPrice: msg[6],
127
+ volume: msg[7],
128
+ high: msg[8],
129
+ low: msg[9]
130
+ }
131
+
132
+ debug('Emitting ticker, %s, %j', event.pair, update)
133
+ this.emit('ticker', event.pair, update)
134
+ }
135
+ }
136
+
137
+ _processTradeEvent (msg, event) {
138
+ if (isSnapshot(msg)) {
139
+ const snapshot = msg[0].map(el => ({
140
+ seq: el[0],
141
+ timestamp: el[1],
142
+ price: el[2],
143
+ amount: el[3]
144
+ }))
145
+
146
+ debug('Emitting trade snapshot, %s, %j', event.pair, snapshot)
147
+ this.emit('trade', event.pair, snapshot)
148
+ return
149
+ }
150
+
151
+ if (msg[0] !== 'te' && msg[0] !== 'tu') return
152
+
153
+ // seq is a string, other payload members are nums
154
+ const update = { seq: msg[1] }
155
+
156
+ if (msg[0] === 'te') { // Trade executed
157
+ update.timestamp = msg[2]
158
+ update.price = msg[3]
159
+ update.amount = msg[4]
160
+ } else { // Trade updated
161
+ update.id = msg[2]
162
+ update.timestamp = msg[3]
163
+ update.price = msg[4]
164
+ update.amount = msg[5]
165
+ }
166
+
167
+ // See http://docs.bitfinex.com/#trades75
168
+ debug('Emitting trade, %s, %j', event.pair, update)
169
+ this.emit('trade', event.pair, update)
170
+ }
171
+
172
+ _processBookEvent (msg, event) {
173
+ // TODO: Maybe break this up into snapshot/normal handlers? Also trade event
174
+ if (!isSnapshot(msg[0]) && msg.length > 2) {
175
+ let update
176
+
177
+ if (event.prec === 'R0') {
178
+ update = {
179
+ price: msg[1],
180
+ orderId: msg[0],
181
+ amount: msg[2]
182
+ }
183
+ } else {
184
+ update = {
185
+ price: msg[0],
186
+ count: msg[1],
187
+ amount: msg[2]
188
+ }
189
+ }
190
+
191
+ debug('Emitting orderbook, %s, %j', event.pair, update)
192
+ this.emit('orderbook', event.pair, update)
193
+ return
194
+ }
195
+
196
+ msg = msg[0]
197
+
198
+ if (isSnapshot(msg)) {
199
+ const snapshot = msg.map((el) => {
200
+ if (event.prec === 'R0') {
201
+ return {
202
+ orderId: el[0],
203
+ price: el[1],
204
+ amount: el[2]
205
+ }
206
+ }
207
+
208
+ return {
209
+ price: el[0],
210
+ count: el[1],
211
+ amount: el[2]
212
+ }
213
+ })
214
+
215
+ debug('Emitting orderbook snapshot, %s, %j', event.pair, snapshot)
216
+ this.emit('orderbook', event.pair, snapshot)
217
+ }
218
+ }
219
+
220
+ close () {
221
+ this._ws.close()
222
+ }
223
+
224
+ _onWSOpen () {
225
+ this._channelMap = {}
226
+ this.emit('open')
227
+ }
228
+
229
+ _onWSError (error) {
230
+ this.emit('error', error)
231
+ }
232
+
233
+ _onWSClose () {
234
+ this.emit('close')
235
+ }
236
+
237
+ send (msg) {
238
+ debug('Sending %j', msg)
239
+ this._ws.send(JSON.stringify(msg))
240
+ }
241
+
242
+ /**
243
+ * Subscribe to order book updates. Snapshot will be sent as multiple updates.
244
+ * Event will be emited as `PAIRNAME_book`.
245
+ *
246
+ * @param {string} pair - BTCUSD, LTCUSD or LTCBTC. Default BTCUSD
247
+ * @param {string} precision - price aggregation level (P0 (def), P1, P2, P3)
248
+ * @param {string} length - number of price points. 25 (default) or 100.
249
+ * @see http://docs.bitfinex.com/#order-books
250
+ */
251
+ subscribeOrderBook (pair = 'BTCUSD', prec = 'P0', len = '25') {
252
+ this.send({
253
+ event: 'subscribe',
254
+ channel: 'book',
255
+ pair,
256
+ prec,
257
+ len
258
+ })
259
+ }
260
+
261
+ /**
262
+ * Subscribe to trades. Snapshot will be sent as multiple updates.
263
+ * Event will be emited as `PAIRNAME_trades`.
264
+ *
265
+ * @param {string} pair - BTCUSD, LTCUSD or LTCBTC. Default BTCUSD
266
+ * @see http://docs.bitfinex.com/#trades75
267
+ */
268
+ subscribeTrades (pair = 'BTCUSD') {
269
+ this.send({
270
+ event: 'subscribe',
271
+ channel: 'trades',
272
+ pair
273
+ })
274
+ }
275
+
276
+ /**
277
+ * Subscribe to ticker updates. The ticker is a high level overview of the
278
+ * state of the market. It shows you the current best bid and ask, as well as
279
+ * the last trade price.
280
+ *
281
+ * Event will be emited as `PAIRNAME_ticker`.
282
+ *
283
+ * @param {string} - pair BTCUSD, LTCUSD or LTCBTC. Default BTCUSD
284
+ * @see http://docs.bitfinex.com/#ticker76
285
+ */
286
+ subscribeTicker (pair = 'BTCUSD') {
287
+ this.send({
288
+ event: 'subscribe',
289
+ channel: 'ticker',
290
+ pair
291
+ })
292
+ }
293
+
294
+ /**
295
+ * Unsubscribe from a channel.
296
+ *
297
+ * @param {number} chanId - ID of the channel received on `subscribed` event
298
+ */
299
+ unsubscribe (chanId) {
300
+ this.send({
301
+ event: 'unsubscribe',
302
+ chanId
303
+ })
304
+ }
305
+
306
+ /**
307
+ * Authenticate the user. Will receive executed traded updates.
308
+ *
309
+ * @see http://docs.bitfinex.com/#wallet-updates
310
+ */
311
+ auth () {
312
+ const { sig, payload } = genAuthSig(this._apiSecret)
313
+
314
+ this.send({
315
+ event: 'auth',
316
+ apiKey: this._apiKey,
317
+ authSig: sig,
318
+ authPayload: payload
319
+ })
320
+ }
321
+ }
322
+
323
+ module.exports = WSv1