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,131 @@
1
+ /* eslint-env mocha */
2
+ 'use strict'
3
+
4
+ const PORT = 1337
5
+
6
+ const assert = require('assert')
7
+ const http = require('http')
8
+
9
+ const RESTv1 = require('../../../lib/transports/rest')
10
+
11
+ describe('rest integration test', () => {
12
+ it('should get the fundingbook asks, zero bids, 100 asks', (done) => {
13
+ const opts = { limit_bids: 0, limit_asks: 10 }
14
+ const bhttp = new RESTv1({ url: `http://localhost:${PORT}` })
15
+
16
+ const testResBody = `
17
+ {"bids":[],"asks":[
18
+ {"rate":"72.25","amount":"67.5","period":30,"timestamp":"1495565109.0","frr":"No"},
19
+ {"rate":"72.2501","amount":"297.58737203","period":2,"timestamp":"1495565054.0","frr":"No"},
20
+ {"rate":"72.2601","amount":"200.0","period":2,"timestamp":"1495565002.0","frr":"No"},
21
+ {"rate":"72.9535","amount":"211.8299","period":2,"timestamp":"1495565037.0","frr":"No"},
22
+ {"rate":"73.0","amount":"1319.59397488","period":30,"timestamp":"1495564972.0","frr":"No"},
23
+ {"rate":"76.0827","amount":"1511.9115692","period":30,"timestamp":"1495564965.0","frr":"Yes"},
24
+ {"rate":"76.0827","amount":"19849.81630455","period":30,"timestamp":"1495564972.0","frr":"Yes"},
25
+ {"rate":"76.0827","amount":"1052.68464219","period":30,"timestamp":"1495564972.0","frr":"Yes"},
26
+ {"rate":"109.5","amount":"55.33131648","period":3,"timestamp":"1495565103.0","frr":"No"},
27
+ {"rate":"153.1999","amount":"134.86","period":2,"timestamp":"1495565106.0","frr":"No"}]}
28
+ `
29
+ const server = http.createServer((req, res) => {
30
+ res.writeHead(200, {
31
+ 'Content-Type': 'application/json'
32
+ })
33
+ res.end(testResBody)
34
+ }).listen(PORT, () => {
35
+ bhttp.fundingbook('USD', opts, (err, data) => {
36
+ if (err) throw err
37
+ assert.ok(data)
38
+ assert.equal(data.bids.length, 0)
39
+ assert.equal(data.asks.length, 10)
40
+ server.close()
41
+ done()
42
+ })
43
+ })
44
+ })
45
+
46
+ it('new_order -- post_only: postonly used and true', (done) => {
47
+ const bhttp = new RESTv1({
48
+ apiKey: 'dummykey',
49
+ apiSecret: 'dummysecret',
50
+ url: `http://localhost:${PORT}`
51
+ })
52
+
53
+ const testResBody = '{}'
54
+ const server = http.createServer((req, res) => {
55
+ res.writeHead(200, {
56
+ 'Content-Type': 'application/json'
57
+ })
58
+ const payload = JSON.parse(
59
+ Buffer.from(req.headers['x-bfx-payload'], 'base64').toString('ascii')
60
+ )
61
+
62
+ assert.equal(payload['post_only'], true)
63
+
64
+ res.end(testResBody)
65
+ }).listen(PORT, () => {
66
+ bhttp.new_order('btcusd', '0.1', '0.1', 'bitfinex', 'buy', 'exchange limit', false, true, (err, data) => {
67
+ if (err) throw err
68
+ server.close()
69
+ done()
70
+ })
71
+ })
72
+ })
73
+
74
+ it('new_order -- post_only: postonly not used and hidden true', (done) => {
75
+ const bhttp = new RESTv1({
76
+ apiKey: 'dummykey',
77
+ apiSecret: 'dummysecret',
78
+ url: `http://localhost:${PORT}`
79
+ })
80
+
81
+ const testResBody = '{}'
82
+ const server = http.createServer((req, res) => {
83
+ res.writeHead(200, {
84
+ 'Content-Type': 'application/json'
85
+ })
86
+ const payload = JSON.parse(
87
+ Buffer.from(req.headers['x-bfx-payload'], 'base64').toString('ascii')
88
+ )
89
+
90
+ assert.equal(payload['is_hidden'], true)
91
+ assert.equal(payload['post_only'], undefined)
92
+
93
+ res.end(testResBody)
94
+ }).listen(PORT, () => {
95
+ bhttp.new_order('btcusd', '0.1', '0.1', 'bitfinex', 'buy', 'exchange limit', true, (err, data) => {
96
+ if (err) throw err
97
+ server.close()
98
+ done()
99
+ })
100
+ })
101
+ })
102
+
103
+ it('new_order -- post_only: postonly not used and hidden not used', (done) => {
104
+ const bhttp = new RESTv1({
105
+ apiKey: 'dummykey',
106
+ apiSecret: 'dummysecret',
107
+ url: `http://localhost:${PORT}`
108
+ })
109
+
110
+ const testResBody = '{}'
111
+ const server = http.createServer((req, res) => {
112
+ res.writeHead(200, {
113
+ 'Content-Type': 'application/json'
114
+ })
115
+ const payload = JSON.parse(
116
+ Buffer.from(req.headers['x-bfx-payload'], 'base64').toString('ascii')
117
+ )
118
+
119
+ assert.equal(payload['is_hidden'], undefined)
120
+ assert.equal(payload['post_only'], undefined)
121
+
122
+ res.end(testResBody)
123
+ }).listen(PORT, () => {
124
+ bhttp.new_order('btcusd', '0.1', '0.1', 'bitfinex', 'buy', 'exchange limit', (err, data) => {
125
+ if (err) throw err
126
+ server.close()
127
+ done()
128
+ })
129
+ })
130
+ })
131
+ })
@@ -0,0 +1,80 @@
1
+ /* eslint-env mocha */
2
+ 'use strict'
3
+
4
+ const assert = require('assert')
5
+ const RESTv2 = require('../../../lib/transports/rest2')
6
+ const { MockRESTv2Server } = require('bfx-api-mock-srv')
7
+
8
+ const getTestREST2 = () => {
9
+ return new RESTv2({
10
+ apiKey: 'dummy',
11
+ apiSecret: 'dummy',
12
+ url: 'http://localhost:9999'
13
+ })
14
+ }
15
+
16
+ it('trades: fetches expected data', (done) => {
17
+ const srv = new MockRESTv2Server({ listen: true })
18
+ const r = getTestREST2()
19
+ srv.setResponse('trades.BTCUSD.0.10.50', [42])
20
+
21
+ r.trades('BTCUSD', 0, 10, 50, (err, res) => {
22
+ if (err) return done(err)
23
+
24
+ assert.deepEqual(res, [42])
25
+ srv.close().then(done).catch(done)
26
+ })
27
+ })
28
+
29
+ describe('RESTv2 integration (mock server) tests', () => {
30
+ // [rest2MethodName, finalMockResponseKey, rest2MethodArgs]
31
+ const methods = [
32
+ // public
33
+ ['ticker', 'ticker.BTCUSD', ['BTCUSD']],
34
+ ['tickers', 'tickers', [['tBTCUSD', 'tETHUSD']]],
35
+ ['stats', 'stats.key.context', ['key', 'context']],
36
+ ['candles', 'candles.trade:30m:tBTCUSD.hist', [{ timeframe: '30m', symbol: 'tBTCUSD', section: 'hist' }]],
37
+
38
+ // private
39
+ ['alertList', 'alerts.price', ['price']],
40
+ ['alertSet', 'alert_set.type.symbol.price', ['type', 'symbol', 'price']],
41
+ ['alertDelete', 'alert_del.symbol.price', ['symbol', 'price']],
42
+ ['trades', 'trades.BTCUSD.0.10.50', ['BTCUSD', 0, 10, 50]],
43
+ ['wallets', 'wallets'],
44
+ ['activeOrders', 'active_orders'],
45
+ ['orderHistory', 'orders.sym.start.end.limit', ['sym', 'start', 'end', 'limit']],
46
+ ['positions'],
47
+ ['fundingOffers', 'f_offers.sym', ['sym']],
48
+ ['fundingOfferHistory', 'f_offer_hist.sym.start.end.limit', ['sym', 'start', 'end', 'limit']],
49
+ ['fundingLoans', 'f_loans.sym', ['sym']],
50
+ ['fundingLoanHistory', 'f_loan_hist.sym.start.end.limit', ['sym', 'start', 'end', 'limit']],
51
+ ['fundingCredits', 'f_credits.sym', ['sym']],
52
+ ['fundingCreditHistory', 'f_credit_hist.sym.start.end.limit', ['sym', 'start', 'end', 'limit']],
53
+ ['fundingTrades', 'f_trade_hist.sym.start.end.limit', ['sym', 'start', 'end', 'limit']],
54
+ ['marginInfo', 'margin_info.k', ['k']],
55
+ ['fundingInfo', 'f_info.k', ['k']],
56
+ ['performance'],
57
+ ['calcAvailableBalance', 'calc.sym.dir.rate.type', ['sym', 'dir', 'rate', 'type']]
58
+ ]
59
+
60
+ methods.forEach((m) => {
61
+ const name = m[0]
62
+ const dataKey = m[1] || m[0]
63
+ const args = m[2] || []
64
+
65
+ it(`${name}: fetches expected data`, (done) => {
66
+ const srv = new MockRESTv2Server({ listen: true })
67
+ const r = getTestREST2()
68
+ srv.setResponse(dataKey, [42])
69
+
70
+ args.push((err, res) => {
71
+ if (err) return done(err)
72
+
73
+ assert.deepEqual(res, [42])
74
+ srv.close().then(done).catch(done)
75
+ })
76
+
77
+ r[name].apply(r, args)
78
+ })
79
+ })
80
+ })
@@ -0,0 +1,61 @@
1
+ /* eslint-env mocha */
2
+ 'use strict'
3
+
4
+ const PORT = 1337
5
+
6
+ const assert = require('assert')
7
+ const http = require('http')
8
+
9
+ const REST2 = require('../../../lib/transports/rest2')
10
+
11
+ const bhttp = new REST2({
12
+ apiKey: 'dummy',
13
+ apiSecret: 'dummy',
14
+ url: `http://localhost:${PORT}`
15
+ })
16
+
17
+ const testResBody = `["ente", "gans", "scholle"]`
18
+
19
+ describe('rest2 api client: issue 80 - argumment length auth request', () => {
20
+ it('errors if no payload defined', (done) => {
21
+ const server = http.createServer((req, res) => {
22
+ res.writeHead(200, {
23
+ 'Content-Type': 'text/plain'
24
+ })
25
+ res.end(testResBody)
26
+ })
27
+
28
+ server.listen(PORT, () => {
29
+ bhttp.genericCallback = (err) => {
30
+ assert.ok(err)
31
+
32
+ server.close()
33
+ done()
34
+ }
35
+
36
+ bhttp._makeAuthRequest('/auth/r/orders', () => {})
37
+ })
38
+ })
39
+
40
+ it('succeeds with the right argument length', (done) => {
41
+ const server = http.createServer((req, res) => {
42
+ res.writeHead(200, {
43
+ 'Content-Type': 'text/plain'
44
+ })
45
+ res.end(testResBody)
46
+ })
47
+
48
+ server.listen(PORT, () => {
49
+ bhttp._makeAuthRequest('/auth/r/orders', {}, (err, res) => {
50
+ assert.equal(err, null)
51
+ assert.deepEqual(
52
+ res,
53
+ [ 'ente', 'gans', 'scholle' ]
54
+ )
55
+
56
+ server.close()
57
+ done()
58
+ })
59
+ })
60
+ })
61
+ })
@@ -0,0 +1,49 @@
1
+ /* eslint-env mocha */
2
+ 'use strict'
3
+
4
+ const PORT = 1337
5
+
6
+ const assert = require('assert')
7
+ const http = require('http')
8
+ const REST2 = require('../../../lib/transports/rest2')
9
+
10
+ const bhttp = new REST2({
11
+ apiKey: 'dummy',
12
+ apiSecret: 'dummy',
13
+ url: `http://localhost:${PORT}`
14
+ })
15
+
16
+ const testResBody = `[1765.3,
17
+ 0.56800816,
18
+ 1767.6,
19
+ 1.3874,
20
+ -62.2,
21
+ -0.034,
22
+ 1765.3,
23
+ 14063.54589155,
24
+ 1834.2,
25
+ 1726.3 ]`
26
+
27
+ describe('rest2 api client', () => {
28
+ it('gets a response as JSON', (done) => {
29
+ const server = http.createServer((req, res) => {
30
+ res.writeHead(200, {
31
+ 'Content-Type': 'text/plain'
32
+ })
33
+ res.end(testResBody)
34
+ })
35
+
36
+ server.listen(PORT, () => {
37
+ bhttp.ticker('tBTCUSD', (err, res) => {
38
+ assert.equal(err, null)
39
+ assert.deepEqual(
40
+ res,
41
+ JSON.parse(testResBody)
42
+ )
43
+
44
+ server.close()
45
+ done()
46
+ })
47
+ })
48
+ })
49
+ })
@@ -0,0 +1,26 @@
1
+ /* eslint-env mocha */
2
+ 'use strict'
3
+
4
+ // const assert = require('assert')
5
+ // const RESTv2 = require('../../../lib/transports/rest2')
6
+
7
+ describe.skip('RESTv2 unit tests', () => {
8
+ it('constructor: applies options')
9
+ it('constructor: provides defaults')
10
+ it('_generateNonce: increments internal nonce')
11
+
12
+ it('_makeAuthRequest: calls cb w/ error on missing arguments')
13
+ it('_makeAuthRequest: POSTs to the specified path')
14
+ it('_makeAuthRequest: includes necessary headers')
15
+ it('_makeAuthRequest: calls cb with an error, or response')
16
+ it('_makeAuthRequest: transforms data if needed')
17
+
18
+ it('_makePublicRequest: GETs the specified path')
19
+ it('_makePublicRequest: calls cb with an error, or response')
20
+ it('_makePublicRequest: transforms data if needed')
21
+
22
+ it('_doTransform: returns empty array for no data')
23
+ it('_doTransform: returns data if unable to transform')
24
+ it('_doTransform: returns array of models for snapshots')
25
+ it('_doTransform: returns single model')
26
+ })
@@ -0,0 +1,152 @@
1
+ 'use strict'
2
+ /* eslint-env mocha */
3
+ /* eslint camelcase: "off" */
4
+ /* eslint-disable no-unused-expressions */
5
+
6
+ const assert = require('assert')
7
+ const { expect } = require('chai')
8
+ const DNS = require('dns')
9
+ const RESTv1 = require('../../../lib/transports/rest')
10
+ const _ = require('lodash')
11
+
12
+ describe('REST v1', () => {
13
+ let skipPublic = process.env.SKIP_PUBLIC_REST
14
+
15
+ if (!skipPublic) {
16
+ before((done) => {
17
+ DNS.resolve('api.bitfinex.com', (err) => {
18
+ if (err) skipPublic = true
19
+ done()
20
+ })
21
+ })
22
+ }
23
+
24
+ describe('errors', function () {
25
+ const bfx_rest = new RESTv1()
26
+ this.timeout(5000)
27
+ it('should error out if a bad endpoint is given', () => {
28
+ expect(bfx_rest.make_public_request).to.throw(Error)
29
+ })
30
+ it('should fail on authenticated requests if no api_key and api_secret', () => {
31
+ expect(bfx_rest.account_infos).to.throw(Error)
32
+ })
33
+ })
34
+
35
+ describe('public endpoints', function () {
36
+ const bfx_rest = new RESTv1()
37
+ this.timeout(10000) // bumped from 5k for moments of platform lag
38
+ it('should get a ticker', (done) => {
39
+ if (skipPublic) return done()
40
+
41
+ bfx_rest.ticker('BTCUSD', (error, data) => {
42
+ assert(!error)
43
+ expect(data).to.exist
44
+ expect(_.has(data, ['mid',
45
+ 'bid',
46
+ 'ask',
47
+ 'last_price',
48
+ 'low',
49
+ 'high',
50
+ 'volume',
51
+ 'timestamp']))
52
+ done()
53
+ })
54
+ })
55
+ it('should get the today endpoint', (done) => {
56
+ if (skipPublic) return done()
57
+
58
+ bfx_rest.today('BTCUSD', (error, data) => {
59
+ assert(!error)
60
+ expect(data).to.exist
61
+ done()
62
+ })
63
+ })
64
+ it('should get the stats', (done) => {
65
+ if (skipPublic) return done()
66
+
67
+ bfx_rest.stats('BTCUSD', (error, data) => {
68
+ assert(!error)
69
+ expect(data).to.exist
70
+ expect(_.has(data[0], ['period', 'volume']))
71
+ expect(_.has(data[1], ['period', 'volume']))
72
+ expect(_.has(data[2], ['period', 'volume']))
73
+ done()
74
+ })
75
+ })
76
+ it('should get the fundingbook', (done) => {
77
+ if (skipPublic) return done()
78
+
79
+ bfx_rest.fundingbook('USD', (error, data) => {
80
+ assert(!error)
81
+ expect(data).to.exist
82
+ expect(_.has(data, ['bids', 'asks']))
83
+ expect(_.keys(data.bids[0])).is.eql(['rate', 'amount', 'period', 'timestamp', 'frr'])
84
+ expect(_.keys(data.asks[0])).is.eql(['rate', 'amount', 'period', 'timestamp', 'frr'])
85
+ expect(_.every([data.asks[0] + data.bids[0]]), !NaN).ok
86
+ done()
87
+ })
88
+ })
89
+
90
+ it('should get the orderbook', (done) => {
91
+ if (skipPublic) return done()
92
+
93
+ bfx_rest.orderbook('BTCUSD', (error, data) => {
94
+ assert(!error)
95
+ expect(data).to.exist
96
+ expect(_.keys(data)).is.eql(['bids', 'asks'])
97
+ expect(_.keys(data.bids[0])).is.eql(['price', 'amount', 'timestamp'])
98
+ expect(_.keys(data.asks[0])).is.eql(['price', 'amount', 'timestamp'])
99
+ expect(_.every([data.asks[0] + data.bids[0]]), !NaN).ok
100
+ done()
101
+ })
102
+ })
103
+ it('should get recent trades', (done) => {
104
+ if (skipPublic) return done()
105
+
106
+ bfx_rest.trades('BTCUSD', (error, data) => {
107
+ assert(!error)
108
+ expect(data).is.an.array
109
+ expect(data.length).to.eql(100)
110
+ expect(_.keys(data[0])).to.eql(['timestamp', 'tid', 'price', 'amount', 'exchange', 'type'])
111
+ expect(
112
+ _.map(_.values(data[0]), (v) => typeof (v))
113
+ ).is.eql(['number', 'number', 'string', 'string', 'string', 'string'])
114
+ done()
115
+ })
116
+ })
117
+ it('should get recent lends', (done) => {
118
+ if (skipPublic) return done()
119
+
120
+ bfx_rest.lends('USD', (error, data) => {
121
+ assert(!error)
122
+ expect(data).to.exist
123
+ expect(data).is.an.array
124
+ expect(data.length).to.eql(50)
125
+ expect(_.keys(data[0])).to.eql(['rate', 'amount_lent', 'amount_used', 'timestamp'])
126
+ expect(
127
+ _.map(_.values(data[0]), (v) => typeof (v))
128
+ ).is.eql(['string', 'string', 'string', 'number'])
129
+ done()
130
+ })
131
+ })
132
+ it('should get symbols', (done) => {
133
+ if (skipPublic) return done()
134
+
135
+ bfx_rest.get_symbols((error, data) => {
136
+ assert(!error)
137
+ expect(data[0]).to.eql('btcusd')
138
+ done()
139
+ })
140
+ })
141
+ it('should get symbol details', (done) => {
142
+ if (skipPublic) return done()
143
+
144
+ bfx_rest.symbols_details((error, data) => {
145
+ assert(!error)
146
+ expect(data).to.exist
147
+ expect(data[0].pair).to.eql('btcusd')
148
+ done()
149
+ })
150
+ })
151
+ })
152
+ })
@@ -0,0 +1,83 @@
1
+ /* eslint-env mocha */
2
+ 'use strict'
3
+
4
+ const assert = require('assert')
5
+ const BfxWs = require('../../../lib/transports/ws.js')
6
+
7
+ const bfxWs = new BfxWs({
8
+ apiKey: 'dummy',
9
+ apiSecret: 'dummy'
10
+ })
11
+
12
+ describe('ws1 channel msg handling', () => {
13
+ it('ws1 transforms & normalizes well - R0 update', (done) => {
14
+ bfxWs._channelMap = {
15
+ 32755: { channel: 'book', prec: 'R0', symbol: 'tBTCUSD' }
16
+ }
17
+
18
+ bfxWs.once('orderbook', (symbol, data) => {
19
+ assert.deepEqual(data, { price: 2477.1, orderId: 2919111002, amount: 0.0125 })
20
+ done()
21
+ })
22
+
23
+ bfxWs._handleChannel([ 32755, 2919111002, 2477.1, 0.0125 ])
24
+ })
25
+
26
+ it('ws1 transforms & normalizes well - P1 update', (done) => {
27
+ bfxWs._channelMap = {
28
+ 182: { channel: 'book', prec: 'P1', symbol: 'tBTCUSD' }
29
+ }
30
+
31
+ bfxWs.once('orderbook', (symbol, data) => {
32
+ assert.deepEqual(data, { price: 2494, count: 2, amount: 5.9895 })
33
+ done()
34
+ })
35
+
36
+ bfxWs._handleChannel([ 182, 2494, 2, 5.9895 ])
37
+ })
38
+
39
+ it('ws1 transforms & normalizes well - P1 snap', (done) => {
40
+ bfxWs._channelMap = {
41
+ 39: { channel: 'book', prec: 'P1', symbol: 'tBTCUSD' }
42
+ }
43
+
44
+ bfxWs.once('orderbook', (symbol, data) => {
45
+ assert.deepEqual(data[1], { price: 2494, count: 3, amount: 0.14606853 })
46
+ done()
47
+ })
48
+
49
+ const snap = [ 39, [
50
+ [ 2495, 2, 0.8744 ],
51
+ [ 2494, 3, 0.14606853 ],
52
+ [ 2492, 1, 0.4 ]
53
+ ]]
54
+
55
+ bfxWs._handleChannel(snap)
56
+ })
57
+
58
+ it('ws1 transforms & normalizes well - R0 snap', (done) => {
59
+ bfxWs._channelMap = {
60
+ 34513: { channel: 'book', prec: 'R0', symbol: 'tBTCUSD' }
61
+ }
62
+
63
+ bfxWs.once('orderbook', (symbol, data) => {
64
+ assert.deepEqual(
65
+ data[1],
66
+ { price: 2494.5, orderId: 2919279471, amount: 0.07288 }
67
+ )
68
+ done()
69
+ })
70
+
71
+ const snap = [ 34513, [
72
+ [ 2919278474, 2494.5, 0.07901704 ],
73
+ [ 2919279471, 2494.5, 0.07288 ],
74
+ [ 2919280093, 2494.5, 0.03644 ]
75
+ ]]
76
+
77
+ bfxWs._handleChannel(snap)
78
+ })
79
+
80
+ it('ws1 _handleChannel ignores heartbeats')
81
+ it('ws1 _processUserEvent emits data, breaks up snapshots')
82
+ it('ws1 _processTradeEvent emits a single trade for te & tu messages')
83
+ })
@@ -0,0 +1,40 @@
1
+ /* eslint-env mocha */
2
+ 'use strict'
3
+
4
+ const PORT = 1337
5
+
6
+ const assert = require('assert')
7
+ const WebSocket = require('ws')
8
+ const WSv1 = require('../../../lib/transports/ws')
9
+
10
+ describe('websocket1 parsing non json', () => {
11
+ it('should not crash the client', (done) => {
12
+ const bws = new WSv1({
13
+ apiKey: 'dummy',
14
+ apiSecret: 'dummy',
15
+ url: `ws://localhost:${PORT}`
16
+ })
17
+
18
+ bws.open()
19
+
20
+ const wss = new WebSocket.Server({
21
+ perMessageDeflate: false,
22
+ port: PORT
23
+ })
24
+
25
+ wss.on('connection', function connection (ws) {
26
+ ws.on('message', function incoming (msg) {
27
+ msg = JSON.parse(msg)
28
+ assert.equal(msg.len, '25')
29
+ wss.close()
30
+ done()
31
+ })
32
+
33
+ ws.send("HTTP Code 408 - I'm a Tea Pot")
34
+ })
35
+
36
+ bws.on('open', () => {
37
+ bws.subscribeOrderBook('BTCUSD', 'R0')
38
+ })
39
+ })
40
+ })