-
Notifications
You must be signed in to change notification settings - Fork 1
/
cusdt.js
128 lines (105 loc) · 3.17 KB
/
cusdt.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const DVF = require('./dvf')
const _ = require('lodash')
const { splitSymbol, prepareAmount, preparePrice } = require('dvf-utils')
const { PAIR, PRIVATE_KEY, ALCHEMY_URL } = require('./config')
const request = require('request-promise')
let dvf
let lastMidPrice
let tokenQuote
let tokenBase
onStartUp()
let pair, routeBuy, routeSell, buySide, sellSide, midPrice
async function marketMake () {
periodicReplace()
setInterval(periodicReplace, 600000)
}
async function periodicReplace() {
midPrice = await getOraclePrice()
console.log(midPrice)
const haveOpenOrders = await checkIfOpenOrders()
if (midPrice !== lastMidPrice || !haveOpenOrders) {
lastMidPrice = midPrice
replaceOrders()
}
}
async function onStartUp () {
dvf = await DVF()
await syncBalances()
console.log('Starting balances: ', balanceA, balanceB)
marketMake()
}
// Trading Functions
let balanceA
let balanceB
async function cancelOpenOrders () {
const orders = await dvf.getOrders()
orders.forEach(o => {
if (o.symbol != PAIR) return
dvf.cancelOrder(o._id)
})
}
async function checkIfOpenOrders () {
const orders = await dvf.getOrders()
return orders.length > 0
}
async function syncBalances () {
const balances = _.chain(await dvf.getBalance())
.keyBy('token')
.mapValues('available')
.value()
const [quote, base] = splitSymbol(PAIR)
balanceA = dvf.token.fromQuantizedAmount(quote, balances[quote])
balanceB = dvf.token.fromQuantizedAmount(base, balances[base])
balanceA = balanceA === 'NaN' ? 0 : balanceA
balanceB = balanceB === 'NaN' ? 0 : balanceB
}
async function replaceOrders () {
await cancelOpenOrders()
setTimeout(async() => {
await syncBalances()
const balanceToSell = Math.min(0.9 * balanceA, 500000 / lastMidPrice)
placeOrder(-1 * balanceToSell)
const balanceToBuy = Math.min(0.9 * balanceB / lastMidPrice, 500000 / lastMidPrice)
placeOrder(balanceToBuy)
}, 2000)
}
async function placeOrder (amount) {
amount = 100 * Math.trunc(prepareAmount(amount, 0) / 100)
if (amount === '0') return
const [quote, base] = splitSymbol(PAIR)
let price
if (amount > 0) {
price = preparePrice(lastMidPrice * 0.9995)
console.log('Place buy at:', price)
} else {
price = preparePrice(lastMidPrice * 1.00)
console.log('Place sell at:', price)
}
if (!price) return
console.log(amount, price)
try {
await dvf.submitOrder({
symbol: PAIR,
amount,
price,
starkPrivateKey: PRIVATE_KEY.substring(2)
})
} catch (e) {
const error = (e.error && e.error.details && e.error.details.error) || {}
console.warn(`Trade not completed: ${error.error}`)
}
}
let config, quote, base
async function getOraclePrice () {
if (!config) {
[quote, base] = splitSymbol(PAIR)
config = await dvf.getConfig()
}
const tokenContractAddress = config.tokenRegistry[quote].tokenAddress
const apiResponse = await request.get({
url: `https://api.compound.finance/api/v2/ctoken?addresses[]=${tokenContractAddress}`,
json: true
})
console.log('OraclePrice: ', apiResponse.cToken[0].exchange_rate.value)
return parseFloat(apiResponse.cToken[0].exchange_rate.value).toPrecision(4)
}