const OneInch = require('./1inch.js') const DoDo = require('./dodo.js') const BinanceSpot = require('./BinanceSpot.js') const Config = require('./Config.js') const PrivateConfig = require('./PrivateConfig.js') const MyKit = require('./kit/MyKit.js') const Wallet = require('./wallet.js') const wallet = new Wallet() const bs = new BinanceSpot('-', '-') async function onTickDoDo(toToken) { while (true) { // 如果BNB连续变化maxRefreshBNBTimes次,则1INCH或其他交易所可能已经出bug。 if (Config.refreshBNBTimes >= Config.maxRefreshBNBTimes) { console.log(`机器人判定交易所可能出了bug,失败次数:${Config.refreshBNBTimes},为保护BNB,已停止交易。`) break } try { const tokenSymbol = toToken.symbol const baseToken = Config.baseToken if (!baseToken.balance) { await MyKit.sleep(1000) continue } const binancePairSymbol = tokenSymbol + baseToken.symbol const amount = Config.baseTokenAmount < baseToken.balance ? Config.baseTokenAmount : baseToken.balance const profitLimit = toToken.profitLimit ? toToken.profitLimit : Config.profitLimit const binancePrice = await bs.price(binancePairSymbol) // 一次判断 let time = MyKit.getTimeByMillisecond(new Date().getTime()) // 直接判断并抢单 const DoDoSwapRst = await DoDo.swap(baseToken.contract, baseToken.decimals, toToken.contract, toToken.decimals, amount) // 对询价结果容错 if (!DoDoSwapRst || !DoDoSwapRst.data) { continue } // 构建交易包 const swapRST = DoDoSwapRst.data swapRST.price = MyKit._N(swapRST.resPricePerToToken, 6) swapRST.tx = { gasPrice: 7 * (10 ** 9), gas: '500000', from: PrivateConfig.address, to: swapRST.to, data: swapRST.data } // 间距百分比与预估利润 distance = MyKit._N(100 * ((binancePrice / swapRST.price - 1.001)), 4) profit = MyKit._N(amount * distance / 100 - Config.charge, 4) // debug if (Config.debug) { console.log(`[${time}, ${binancePairSymbol}] D价格: ${swapRST.price},C价格: ${binancePrice},利润:${profit},源:${swapRST.useSource}。`) } // 屏蔽询价源 if (Config.limitSources.indexOf(swapRST.useSource) !== -1 || !swapRST.useSource) { continue } if (swapRST.price && !baseToken.isSwap && profit > Config.profitLimit) { if (distance > 20) { console.log('[利润大于20%]手续费*1.5执行抢单逻辑.') swapRST.tx.gasPrice = parseInt((parseInt(swapRST.tx.gasPrice) * 1.5)) + '' } console.log(`[${time}, ${tokenSymbol}]判定通过, 利润率:${distance}%, 预估利润:${profit}${baseToken.symbol}, 目标利润:${Config.profitLimit}${baseToken.symbol}.\n`) console.log(`DEFI价格: ${swapRST.price}, CEFI价格: ${binancePrice}, 报价源: ${swapRST.useSource}\n\n`) await wallet.transferByTXDoDo(swapRST.tx) } // else if (profit > 0) { // console.log(`[${time}, ${tokenSymbol}]二次判定不通过, 利润率:${distance}%, 预估利润:${profit}${baseToken.symbol}, 目标利润:${profitLimit}${baseToken.symbol}.\n`) // console.log(`DEFI价格: ${swapRST.price}, CEFI价格: ${binancePrice}, 报价源: ${swapRST.useSource}\n\n`) // } } catch (e) { console.log(e) } await MyKit.sleep(Config.delay) } } async function onTick1Inch(toToken) { while (true) { toToken.alive = true // 如果BNB连续变化maxRefreshBNBTimes次,则1INCH或其他交易所可能已经出bug。 if (Config.refreshBNBTimes >= Config.maxRefreshBNBTimes) { console.log(`机器人判定交易所可能出了bug,失败次数:${Config.refreshBNBTimes},为保护BNB,已停止交易。`) break } try { const tokenSymbol = toToken.symbol const baseToken = Config.baseToken if (!baseToken.balance) { await MyKit.sleep(1000) continue } const binancePairSymbol = tokenSymbol + baseToken.symbol const amount = Config.baseTokenAmount < baseToken.balance ? Config.baseTokenAmount : baseToken.balance const OneInchPrice = await OneInch.price(baseToken.contract, baseToken.decimals, amount, toToken.contract) const binancePrice = await bs.price(binancePairSymbol) let distance = MyKit._N(100 * ((binancePrice / OneInchPrice) - 1.001), 4) let profit = MyKit._N(amount * distance / 100 - Config.charge, 4) let time = MyKit.getTimeByMillisecond(new Date().getTime()) // debug if (Config.debug && profit > 0) { console.log(`[${time}, ${binancePairSymbol}] D价格: ${OneInchPrice},C价格: ${binancePrice},利润:${profit}。`) } // 一次判断 if (profit > Config.profitLimit) { // 二次判断,并获取交易tx const swapRST = await OneInch.swap(baseToken.contract, toToken.contract, baseToken.decimals, amount) if (!swapRST) { continue } distance = MyKit._N(100 * ((binancePrice / swapRST.price) - 1.001), 4) profit = MyKit._N(amount * distance / 100 - Config.charge, 4) if (!baseToken.isSwap && profit > Config.profitLimit) { time = MyKit.getTimeByMillisecond(new Date().getTime()) // gas容错 swapRST.tx.gas = parseInt((parseInt(swapRST.tx.gas) * 1.5)) + '' // 如果利润大于5%,手续费*2抢单 if (distance > 20) { console.log('[利润大于20%]手续费*1.5执行抢单逻辑.') swapRST.tx.gasPrice = parseInt((parseInt(swapRST.tx.gasPrice) * 1.5)) + '' } console.log(`[${time}, ${tokenSymbol}]判定通过, 利润率:${distance}%, 预估利润:${profit}${baseToken.symbol}, 目标利润:${Config.profitLimit}${baseToken.symbol}.\n`) console.log(`DEFI价格: ${swapRST.price}, CEFI价格: ${binancePrice}\n\n`) await wallet.transferByTX1Inch(swapRST.tx) } } await MyKit.sleep(5000) } catch (e) { console.log(e) } } } async function flushBalance () { while (true) { try { Config.baseToken.contractModel.methods.balanceOf(PrivateConfig.address).call((err, result) => { if (result) { let balance = MyKit._N(parseFloat(result) / (10 ** Config.baseToken.decimals), 4) const prevBalance = Config.baseToken.balance Config.baseToken.balance = balance if ((prevBalance || prevBalance === 0) && balance !== prevBalance) { console.log(`[${Config.baseToken.symbol}余额变更]${prevBalance}->${balance}, 交易失败(BNB连续减少但BUSD不变化)次数: 0.\n`) Config.refreshBNBTimes = 0 } else if (!prevBalance && prevBalance !== 0) { console.log(`[${Config.baseToken.symbol}余额初始化]${balance}.`) } } }) } catch (e) { console.log(e) } await MyKit.sleep(1000) } } async function flushBNB() { while (true) { try { let balance = await wallet.getBalance() if (balance) { balance = MyKit._N(parseFloat(balance), 4) const prevBalance = Config.bnbBalance if ((prevBalance || prevBalance === 0) && balance !== prevBalance) { console.log(`[BNB余额变更]${prevBalance}->${balance}.`) // 发送过交易的情况下才判定为因交易减少BNB if (balance < prevBalance) { console.log(`\t当前交易失败(BNB连续减少但BUSD不变化)次数:${++Config.refreshBNBTimes}.`) } } else if (!prevBalance && prevBalance !== 0) { console.log(`[BNB余额初始化]${balance}.`) } Config.bnbBalance = balance } } catch (e) { console.log(e) } await MyKit.sleep(1000) } } async function main () { console.log('初始化中...') console.log(`交易所:${Config.exchange}。`) await MyKit.sleep(1000) flushBalance() flushBNB() for (const token of Config.tokenList) { if (Config.exchange === '1inch') { onTick1Inch(token) } else if (Config.exchange === 'dodo') { onTickDoDo(token) } } } main()