Skip to content

Instantly share code, notes, and snippets.

@korrio
Created July 31, 2024 06:33
Show Gist options
  • Save korrio/fa93de855aff6236dcaeb39697a913e0 to your computer and use it in GitHub Desktop.
Save korrio/fa93de855aff6236dcaeb39697a913e0 to your computer and use it in GitHub Desktop.
bot.js
const ethers = require('ethers');
const { ChainId, Token, Fetcher, Route, Trade, TokenAmount, TradeType, Percent } = require('@uniswap/sdk');
const { abi: IUniswapV2PairABI } = require('@uniswap/v2-core/build/IUniswapV2Pair.json');
const { abi: IUniswapV2Router02ABI } = require('@uniswap/v2-periphery/build/IUniswapV2Router02.json');
// Configuration
const ALCHEMY_URL = 'https://eth-mainnet.g.alchemy.com/v2/jssjArgnoSmS2Uv5RMVwQAySLhkBsOnJ';
//const ALCHEMY_URL_TESTNET = 'https://eth-sepolia.g.alchemy.com/v2/jssjArgnoSmS2Uv5RMVwQAySLhkBsOnJ';
const DAI_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
const WETH_ADDRESS = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
const UNISWAP_ROUTER_ADDRESS = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D';
const SUSHISWAP_ROUTER_ADDRESS = '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F';
const ARBITRAGE_THRESHOLD = 1; // 1% price difference
const AMOUNT_ETH = '1'; // Amount of ETH to check for arbitrage
// Create provider
let provider;
try {
provider = new ethers.providers.JsonRpcProvider(ALCHEMY_URL);
} catch (error) {
console.error('Failed to create provider:', error);
process.exit(1);
}
// สร้าง wallet จาก private key
const privateKey = '562b89ec5422eb55a52be67dd5d26e93a4c3c9a33cb55158c03d97e82dab40c3'; // อย่าใช้ private key ของ wallet หลัก!
const wallet = new ethers.Wallet(privateKey, provider);
console.log('Wallet address:', wallet.address);
// ตรวจสอบยอดคงเหลือ
async function checkBalance() {
const balance = await provider.getBalance(wallet.address);
console.log('Wallet balance:', ethers.utils.formatEther(balance), 'ETH');
}
checkBalance();
// Create token instances
const DAI = new Token(ChainId.MAINNET, DAI_ADDRESS, 18);
const WETH = new Token(ChainId.MAINNET, WETH_ADDRESS, 18);
// DEX configurations
// Create router instances
const uniswapRouter = new ethers.Contract(UNISWAP_ROUTER_ADDRESS, IUniswapV2Router02ABI, provider);
const sushiswapRouter = new ethers.Contract(SUSHISWAP_ROUTER_ADDRESS, IUniswapV2Router02ABI, provider);
async function getPriceOnDEX(router, tokenIn, tokenOut, amount) {
try {
const amounts = await router.getAmountsOut(amount,[tokenIn.address, tokenOut.address]);
return amounts[1];
} catch (error) {
console.error(`Error getting price on DEX: ${error.message}`);
return null;
}
}
async function checkArbitragePossibility() {
try {
const amount = ethers.utils.parseEther(AMOUNT_ETH);
console.log('Fetching prices...');
const uniswapPrice = await getPriceOnDEX(uniswapRouter, WETH, DAI, amount);
const sushiswapPrice = await getPriceOnDEX(sushiswapRouter, WETH, DAI, amount);
if (!uniswapPrice || !sushiswapPrice) {
console.log("Failed to fetch prices from one or both DEXes. Retrying in 5 seconds...");
setTimeout(checkArbitragePossibility, 5000);
return;
}
console.log(`Uniswap price: 1 WETH = ${ethers.utils.formatUnits(uniswapPrice, 18)} DAI`);
console.log(`Sushiswap price: 1 WETH = ${ethers.utils.formatUnits(sushiswapPrice, 18)} DAI`);
const priceDifference = uniswapPrice.gt(sushiswapPrice) ? uniswapPrice.sub(sushiswapPrice)
: sushiswapPrice.sub(uniswapPrice);
const priceDifferencePercent = priceDifference.mul(10000).div(uniswapPrice);
console.log(`Price difference: ${priceDifferencePercent.toNumber() / 100}%`);
if (priceDifferencePercent.gte(ethers.BigNumber.from(ARBITRAGE_THRESHOLD * 100))) {
console.log('Arbitrage opportunity found!');
if (uniswapPrice.gt(sushiswapPrice)) {
console.log("Buy on Sushiswap, sell on Uniswap");
await simulateArbitrage(sushiswapRouter, uniswapRouter, amount);
} else {
console.log("Buy on Uniswap, sell on Sushiswap");
await simulateArbitrage(uniswapRouter, sushiswapRouter, amount);
}
} else {
console.log("No significant arbitrage opportunity at the moment");
}
// Schedule next check
console.log("Scheduling next check in 1 minute...");
setTimeout(checkArbitragePossibility, 60000);
} catch (error) {
console.error("Error checking arbitrage possibility:", error);
console.log("Retrying in 5 seconds...");
setTimeout(checkArbitragePossibility, 5000);
}
}
async function simulateArbitrage(buyRouter, sellRouter, amount) {
try {
console.log('Simulating arbitrage...');
// Simulate buy
const buyAmount = await getPriceOnDEX(buyRouter, WETH, DAI, amount);
if (!buyAmount) {
console.log('Failed to simulate buy. Aborting arbitrage simulation.');
return;
}
console.log(`Buying ${ethers.utils.formatUnits(buyAmount, 18)} DAI for ${AMOUNT_ETH} WETH`);
// Simulate sell
const sellAmount = await getPriceOnDEX(sellRouter, DAI, WETH, buyAmount);
if (!sellAmount) {
console.log('Failed to simulate sell. Aborting arbitrage simulation.');
return;
}
console.log(`Selling DAI for ${ethers.utils.formatUnits(sellAmount, 18)} WETH`);
// Calculate profit
const profit = sellAmount.sub(amount);
console.log(`Estimated profit: ${ethers.utils.formatUnits(profit, 18)} WETH`);
if (profit.gt(0)) {
console.log('Profitable arbitrage opportunity!');
// Here you would implement the actual trading logic
// This would involve calling the swap functions on the router contracts
// You'd also need to handle approvals, gas fees, and slippage tolerance
} else {
console.log('Arbitrage not profitable after considering potential fees.');
}
} catch (error) {
console.error("Error simulating arbitrage:", error);
}
}
// Start the arbitrage checking process
console.log('Starting arbitrage bot...');
checkArbitragePossibility();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment