import ipc from 'node-ipc' ; import Web3Utils from 'web3-utils' ; import winston from 'winston' ; import { providerFor } from '@goldenagellc/web3-blocks' ; import SlackHook from './logging/SlackHook' ; import cTokens from './contracts/CToken' ; import comptroller from './contracts/Comptroller' ; import openOraclePriceData from './contracts/OpenOraclePriceData' ; import uniswapAnchoredView from './contracts/UniswapAnchoredView' ; import PriceLedger from './PriceLedger' ; import StatefulBorrowers from './StatefulBorrowers' ; import StatefulComptroller from './StatefulComptroller' ; import StatefulPricesOnChain from './StatefulPricesOnChain' ; import StatefulPricesCoinbase from './StatefulPricesCoinbase' ; import getBorrowers from './CompoundAPI' ; require ( 'dotenv-safe' ) . config ( ) ; const provider = providerFor ( 'mainnet' , { type : 'IPC' , envKeyPath : 'PROVIDER_IPC_PATH' , } ) ; winston . configure ( { format : winston . format . combine ( winston . format . splat ( ) , winston . format . simple ( ) ) , transports : [ new winston . transports . Console ( { handleExceptions : true } ) , new winston . transports . File ( { level : 'debug' , filename : 'delegator.log' , maxsize : 100000 , } ) , new SlackHook ( process . env . SLACK_WEBHOOK ! , { level : 'info' } ) , ] , exitOnError : false , } ) ; const priceLedger = new PriceLedger ( ) ; const statefulBorrowers = new StatefulBorrowers ( provider , cTokens ) ; const statefulComptroller = new StatefulComptroller ( provider , comptroller ) ; const statefulPricesOnChain = new StatefulPricesOnChain ( provider , priceLedger , openOraclePriceData , uniswapAnchoredView ) ; const statefulPricesCoinbase = new StatefulPricesCoinbase ( priceLedger , process . env . COINBASE_ENDPOINT ! , process . env . CB_ACCESS_KEY ! , process . env . CB_ACCESS_SECRET ! , process . env . CB_ACCESS_PASSPHRASE ! ) ; let candidatesObj = { previous : < string [ ] > [ ] , } ; async function scan ( ipcTxManagers ) { const candidates = await statefulBorrowers . scan ( statefulComptroller , priceLedger ) ; const candidatesSet = new Set < string > ( ) ; candidates . forEach ( ( candidate ) => { candidatesSet . add ( candidate . address ) ; ipcTxManagers . forEach ( ( i ) => i . emit ( 'liquidation-candidate-add' , candidate ) ) ; } ) ; candidatesObj . previous . forEach ( ( address ) => { if ( candidatesSet . has ( address ) ) return ; ipcTxManagers . forEach ( ( i ) => i . emit ( 'liquidation-candidate-remove' , address ) ) ; } ) ; candidatesObj . previous = Array . from ( candidatesSet ) ; } async function start ( ipcTxManagers ) { await statefulBorrowers . init ( ) ; await statefulComptroller . init ( ) ; await statefulPricesOnChain . init ( ) ; await statefulPricesCoinbase . init ( 2000 ) ; winston . log ( 'info' , 'Searching for borrowers using the Compound API...' ) ; const borrowers = await getBorrowers ( '1' ) ; winston . log ( 'info' , `Found ${ borrowers . length } borrowers using the Compound API` ) ; const borrowersPushStart = Date . now ( ) ; await statefulBorrowers . push ( borrowers . map ( ( x ) => Web3Utils . toChecksumAddress ( x ) ) ) ; winston . log ( 'info' , `Fetched all borrower data in ${ Date . now ( ) - borrowersPushStart } ms` ) ; statefulPricesCoinbase . register ( ( ) => scan ( ipcTxManagers ) ) ; provider . eth . subscribe ( 'newBlockHeaders' ) . on ( 'data' , ( _block ) => setTimeout ( ( ) => scan ( ipcTxManagers ) , 500 ) ) ; setInterval ( ( ) => ipcTxManagers . forEach ( ( i ) => i . emit ( 'keepalive' , '' ) ) , 60 * 5 * 1000 ) ; } function stop ( ) { statefulPricesCoinbase . stop ( ) ; provider . eth . clearSubscriptions ( ) ; provider . eth . currentProvider . connection . destroy ( ) ; } ipc . config . appspace = 'newbedford.' ; ipc . config . id = 'delegator' ; ipc . config . silent = true ; ipc . connectTo ( 'txmanager-mev' , '/tmp/newbedford.txmanager-mev' , ( ) => { ipc . of [ 'txmanager-mev' ] . on ( 'connect' , ( ) => { console . log ( "Connected to TxManagerMEV's IPC" ) ; start ( [ ipc . of [ 'txmanager-mev' ] ] ) ; } ) ; } ) ; process . on ( 'SIGINT' , ( ) => { console . log ( '\nCaught interrupt signal' ) ; ipc . disconnect ( 'txmanager-mev' ) ; stop ( ) ; console . log ( 'Exited cleanly' ) ; process . exit ( ) ; } ) ;