· 6 years ago · Dec 23, 2019, 10:06 AM
1
2const rp = require('request-promise');
3const axios = require('axios')
4const Crypto = require('crypto');
5const config = require('./config.json')
6
7const API = "https://api.bittrex.com/api/v1.1"
8const KEY = config.key
9const SECRET = config.secret
10
11
12async function getExpAskBid() {
13 let data = await rp(`${API}/public/getticker?market=BTC-EXP`)
14 data = JSON.parse(data)
15 if(data.success) return data.result
16}
17
18async function getAccountBalance(currency = "EXP") {
19 const nonce = Date.now()
20 const url = `${API}/account/getbalance?apikey=${KEY}¤cy=${currency}&nonce=${nonce}`
21 const res = await makeCall(url)
22 if(res)
23 return { success: true, data: res }
24 return { success: false, reason: "Error, cannot get balances"}
25}
26
27async function sellExp(amount, price) {
28 const nonce = Date.now()
29 const url = `${API}/market/selllimit?apikey=${KEY}&market=BTC-EXP&quantity=${amount}&rate=${price}&nonce=${nonce}`
30 const res = await makeCall(url)
31 return res
32}
33
34async function buyExp(amount, price) {
35 const nonce = Date.now()
36 const url = `${API}/market/buylimit?apikey=${KEY}&market=BTC-EXP&quantity=${amount}&rate=${price}&nonce=${nonce}`
37 const res = await makeCall(url)
38 return res
39}
40
41
42async function getMyOpenOrders(type = "all") {
43 const nonce = Date.now()
44 const url = `${API}/market/getopenorders?apikey=${KEY}&market=BTC-EXP&nonce=${nonce}`
45 const signature = Crypto.createHmac('sha512', SECRET)
46 .update(url)
47 .digest('hex');
48 const data = await axios({
49 method: 'get',
50 url: url,
51 headers: {
52 apisign: signature
53 }
54 })
55 if(data.data.success) {
56 const allOrders = data.data.result
57 switch(type) {
58 case "all":
59 return allOrders
60 break
61 case "sell":
62 // return lowest Ask
63 const sellOrders = allOrders.filter(order => order.OrderType == "LIMIT_SELL")
64 if(sellOrders.length === 0) return null
65 const lowestAsk = sellOrders.sort(compare)[0]
66 return lowestAsk.Limit
67 break
68 case "buy":
69 // return highest Bid
70 const buyOrders = allOrders.filter(order => order.OrderType == "LIMIT_BUY")
71 if(buyOrders.length === 0) return null
72 const highestBid = buyOrders.sort(compare)[buyOrders.length - 1]
73 return highestBid.Limit
74 break
75 }
76 }
77}
78
79async function checkBalances() {
80 console.log("--- Check balances")
81 const allExp = await getAccountBalance("EXP")
82 const allBtc = await getAccountBalance("BTC")
83 const { Ask, Bid } = await getExpAskBid()
84 const availableExp = Number(allExp.data.Available)
85 const availableBtc = Number(allBtc.data.Available)
86
87 if((availableBtc) >= 0.0005) {
88 let buyPrice = Number(Bid) + 0.00000001
89 const expAmount = availableBtc/buyPrice;
90 console.log(`--- Create buy order at ${buyPrice} sats`)
91 const lowestAsk = await getMyOpenOrders("sell")
92 if(Number(lowestAsk) === Number(buyPrice)) {
93 return {error: true, reason: "Bot cannot trade with ourselves"}
94 }
95 await buyExp(parseInt(expAmount)-1, Number(buyPrice.toFixed(9)))
96 }
97 if((availableExp*Number(Ask)) >= 0.0005) {
98 const sellPrice = Number(Ask) - 0.00000001
99 console.log(`--- Create sell order at ${sellPrice} sats`)
100 const highestBid = await getMyOpenOrders("buy")
101 if(Number(highestBid) === Number(sellPrice)) {
102 return {error: true, reason: "Bot cannot trade with ourselves"}
103 }
104 await sellExp(availableExp, sellPrice.toFixed(9))
105 }
106}
107
108async function run() {
109 checkBalances()
110 // check balances every 1 hour
111 setInterval(checkBalances, 60*60*1000)
112 // check orders every 2 hours
113 setInterval(checkOrdersRange, 120*60*1000)
114}
115run()
116
117
118
119async function checkOrdersRange() {
120 console.log("--- Check orders range")
121 const uuidsOrders = [];
122 const allOrders = await getMyOpenOrders("all");
123 if(allOrders.length > 0) {
124 const { Ask, Bid } = await getExpAskBid()
125 let spreadAsk = Ask+(Ask*0.05)
126 let spreadBid = Bid-(Bid*0.05)
127 for(let i = 0; i < allOrders.length; i++) {
128 // compare Limit and ask/bid range
129 if(allOrders[i].Limit >= spreadBid && allOrders[i].Limit <= spreadAsk ) {
130 console.log("Orders in fine range")
131 } else {
132 uuidsOrders.push(allOrders[i].OrderUuid)
133 }
134 }
135 if(uuidsOrders.length > 0) {
136 cancelOrders(uuidsOrders)
137 }
138 }
139}
140
141function cancelOrders(uuidsOrders) {
142 uuidsOrders.forEach(async uuid => {
143 const nonce = Date.now()
144 const url = `${API}/market/cancel?apikey=${KEY}&uuid=${uuid}&nonce=${nonce}`
145 const signature = Crypto.createHmac('sha512', SECRET)
146 .update(url)
147 .digest('hex');
148 const { data } = await axios({
149 method: 'get',
150 url: url,
151 headers: {
152 apisign: signature
153 }
154 })
155 if(data.success) {
156 console.log(`Order ${uuid} canceled.`)
157 }
158 })
159}
160
161
162async function makeCall(url) {
163 const signature = Crypto.createHmac('sha512', SECRET)
164 .update(url)
165 .digest('hex');
166 const data = await axios({
167 method: 'get',
168 url: url,
169 headers: {
170 apisign: signature
171 }
172 })
173 if(data.data.success)
174 return data.data.result
175}
176
177function compare(a,b) {
178 const limitA = Number(a.Limit)
179 const limitB = Number(b.Limit)
180 let comprasion
181 if(limitA > limitB) {
182 comprasion = 1
183 } else if(limitB > limitA) {
184 comprasion = -1
185 }
186 return comprasion
187}