-
Notifications
You must be signed in to change notification settings - Fork 20
/
block-watcher.js
182 lines (166 loc) · 5.04 KB
/
block-watcher.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
const Web3Connection = require("./web3-connection");
const Big = require("bignumber.js");
const ethers = require("ethers");
const axios = require("axios");
const SetTokenAbi = require("./abis/SetToken.json");
const ERC20Abi = require("./abis/erc20.json");
const DFPIndexTradeAbi = require("./abis/DFPIndexTrade.json");
const {
ChainId,
Token,
WETH,
Fetcher,
Trade,
Route,
TokenAmount,
TradeType,
} = require("@uniswap/sdk");
const { resolveProperties } = require("ethers/lib/utils");
let lastArbitrageDate;
async function checkPositions(web3) {
const provider = new ethers.providers.InfuraProvider(
"mainnet",
process.env.INFURA_KEY
);
const SetToken = new web3.eth.Contract(
SetTokenAbi,
process.env.DFP_INDEX_ADDRESS
);
const positions = await SetToken.methods.getPositions().call();
let ethSum = new Big(0);
if (positions) {
for (let position of positions) {
let erc20 = new web3.eth.Contract(ERC20Abi, position.component);
let decimals = await erc20.methods.decimals().call();
let uniToken = new Token(ChainId.MAINNET, position.component, decimals);
let pair = await Fetcher.fetchPairData(
uniToken,
WETH[uniToken.chainId],
provider
);
let route = new Route([pair], uniToken);
let returnAmount = new Big(position.unit).times(
route.midPrice.toSignificant(18)
);
ethSum = ethSum.plus(returnAmount);
}
console.log(`Component ETH Value: ${ethSum.toFixed(0)}`);
let dfpIndexToken = new Token(
ChainId.MAINNET,
process.env.DFP_INDEX_ADDRESS,
18
);
let pair = await Fetcher.fetchPairData(
dfpIndexToken,
WETH[dfpIndexToken.chainId],
provider
);
let route = new Route([pair], dfpIndexToken);
let returnAmount = new Big("1000000000000000000").times(
route.midPrice.toSignificant(18)
);
let pctDiff = new Big(100).times(
returnAmount.minus(ethSum).div(returnAmount.plus(ethSum).div(2)).abs()
);
console.log(`DFP Index Price: ${route.midPrice.toSignificant(18)}`);
console.log(`Percentage Price Difference: ${pctDiff.toFixed(18)}`);
if (pctDiff.gt(process.env.PRICE_THRESHOLD)) {
if (lastArbitrageDate && checkDay(lastArbitrageDate, new Date())) {
console.log("Already arbed today");
} else {
const newPrice = ethSum.div(Math.pow(10, 9));
const arbed = await triggerArbitrage(newPrice.toFixed(0));
console.log(arbed);
if (arbed) {
lastArbitrageDate = new Date();
console.log("ARBITRAGE!");
}
}
}
}
}
function checkDay(date1, date2) {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
}
let txSent = false;
async function triggerArbitrage(newPrice) {
if (!txSent) {
console.log(`New Price: ${newPrice}`);
const provider = new ethers.providers.InfuraProvider(
"mainnet",
process.env.INFURA_KEY
);
const signer = ethers.Wallet.fromMnemonic(process.env.MNEMONIC).connect(
provider
);
let DFPIndexTrade = new ethers.Contract(
process.env.DFP_TRADE_ADDRESS,
DFPIndexTradeAbi,
signer
);
txSent = true;
try {
let gasPrice = await axios.get(
`https://data-api.defipulse.com/api/v1/egs/api/ethgasAPI.json?api-key=${process.env.DPD_KEY}`
);
gasPrice = Number(gasPrice.data.fastest) / 10;
let gasLimit = await DFPIndexTrade.estimateGas.initiateArbitrage(
process.env.DFP_INDEX_ADDRESS,
newPrice,
{ value: ethers.utils.parseEther('1.0') }
);
let profit = await DFPIndexTrade.callStatic.initiateArbitrage(
process.env.DFP_INDEX_ADDRESS,
newPrice,
{ value: ethers.utils.parseEther('1.0') }
);
console.log(`Expected Return Amount: ${profit.toString()}`);
console.log('Sending Arbitrage tx...');
let tx = await DFPIndexTrade.initiateArbitrage(
process.env.DFP_INDEX_ADDRESS,
newPrice,
{
value: ethers.utils.parseEther('1.0'),
gasLimit,
gasPrice: ethers.utils.parseUnits(gasPrice, "gwei"),
}
);
txSent = false;
return true;
} catch (e) {
console.log(e);
txSent = false;
return false;
}
} else {
return false;
}
}
let BLOCK_LISTENER;
const _connectListener = () => {
BLOCK_LISTENER = new Web3Connection(listen, "BlockListener");
return BLOCK_LISTENER;
};
async function listen(web3) {
console.log("Starting Block Watcher...");
await checkPositions(web3);
console.log(`finished getting data.....\n\n`);
web3.eth.subscribe("newBlockHeaders", async (error, result) => {
if (error) {
console.error(new Error(error));
return;
}
if (result.number) {
console.log(`Getting Positions for block: ${result.number} >>>>>`);
await checkPositions(web3);
console.log(
`finished getting data for block: ${result.number} .....\n\n`
);
}
});
}
module.exports = _connectListener();