-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHealthFactor.cs
More file actions
79 lines (64 loc) · 2.84 KB
/
Copy pathHealthFactor.cs
File metadata and controls
79 lines (64 loc) · 2.84 KB
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
public class HealthFactor(ITokenPriceProvider priceProvider, AaveDataProvider dataProvider)
{
public async Task<Dictionary<string, decimal>> CalculateHealthFactorAsync(List<BorrowerAccount> borrowersAccs)
{
var borrowersWithHealth = new Dictionary<string, decimal>();
foreach (var account in borrowersAccs)
{
var input = new HealthFactorInput
{
Deposits = new List<TokenPosition>(),
Borrows = new List<TokenPosition>()
};
foreach (var deposit in account.Deposits)
{
if (!decimal.TryParse(deposit.Amount, out var amt) || amt == 0) continue;
var price = await priceProvider.GetPriceInEthAsync(deposit.Asset.Id);
var reserveConfigData = await dataProvider.GetReserveConfigDataAsync(deposit.Asset.Id);
input.Deposits.Add(new TokenPosition
{
AssetAddress = deposit.Asset.Id,
Amount = amt,
PriceInEth = price,
LiquidationThreshold = (decimal)reserveConfigData.LiquidationThreshold / 10000m, // e.g., 8250 → 0.825
IsActive = reserveConfigData.IsActive,
IsFrozen = reserveConfigData.IsFrozen,
UsageAsCollateral = reserveConfigData.UsageAsCollateralEnabled
});
}
foreach (var borrow in account.Borrows)
{
if (!decimal.TryParse(borrow.Amount, out var amt) || amt == 0) continue;
var price = await priceProvider.GetPriceInEthAsync(borrow.Asset.Id);
input.Borrows.Add(new TokenPosition
{
AssetAddress = borrow.Asset.Id,
Amount = amt,
PriceInEth = price,
LiquidationThreshold = 0 // not used for borrows
});
}
var hf = CalculateHealthFactor(input);
borrowersWithHealth.Add(account.Id, hf);
}
return borrowersWithHealth;
}
public decimal CalculateHealthFactor(HealthFactorInput input)
{
decimal totalCollateralETH = input.Deposits
.Where(d => d.IsActive && !d.IsFrozen && d.UsageAsCollateral)
.Sum(d => d.Amount * d.PriceInEth * d.LiquidationThreshold);
decimal totalBorrowedETH = input.Borrows
.Where(b => b.IsActive && !b.IsFrozen)
.Sum(b => b.Amount * b.PriceInEth);
if (totalBorrowedETH == 0)
return decimal.MaxValue; // Fully safe
decimal healthFactor = totalCollateralETH / totalBorrowedETH;
return healthFactor;
}
}
public class HealthFactorInput
{
public List<TokenPosition> Deposits { get; set; } = new();
public List<TokenPosition> Borrows { get; set; } = new();
}