Skip to content

Commit

Permalink
Merge pull request #54 from cheng521521/main
Browse files Browse the repository at this point in the history
feat: add defi monitor
  • Loading branch information
yanyanho authored Nov 6, 2023
2 parents ce00da4 + 6d11a93 commit 15a89a1
Show file tree
Hide file tree
Showing 12 changed files with 951 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;

import java.util.Properties;

@EnableJpaAuditing
@SpringBootApplication
@EnableAspectJAutoProxy
@EnableScheduling
public class OfficialSiteApplication {

public static void main(String[] args) {
Expand Down
140 changes: 101 additions & 39 deletions src/main/java/com/dl/officialsite/aave/AaveService.java
Original file line number Diff line number Diff line change
@@ -1,72 +1,134 @@
package com.dl.officialsite.aave;

import com.dl.officialsite.contract.ilendingpool.ILendingPool;
import com.dl.officialsite.contract.ilendingpooladdressesprovider.ILendingPoolAddressesProvider;
import static org.web3j.tx.gas.DefaultGasProvider.GAS_LIMIT;
import static org.web3j.tx.gas.DefaultGasProvider.GAS_PRICE;

import com.dl.officialsite.contract.iaaveoracle.IAaveOracle;
import com.dl.officialsite.contract.ipool.IPool;
import com.dl.officialsite.contract.ipooladdressesprovider.IPoolAddressesProvider;
import com.dl.officialsite.member.MemberController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthGetBalance;
import org.web3j.protocol.http.HttpService;
import org.web3j.tuples.generated.Tuple6;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import static org.web3j.tx.gas.DefaultGasProvider.GAS_LIMIT;
import static org.web3j.tx.gas.DefaultGasProvider.GAS_PRICE;

@Service
@Slf4j
public class AaveService {
public static ContractGasProvider GAS_PROVIDER = new StaticGasProvider(GAS_PRICE, GAS_LIMIT);
public static final Logger logger = LoggerFactory.getLogger(AaveService.class);

BigInteger e16 = new BigInteger("10000000000000000");
BigInteger e8 = new BigInteger("100000000");
BigInteger e23 = new BigInteger("100000000000000000000000");


@Autowired
Web3j web3j;

@Autowired
Credentials credentials;

@Autowired
IPoolAddressesProvider poolAddressesProvider;

// 1 完成自己地址的健康系数,总借款,总存款, LTV数据获取
// 2 完成USDC、DAI、USDT,LUSD 借贷利率的获取
// 3 完成ETH 、BTC借贷利率 以及价格获取。
// 4 用DL的官网邮箱 发送team0 成员,这些数据。 每天发送一次。
// 5 半小时调一次接口 ,如果HF< 1.2 。立即发送邮件告警;

public float getHF(String whale) throws Exception {

// EthGetBalance ethGetBalance = web3j.ethGetBalance(fish, DefaultBlockParameterName.LATEST).send();
// logger.info("balance: " + ethGetBalance.getBalance());
// polygonv3
String lendingPoolAddressProviderV3 = "0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb";
IPoolAddressesProvider addrProV3 = IPoolAddressesProvider.load(lendingPoolAddressProviderV3, web3j, credentials, GAS_PROVIDER);

String s = addrProV3.getPool().send();
logger.info("v3 pool: " + s);
IPool lendingPool = IPool.load(s, web3j, credentials, GAS_PROVIDER);
BigInteger hf = lendingPool.getUserAccountData(whale).send().getValue6();

BigInteger e16 = new BigInteger("10000000000000000");
public HealthInfo getHealthInfo(String address) throws Exception {
String poolAddress = poolAddressesProvider.getPool().send();
log.info("poolAddress is : " + poolAddress);
IPool pool = IPool.load(poolAddress, web3j, credentials, GAS_PROVIDER);
Tuple6<BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger> info = pool.getUserAccountData(
address).send();
BigInteger totalCollateralBase = info.component1();
BigInteger totalDebtBase = info.component2();
BigInteger ltv = info.component5();
BigInteger healthFactor = info.component6();
HealthInfo healthInfo = HealthInfo.builder()
.healthFactor(healthFactor)
.totalBorrows(totalDebtBase.toString())
.totalCollateralETH(totalCollateralBase.toString())
.totalLiquidity(ltv.toString())
.build();
return healthInfo;
}

logger.info("*******: " + hf.divide(e16).floatValue()/100);
public TokenInfoList getVar() throws Exception {

// get Interest
String usdc= "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
String usdt = "0xc2132D05D31c914a87C6611C10748AEb04B58e8F";
String dai= "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063";
String eth = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619";
String btc = "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6";

String poolAddress = poolAddressesProvider.getPool().send();
log.info("poolAddress is : " + poolAddress);
IPool pool = IPool.load(poolAddress, web3j, credentials, GAS_PROVIDER);
IPool.ReserveData reserveData = pool.getReserveData(usdc).send();

TokenInfo USDC = TokenInfo.builder()
.borrow(getBorrow("usdc", reserveData))
.deposit(getDeposit("usdc", reserveData))
.build();

reserveData = pool.getReserveData(dai).send();
TokenInfo DAI = TokenInfo.builder()
.borrow(getBorrow("dai", reserveData))
.deposit(getDeposit("dai", reserveData))
.build();

reserveData = pool.getReserveData(usdt).send();
TokenInfo USDT = TokenInfo.builder()
.borrow(getBorrow("usdt", reserveData))
.deposit(getDeposit("usdt", reserveData))
.build();

reserveData = pool.getReserveData(eth).send();
TokenInfo ETH = TokenInfo.builder()
.borrow(getBorrow("eth", reserveData))
.deposit(getDeposit("eth", reserveData))
.price(String.valueOf(getTokenPrice(eth)))
.build();

reserveData = pool.getReserveData(btc).send();
TokenInfo BTC = TokenInfo.builder()
.borrow(getBorrow("btc", reserveData))
.deposit(getDeposit("btc", reserveData))
.price(String.valueOf(getTokenPrice(btc)))
.build();

TokenInfoList tokenInfoList = new TokenInfoList();
tokenInfoList.setUSDC(USDC);
tokenInfoList.setDAI(DAI);
tokenInfoList.setUSDT(USDT);
tokenInfoList.setETH(ETH);
tokenInfoList.setBTC(BTC);
return tokenInfoList;
}

return hf.divide(e16).floatValue()/100;
private String getBorrow(String tokenName, IPool.ReserveData reserveData) {
log.info("{} variable borrow interest:" + reserveData.currentVariableBorrowRate.divide(e23).floatValue()/100, tokenName);
return reserveData.currentVariableBorrowRate.divide(e23).floatValue()/100 + "%";
}

private String getDeposit(String tokenName, IPool.ReserveData reserveData) {
log.info("{} variable deposit interest:" + reserveData.currentVariableBorrowRate.divide(e23).floatValue()/100, tokenName);
return reserveData.currentLiquidityRate.divide(e23).floatValue()/100 + "%";
}

//udsc , usdc , DAI borrow and supply interest.
public List<Float> getInterestOfSupplyAndBorrow(String address) {
// 返回 USDC
return new ArrayList<>() ;
private float getTokenPrice(String tokenAddress) throws Exception {
String iAaveOracleAddress = "0xb023e699F5a33916Ea823A16485e259257cA8Bd1";
IAaveOracle iAaveOracle = IAaveOracle.load(iAaveOracleAddress, web3j, credentials, GAS_PROVIDER);
float tokenPrice =
iAaveOracle.getAssetPrice(tokenAddress).send().divide(e8).floatValue();
return tokenPrice;
}


}
40 changes: 40 additions & 0 deletions src/main/java/com/dl/officialsite/aave/Compent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.dl.officialsite.aave;

import static org.web3j.tx.gas.DefaultGasProvider.GAS_LIMIT;
import static org.web3j.tx.gas.DefaultGasProvider.GAS_PRICE;

import com.dl.officialsite.contract.ipooladdressesprovider.IPoolAddressesProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;

/**
* @ClassName Compent
* @Author jackchen
* @Date 2023/11/5 14:30
* @Description TODO
**/
@Component
public class Compent {

public static ContractGasProvider GAS_PROVIDER = new StaticGasProvider(GAS_PRICE, GAS_LIMIT);

@Autowired
Web3j web3j;

@Autowired
Credentials credentials;

@Bean
IPoolAddressesProvider IPoolAddressesProvider() {
String poolAddressesProviderAddress = "0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb";
IPoolAddressesProvider poolAddressesProvider = IPoolAddressesProvider.load(poolAddressesProviderAddress,
web3j, credentials, GAS_PROVIDER);
return poolAddressesProvider;
}

}
28 changes: 28 additions & 0 deletions src/main/java/com/dl/officialsite/aave/HealthInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.dl.officialsite.aave;

import java.math.BigInteger;
import lombok.Builder;
import lombok.Data;

/**
* @ClassName HealthInfo
* @Author jackchen
* @Date 2023/11/2 20:29
* @Description HealthInfo
**/
@Data
@Builder
public class HealthInfo {

//健康系数
private BigInteger healthFactor;

//总借款
private String totalBorrows;

//总存款
private String totalCollateralETH;

//LTV数据获取
private String totalLiquidity;
}
88 changes: 88 additions & 0 deletions src/main/java/com/dl/officialsite/aave/Schedule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.dl.officialsite.aave;

import com.dl.officialsite.mail.EmailService;
import com.dl.officialsite.member.Member;
import com.dl.officialsite.team.TeamService;
import com.dl.officialsite.team.vo.TeamQueryVo;
import com.dl.officialsite.team.vo.TeamsMembersVo;
import java.math.BigInteger;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
* @ClassName Scheaml
* @Author jackchen
* @Date 2023/11/5 14:53
* @Description Schedule
**/
@Component
@Slf4j
public class Schedule {

@Autowired
private AaveService aaveService;

@Autowired
private EmailService emailService;

@Autowired
private TeamService teamService;

BigInteger e16 = new BigInteger("10000000000000000");

/**
* 监控价格一天发送一次
*/
@Scheduled(cron = "0 0 12 * * ?")
public void monitorPrice() throws Exception {
log.info("monitorPrice start");
//查找team0 memeber获取地址
TeamQueryVo teamQueryVo = new TeamQueryVo();
teamQueryVo.setTeamName("Dapp-Learning DAO core founders");
List<TeamsMembersVo> teamAndMembers = teamService.getTeamAndMembers(teamQueryVo);
if (teamAndMembers.size() != 0) {
for (TeamsMembersVo teamAndMember : teamAndMembers) {
for (Member member : teamAndMember.getMembers()) {
String email = member.getEmail();
HealthInfo healthInfo = aaveService.getHealthInfo(member.getAddress());
TokenInfoList tokenInfoList = aaveService.getVar();
emailService.sendMail(email, "Dapp Defi Monitor", tokenInfoList.toString() + "\n" + healthInfo.toString());
}
}
}
}

/**
* 监控健康系数,如果小于1.2,立即发送邮件
*/
@Scheduled(cron = "0 0/30 * * * ? ")
public void monitorHealth() {
try {
log.info("monitorHealth start");
//查找team0 memeber获取地址
TeamQueryVo teamQueryVo = new TeamQueryVo();
teamQueryVo.setTeamName("Dapp-Learning DAO core founders");
List<TeamsMembersVo> teamAndMembers = teamService.getTeamAndMembers(teamQueryVo);
if (teamAndMembers.size() != 0) {
for (TeamsMembersVo teamAndMember : teamAndMembers) {
for (Member member : teamAndMember.getMembers()) {
String email = member.getEmail();
HealthInfo healthInfo = aaveService.getHealthInfo(member.getAddress());
float health = healthInfo.getHealthFactor().divide(e16).floatValue() / 100;
log.info("health is : " + health);
if (health < 1.2) {
emailService.sendMail(email, "Dapp Defi Monitor", healthInfo.toString());
}
emailService.sendMail(email, "Dapp Defi Monitor HealthInfo < 1.2",
"health is : " + health);
}
}
}
} catch (Exception e) {
log.error("monitorHealth error", e);
}
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/dl/officialsite/aave/TokenInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.dl.officialsite.aave;

import lombok.Builder;
import lombok.Data;

/**
* @ClassName TokenInfo
* @Author jackchen
* @Date 2023/11/5 12:32
* @Description TokenInfo
**/
@Data
@Builder
public class TokenInfo {

private String deposit;

private String borrow;

private String price;
}
Loading

0 comments on commit 15a89a1

Please sign in to comment.