binance-spot.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. const BinanceKit = require('./binance-kit')
  2. const HttpKit = require('../../kit/http-kit')
  3. const TimeKit = require("../../kit/time-kit");
  4. const HTTPRequest = require('request')
  5. const assert = require("assert");
  6. const isDev = process.env.USER === 'skyfffire'
  7. const proxy = 'http://localhost:9080'
  8. class BinanceSpot {
  9. static BASE_URL = 'https://api.binance.com'
  10. static TRADE_TYPE = {
  11. MARKET: 'MARKET'
  12. }
  13. static TRADE_SIDE = {
  14. BUY: 'buy',
  15. SELL: 'sell'
  16. }
  17. static PRICE = {
  18. MARKET: -1
  19. }
  20. static NETWORK = {
  21. BSC: 'BSC'
  22. }
  23. static BASE_TOKEN = {
  24. BUSD: 'BUSD'
  25. }
  26. static INTERVAL = {
  27. H1: '1h',
  28. H4: '4h'
  29. }
  30. constructor(apiKey, secretKey) {
  31. this.apiKey = apiKey
  32. this.secretKey = secretKey
  33. }
  34. static async realPrice(symbol='BNBBUSD', side=BinanceSpot.TRADE_SIDE.BUY) {
  35. const url = `${BinanceSpot.BASE_URL}/api/v3/depth?symbol=${symbol}&limit=${5}`
  36. const { data: rst } = await HttpKit.get(url)
  37. if (!rst || !rst.bids || !rst.asks || !rst.bids[0] || !rst.asks[0]) {
  38. return 0
  39. }
  40. if (side === BinanceSpot.TRADE_SIDE.SELL) {
  41. return parseFloat(rst.bids[0][0])
  42. } else {
  43. return parseFloat(rst.asks[0][0])
  44. }
  45. }
  46. static async klines(symbol='BNBBUSD', interval=BinanceSpot.INTERVAL.H1, limit=20) {
  47. const url = `${BinanceSpot.BASE_URL}/api/v3/klines?symbol=${symbol}&interval=${interval}&limit=${limit}`
  48. const { data: rst } = await HttpKit.get(url)
  49. return rst
  50. }
  51. static async exchangeInfo(symbols=['BNBBUSD', 'BTCBUSD']) {
  52. const url = `${BinanceSpot.BASE_URL}/api/v3/exchangeInfo?symbols=${BinanceKit.buildExchangeInfoSymbols(symbols)}`
  53. const { data: rst } = await HttpKit.get(url)
  54. return rst
  55. }
  56. async accountInfo() {
  57. const url = `${BinanceSpot.BASE_URL}/api/v3/account`
  58. let timestamp = new Date().getTime()
  59. let data = {
  60. timestamp: timestamp
  61. }
  62. let signature = BinanceKit.createSignature(this.secretKey, data)
  63. let finalQueryURL = BinanceKit.toFinalQueryURL(url, data, signature)
  64. let headers = {
  65. 'X-MBX-APIKEY': this.apiKey
  66. }
  67. const { data: rst } = await HttpKit.get(finalQueryURL, headers)
  68. return rst
  69. }
  70. async withdraw(amount, coin=BinanceSpot.BASE_TOKEN.BUSD,
  71. address='0xCfB3Cb29EeAE464ABD44E35d53e12c555705e824', network=BinanceSpot.NETWORK.BSC) {
  72. const url = `${BinanceSpot.BASE_URL}/sapi/v1/capital/withdraw/apply`
  73. let timestamp = new Date().getTime()
  74. let data = {
  75. timestamp: timestamp,
  76. coin: coin,
  77. address: address,
  78. amount: amount,
  79. network: network
  80. }
  81. let signature = BinanceKit.createSignature(this.secretKey, data)
  82. let finalQueryURL = BinanceKit.toFinalQueryURL(url, data, signature)
  83. let headers = {
  84. 'X-MBX-APIKEY': this.apiKey
  85. }
  86. const { data: rst } = await HttpKit.post(finalQueryURL, data, headers)
  87. return rst
  88. }
  89. async takeOrder(symbol='BTCUSDT', price, side, quantity, quoteOrderQty, type=BinanceSpot.TRADE_TYPE.MARKET) {
  90. const url = `${BinanceSpot.BASE_URL}/api/v3/order`
  91. let timestamp = new Date().getTime()
  92. let data = {
  93. timestamp: timestamp,
  94. symbol: symbol,
  95. side: side,
  96. type: type,
  97. recvWindow: 60 * 1000
  98. }
  99. // 区分买卖情况应该分别传入什么数量
  100. if (side === BinanceSpot.TRADE_SIDE.BUY) data['quoteOrderQty'] = quoteOrderQty
  101. else if (side === BinanceSpot.TRADE_SIDE.SELL) data['quantity'] = quantity
  102. // MARKET状态不传入price
  103. if (type !== 'MARKET') data['price'] = price
  104. let signature = BinanceKit.createSignature(this.secretKey, data)
  105. let finalQueryURL = BinanceKit.toFinalQueryURL(url, data, signature)
  106. let headers = {
  107. 'X-MBX-APIKEY': this.apiKey
  108. }
  109. const params = {
  110. url: finalQueryURL,
  111. method: 'POST',
  112. headers: headers,
  113. proxy: isDev ? proxy : undefined
  114. }
  115. let finish = false
  116. let rst = undefined
  117. HTTPRequest(params, function (error, response) {
  118. // 请求成功的处理逻辑
  119. if (!error) {
  120. rst = JSON.parse(response.body)
  121. } else {
  122. rst = error
  123. }
  124. finish = true
  125. })
  126. while (!finish) {
  127. await TimeKit.sleep(10)
  128. }
  129. return rst
  130. }
  131. async buy(pair, price, quoteOrderQty, type=BinanceSpot.TRADE_TYPE.MARKET) {
  132. return await this.takeOrder(
  133. pair,
  134. price,
  135. BinanceSpot.TRADE_SIDE.BUY,
  136. 0,
  137. quoteOrderQty,
  138. type)
  139. }
  140. async sell(pair, price, quantity, type=BinanceSpot.TRADE_TYPE.MARKET) {
  141. return await this.takeOrder(
  142. pair,
  143. price,
  144. BinanceSpot.TRADE_SIDE.SELL,
  145. quantity,
  146. 0,
  147. type)
  148. }
  149. async buyMarket(pair, quoteOrderQty) {
  150. const buyRst = await this.buy(pair, -1, quoteOrderQty)
  151. assert.notEqual(buyRst.executedQty, undefined, JSON.stringify(buyRst))
  152. const cummulativeQuoteQty = parseFloat(buyRst.cummulativeQuoteQty)
  153. // 计算扣除手续费后的实际成交数量
  154. let executedQty = 0
  155. for (const fill of buyRst.fills) {
  156. executedQty += parseFloat(fill.qty)
  157. // 扣除支付的手续费
  158. if (fill.commissionAsset !== 'BNB') executedQty -= parseFloat(fill.commission)
  159. }
  160. return {
  161. cummulativeQuoteQty: cummulativeQuoteQty,
  162. executedQty: executedQty,
  163. avgPrice: cummulativeQuoteQty / executedQty
  164. }
  165. }
  166. async sellMarket(pair, quantity) {
  167. const sellRst = await this.sell(pair, -1, quantity)
  168. assert.notEqual(sellRst.executedQty, undefined, JSON.stringify(sellRst))
  169. let cummulativeQuoteQty = parseFloat(sellRst.cummulativeQuoteQty)
  170. // 计算扣除手续费后的实际成交数量
  171. let executedQty = 0
  172. for (const fill of sellRst.fills) {
  173. executedQty += parseFloat(fill.qty)
  174. // 扣除支付的手续费
  175. if (fill.commissionAsset !== 'BNB') cummulativeQuoteQty -= parseFloat(fill.commission)
  176. }
  177. return {
  178. cummulativeQuoteQty: cummulativeQuoteQty,
  179. executedQty: executedQty,
  180. avgPrice: cummulativeQuoteQty / executedQty
  181. }
  182. }
  183. }
  184. module.exports = BinanceSpot