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,214 @@
1
+ 'use strict'
2
+
3
+ const { EventEmitter } = require('events')
4
+
5
+ /**
6
+ * High level OB model to automatically integrate WS updates & maintain sort
7
+ */
8
+ class OrderBook extends EventEmitter {
9
+ /**
10
+ * Initializes the order book with an existing snapshot (array form)
11
+ *
12
+ * @param {Array[]} snapshot
13
+ */
14
+ constructor (snapshot = []) {
15
+ super()
16
+
17
+ if (snapshot && snapshot.length > 0) {
18
+ this.updateFromSnapshot(snapshot)
19
+ } else {
20
+ this.bids = []
21
+ this.asks = []
22
+ }
23
+ }
24
+
25
+ updateFromSnapshot (snapshot) {
26
+ this.bids = []
27
+ this.asks = []
28
+
29
+ for (let i = 0; i < snapshot.length; i++) {
30
+ if (snapshot[i][2] < 0) {
31
+ this.asks.push(snapshot[i])
32
+ } else {
33
+ this.bids.push(snapshot[i])
34
+ }
35
+ }
36
+
37
+ // snapshots may not be sorted
38
+ this.bids.sort((a, b) => b[0] - a[0])
39
+ this.asks.sort((a, b) => a[0] - b[0])
40
+ }
41
+
42
+ /**
43
+ * Integrate an update packet; emits an 'update' event on success
44
+ *
45
+ * @param {Array} entry
46
+ * @return {boolean} success - false if entry doesn't match OB
47
+ */
48
+ updateWith (entry) {
49
+ const [price, count, amount] = entry
50
+ const side = amount < 0 ? this.asks : this.bids
51
+ let insertIndex = -1
52
+
53
+ for (let i = 0; i < side.length; i++) {
54
+ if (insertIndex === -1 && (
55
+ (amount > 0 && price > side[i][0]) ||
56
+ (amount < 0 && price < side[i][0])
57
+ )) {
58
+ insertIndex = i
59
+ }
60
+
61
+ if (side[i][0] === price) {
62
+ if (count === 0) { // remove
63
+ side.splice(i, 1)
64
+ } else {
65
+ side[i] = entry // update
66
+ }
67
+
68
+ this.emit('update', entry)
69
+ return true
70
+ }
71
+ }
72
+
73
+ // remove unkown
74
+ if (count === 0) {
75
+ this.emit('error', new Error(
76
+ `can't remove unknown price level: ${JSON.stringify(entry)}`
77
+ ))
78
+
79
+ return false
80
+ }
81
+
82
+ // add
83
+ if (insertIndex === -1) {
84
+ side.push(entry)
85
+ } else {
86
+ side.splice(insertIndex, 0, entry)
87
+ }
88
+
89
+ this.emit('update', entry)
90
+ return true
91
+ }
92
+
93
+ /**
94
+ * @return {number} price
95
+ */
96
+ midPrice () {
97
+ return (this.asks[0][0] + this.bids[0][0]) / 2
98
+ }
99
+
100
+ /**
101
+ * @return {number} spread - top bid/ask difference
102
+ */
103
+ spread () {
104
+ return this.asks[0][0] - this.bids[0][0]
105
+ }
106
+
107
+ /**
108
+ * @return {number} amount - total buy-side volume
109
+ */
110
+ bidAmount () {
111
+ let amount = 0
112
+
113
+ for (let i = 0; i < this.bids.length; i++) {
114
+ amount += this.bids[i][2]
115
+ }
116
+
117
+ return amount
118
+ }
119
+
120
+ /**
121
+ * @return {number} amount - total sell-side volume
122
+ */
123
+ askAmount () {
124
+ let amount = 0
125
+
126
+ for (let i = 0; i < this.asks.length; i++) {
127
+ amount += this.asks[i][2]
128
+ }
129
+
130
+ return Math.abs(amount)
131
+ }
132
+
133
+ /**
134
+ * @param {number} price
135
+ * @return {Object} entry - unserialized, null if not found
136
+ */
137
+ getEntry (price) {
138
+ const side = this.asks.length > 0 // pick a side w/ incomplete data
139
+ ? price >= this.asks[0][0] ? this.asks : this.bids
140
+ : price <= this.bids[0][0] ? this.bids : this.asks
141
+
142
+ for (let i = 0; i < side.length; i++) {
143
+ if (price === side[i][0]) {
144
+ return OrderBook.unserialize(side[i])
145
+ }
146
+ }
147
+
148
+ return null
149
+ }
150
+
151
+ /**
152
+ * Modifies an array-format OB in place with an update entry. Sort is not
153
+ * gauranteed!
154
+ *
155
+ * @param {number[][]} ob
156
+ * @param {number[]} entry
157
+ * @return {boolean} success - false if entry doesn't match OB
158
+ */
159
+ static updateArrayOBWith (ob, entry) {
160
+ const [price, count] = entry
161
+ let insertIndex = -1
162
+
163
+ for (let i = 0; i < ob.length; i++) {
164
+ if (price > ob[i][0] && insertIndex === -1) insertIndex = i
165
+
166
+ if (ob[i][0] === price) {
167
+ if (count === 0) {
168
+ ob.splice(i, 1) // remove existing
169
+ } else {
170
+ ob[i] = entry // update existing
171
+ }
172
+
173
+ return true
174
+ }
175
+ }
176
+
177
+ // remove unkown
178
+ if (count === 0) return false
179
+
180
+ // add
181
+ if (insertIndex === -1) {
182
+ ob.push(entry)
183
+ } else {
184
+ ob.splice(insertIndex, 0, entry)
185
+ }
186
+
187
+ return true
188
+ }
189
+
190
+ /**
191
+ * Converts an array order book entry or snapshot to an object, with 'price',
192
+ * 'count', and 'amount' keys on entries
193
+ *
194
+ * @param {number[]|number[][]} arr
195
+ * @return {Object} ob - either a map w/ bids & asks, or single entry object
196
+ */
197
+ static unserialize (arr) {
198
+ if (Array.isArray(arr[0])) {
199
+ const entries = arr.map(e => OrderBook.unserialize(e))
200
+ const bids = entries.filter(e => e.amount > 0)
201
+ const asks = entries.filter(e => e.amount < 0)
202
+
203
+ return { bids, asks }
204
+ }
205
+
206
+ return {
207
+ price: arr[0],
208
+ count: arr[1],
209
+ amount: arr[2]
210
+ }
211
+ }
212
+ }
213
+
214
+ module.exports = OrderBook
@@ -0,0 +1,43 @@
1
+ 'use strict'
2
+
3
+ const Model = require('../model')
4
+
5
+ class Position extends Model {
6
+ serialize () {
7
+ return [
8
+ this.symbol,
9
+ this.status,
10
+ this.amount,
11
+ this.basePrice,
12
+ this.marginFunding,
13
+ this.marginFundingType,
14
+ this.pl,
15
+ this.plPerc,
16
+ this.liquidationPrice,
17
+ this.leverage
18
+ ]
19
+ }
20
+
21
+ static unserialize (arr) {
22
+ return {
23
+ symbol: arr[0],
24
+ status: arr[1],
25
+ amount: arr[2],
26
+ basePrice: arr[3],
27
+ marginFunding: arr[4],
28
+ marginFundingType: arr[5],
29
+ pl: arr[6],
30
+ plPerc: arr[7],
31
+ liquidationPrice: arr[8],
32
+ leverage: arr[9]
33
+ }
34
+ }
35
+ }
36
+
37
+ Position.status = {}
38
+ const statuses = ['ACTIVE', 'CLOSED']
39
+ statuses.forEach((s) => {
40
+ Position.status[s] = s
41
+ })
42
+
43
+ module.exports = Position
@@ -0,0 +1,83 @@
1
+ 'use strict'
2
+
3
+ const Model = require('../model')
4
+
5
+ class Tick extends Model {
6
+ serialize () {
7
+ if (!this.symbol) return []
8
+
9
+ if (this.symbol[0] === 't') {
10
+ return [
11
+ this.symbol,
12
+ this.bid,
13
+ this.bidSize,
14
+ this.ask,
15
+ this.askSize,
16
+ this.dailyChange,
17
+ this.dailyChangePerc,
18
+ this.lastPrice,
19
+ this.volume,
20
+ this.high,
21
+ this.low
22
+ ]
23
+ } else {
24
+ return [
25
+ this.symbol,
26
+ this.frr,
27
+ this.bid,
28
+ this.bidSize,
29
+ this.bidPeriod,
30
+ this.ask,
31
+ this.askSize,
32
+ this.askPeriod,
33
+ this.dailyChange,
34
+ this.dailyChangePerc,
35
+ this.lastPrice,
36
+ this.volume,
37
+ this.high,
38
+ this.low
39
+ ]
40
+ }
41
+ }
42
+
43
+ static unserialize (arr) {
44
+ if (Array.isArray(arr[0])) {
45
+ return arr.map(tick => Tick.unserialize(tick))
46
+ } else if (!arr[0]) { // no symbol
47
+ return null
48
+ } else if (arr[0][0] === 't') {
49
+ return {
50
+ symbol: arr[0],
51
+ bid: arr[1],
52
+ bidSize: arr[2],
53
+ ask: arr[3],
54
+ askSize: arr[4],
55
+ dailyChange: arr[5],
56
+ dailyChangePerc: arr[6],
57
+ lastPrice: arr[7],
58
+ volume: arr[8],
59
+ high: arr[9],
60
+ low: arr[10]
61
+ }
62
+ }
63
+
64
+ return {
65
+ symbol: arr[0],
66
+ frr: arr[1],
67
+ bid: arr[2],
68
+ bidSize: arr[3],
69
+ bidPeriod: arr[4],
70
+ ask: arr[5],
71
+ askSize: arr[6],
72
+ askPeriod: arr[7],
73
+ dailyChange: arr[8],
74
+ dailyChangePerc: arr[9],
75
+ lastPrice: arr[10],
76
+ volume: arr[11],
77
+ high: arr[12],
78
+ low: arr[13]
79
+ }
80
+ }
81
+ }
82
+
83
+ module.exports = Tick
@@ -0,0 +1,43 @@
1
+ 'use strict'
2
+
3
+ const Model = require('../model')
4
+
5
+ class Trade extends Model {
6
+ serialize () {
7
+ return [
8
+ this.id,
9
+ this.pair,
10
+ this.mtsCreate,
11
+ this.orderID,
12
+ this.execAmount,
13
+ this.execPrice,
14
+ this.orderType,
15
+ this.orderPrice,
16
+ this.maker ? 1 : 0,
17
+ this.fee,
18
+ this.feeCurrency
19
+ ]
20
+ }
21
+
22
+ static unserialize (arr) {
23
+ if (Array.isArray(arr[0])) {
24
+ return arr.map(trade => Trade.unserialize(trade))
25
+ }
26
+
27
+ return {
28
+ id: arr[0],
29
+ pair: arr[1],
30
+ mtsCreate: arr[2],
31
+ orderID: arr[3],
32
+ execAmount: arr[4],
33
+ execPrice: arr[5],
34
+ orderType: arr[6],
35
+ orderPrice: arr[7],
36
+ maker: arr[8] === 1,
37
+ fee: arr[9],
38
+ feeCurrency: arr[10]
39
+ }
40
+ }
41
+ }
42
+
43
+ module.exports = Trade
@@ -0,0 +1,29 @@
1
+ 'use strict'
2
+
3
+ const Model = require('../model')
4
+
5
+ class TradeTick extends Model {
6
+ serialize () {
7
+ return [
8
+ this.id,
9
+ this.mts,
10
+ this.amount,
11
+ this.price
12
+ ]
13
+ }
14
+
15
+ static unserialize (arr) {
16
+ if (Array.isArray(arr[0])) {
17
+ return arr.map(trade => TradeTick.unserialize(trade))
18
+ }
19
+
20
+ return {
21
+ id: arr[0],
22
+ mts: arr[1],
23
+ amount: arr[2],
24
+ price: arr[3]
25
+ }
26
+ }
27
+ }
28
+
29
+ module.exports = TradeTick
@@ -0,0 +1,34 @@
1
+ 'use strict'
2
+
3
+ const Model = require('../model')
4
+
5
+ class Wallet extends Model {
6
+ serialize () {
7
+ return [
8
+ this.type,
9
+ this.currency,
10
+ this.balance,
11
+ this.unsettledInterest,
12
+ this.balanceAvailable
13
+ ]
14
+ }
15
+
16
+ static unserialize (arr) {
17
+ return {
18
+ type: arr[0],
19
+ currency: arr[1],
20
+ balance: arr[2],
21
+ unsettledInterest: arr[3],
22
+ balanceAvailable: arr[4]
23
+ }
24
+ }
25
+ }
26
+
27
+ Wallet.type = {}
28
+ const types = ['exchange', 'margin', 'funding']
29
+
30
+ types.forEach((t) => {
31
+ Wallet.type[t.toUpperCase()] = t
32
+ })
33
+
34
+ module.exports = Wallet