-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEthPriceOracle.js
107 lines (97 loc) · 3.33 KB
/
EthPriceOracle.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
const axios = require('axios')
const BN = require('bn.js')
const common = require('./utils/common.js')
const SLEEP_INTERVAL = process.env.SLEEP_INTERVAL || 2000
const PRIVATE_KEY_FILE_NAME = process.env.PRIVATE_KEY_FILE || './oracle/oracle_private_key'
const CHUNK_SIZE = process.env.CHUNK_SIZE || 3
const MAX_RETRIES = process.env.MAX_RETRIES || 5
const OracleJSON = require('./oracle/build/contracts/EthPriceOracle.json')
var pendingRequests = []
async function getOracleContract (web3js) {
const networkId = await web3js.eth.net.getId()
return new web3js.eth.Contract(OracleJSON.abi, OracleJSON.networks[networkId].address)
}
async function filterEvents (oracleContract, web3js) {
oracleContract.events.GetLatestEthPriceEvent(async (err, event) => {
if (err) {
console.error('Error on event', err)
return
}
await addRequestToQueue(event)
})
oracleContract.events.SetLatestEthPriceEvent(async (err, event) => {
if (err) {
console.error('Error on event', err)
return
}
// Do something
})
}
async function addRequestToQueue (event) {
const callerAddress = event.returnValues.callerAddress
const id = event.returnValues.id
pendingRequests.push({ callerAddress, id })
}
async function processQueue (oracleContract, ownerAddress) {
let processedRequests = 0
while (pendingRequests.length > 0 && processedRequests < CHUNK_SIZE) {
const req = pendingRequests.shift()
await processRequest(oracleContract, ownerAddress, req.id, req.callerAddress)
processedRequests++
}
}
async function retrieveLatestEthPrice () {
const resp = await axios({
url: 'https://api.binance.com/api/v3/ticker/price',
params: {
symbol: 'ETHUSDT'
},
method: 'get'
})
return resp.data.price
}
async function processRequest (oracleContract, ownerAddress, id, callerAddress) {
let retries = 0
while (retries < MAX_RETRIES) {
try {
const ethPrice = await retrieveLatestEthPrice()
await setLatestEthPrice(oracleContract, callerAddress, ownerAddress, ethPrice, id)
return
} catch (error) {
if (retries === MAX_RETRIES - 1) {
await setLatestEthPrice(oracleContract, callerAddress, ownerAddress, '0', id)
return
}
retries++
}
}
}
async function setLatestEthPrice (oracleContract, callerAddress, ownerAddress, ethPrice, id) {
ethPrice = ethPrice.replace('.', '')
const multiplier = new BN(10**10, 10)
const ethPriceInt = (new BN(parseInt(ethPrice), 10)).mul(multiplier)
const idInt = new BN(parseInt(id))
try {
await oracleContract.methods.setLatestEthPrice(ethPriceInt.toString(), callerAddress, idInt.toString()).send({ from: ownerAddress })
} catch (error) {
console.log('Error encountered while calling setLatestEthPrice.')
// Do some error handling
}
}
async function init () {
const { ownerAddress, web3js, client } = common.loadAccount(PRIVATE_KEY_FILE_NAME)
const oracleContract = await getOracleContract(web3js)
filterEvents(oracleContract, web3js)
return { oracleContract, ownerAddress, client }
}
(async () => {
const { oracleContract, ownerAddress, client } = await init()
process.on( 'SIGINT', () => {
console.log('Calling client.disconnect()')
client.disconnect()
process.exit( )
})
setInterval(async () => {
await processQueue(oracleContract, ownerAddress)
}, SLEEP_INTERVAL)
})()