binance-spot.js 5.8 KB

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