diff --git a/Frontend/AssetStores/PotatoStorage.cs b/Frontend/AssetStores/PotatoStorage.cs index bf72759489a8778fbcaba25e5cca14cc78721a68..d4623cc1a96a81e2a7b3a0a03ff5538b248317dc 100644 --- a/Frontend/AssetStores/PotatoStorage.cs +++ b/Frontend/AssetStores/PotatoStorage.cs @@ -15,28 +15,14 @@ public class PotatoStorage(DbContextOptions<PotatoStorage> options) : DbContext( public async Task<PotatoTransaction> RemovePotatoes(double weight) { - var transactions = Transactions - .OrderBy(p => p.Id) - .AsQueryable(); - - var newTransaction = new PotatoTransaction(); - foreach (var transaction in transactions) + var maxRemovableWeight = SupplyWeight(); + + var removingWeight = Math.Min(maxRemovableWeight, weight); + var newTransaction = new PotatoTransaction { - var newTransactionWeight = newTransaction.Weight + transaction.Weight; - if (newTransactionWeight <= weight) - { - newTransaction.Weight += transaction.Weight; - Transactions.Remove(transaction); - } - else - { - var overshoot = newTransactionWeight - weight; - transaction.Weight -= overshoot; - newTransaction.Weight += transaction.Weight; - Transactions.Update(transaction); - } - } - + Weight = -removingWeight, + }; + await Transactions.AddAsync(newTransaction); await SaveChangesAsync(); return newTransaction; } diff --git a/Frontend/BackgroundServices/RebalanceService.cs b/Frontend/BackgroundServices/RebalanceService.cs new file mode 100644 index 0000000000000000000000000000000000000000..408579cec2c41b244d95cd6c5be83ece1887c1de --- /dev/null +++ b/Frontend/BackgroundServices/RebalanceService.cs @@ -0,0 +1,46 @@ +using System.Diagnostics.Metrics; +using Frontend.Configuration; +using Frontend.Metrics; +using Nethereum.Web3; +using Nethereum.Web3.Accounts; + +namespace Frontend.BackgroundServices; + +public class RebalanceService : BackgroundService +{ + + private readonly ILogger<RebalanceService> _logger; + private readonly TimeSpan _interval = TimeSpan.FromSeconds(10); + private int startUpDelayCycles = 6; + private readonly Rebalancer _rebalancer; + + public RebalanceService( + Rebalancer rebalancer, + Logger<RebalanceService> logger + ) + { + _logger = logger; + _rebalancer = rebalancer; + } + protected async override Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + if (startUpDelayCycles > 0) + { + _logger.LogInformation("RebalanceService is waiting to start. remaining cycles: {startUpDelayCycles}", startUpDelayCycles); + startUpDelayCycles--; + } + else + { + _logger.LogInformation("Rebalancer: EnsureCoinSupplyMatchesRwaSupplyAsync is running at {time}", DateTime.Now); + await _rebalancer.EnsureCoinSupplyMatchesRwaSupplyAsync(); + _logger.LogInformation("Rebalancer: MaintainLiquidReservesAsync is running at {time}", DateTime.Now); + await _rebalancer.MaintainLiquidReservesAsync(); + _logger.LogInformation("Rebalancer: MaintainPoolAsync is running at {time}", DateTime.Now); + await _rebalancer.MaintainPoolAsync(); + } + await Task.Delay(_interval, stoppingToken); + } + } +} \ No newline at end of file diff --git a/Frontend/Marketplaces/PotatoMarketplaceMock.cs b/Frontend/Marketplaces/PotatoMarketplaceMock.cs index 1e638aa81766fe831e0733ab2ece736f7742dfcc..5134cd904daa343a39dc3ac48433f9ae18a29e44 100644 --- a/Frontend/Marketplaces/PotatoMarketplaceMock.cs +++ b/Frontend/Marketplaces/PotatoMarketplaceMock.cs @@ -14,7 +14,7 @@ public class PotatoMarketplaceMock( string wethAddress ) : IPotatoMarketPlace { - private const double potatoKgChfPrice = 2.02; // source: https://www.blw.admin.ch/blw/de/home/markt/marktbeobachtung/kartoffeln.html + private const double potatoKgChfPrice = 0.8; //2.02; // source: https://www.blw.admin.ch/blw/de/home/markt/marktbeobachtung/kartoffeln.html private readonly Account account = marketplaceAccount; private readonly Web3 web3 = marketplaceWeb3Client; @@ -60,7 +60,7 @@ public class PotatoMarketplaceMock( public async Task<bool> Sell(PotatoTransaction transaction, string receiverAddress) { - var amount = (double)await PotatoKgWeiPrice() * transaction.Weight; + var amount = (double)await PotatoKgWeiPrice() * Math.Abs(transaction.Weight); // negative weight means selling var transferHandler = web3.Eth.GetContractTransactionHandler<TransferFunction>(); var transferFunction = new TransferFunction diff --git a/Frontend/Pages/Index.cshtml.cs b/Frontend/Pages/Index.cshtml.cs index 6e2cbe232f5e1841ad1e97986e5bd338f761b2b9..96342b8a0cd05e583941aad82c3ed70d4d3a56d7 100644 --- a/Frontend/Pages/Index.cshtml.cs +++ b/Frontend/Pages/Index.cshtml.cs @@ -1,3 +1,5 @@ +using Frontend.Assets; +using Frontend.AssetStores; using Frontend.Configuration; using Microsoft.AspNetCore.Mvc.RazorPages; using Nethereum.Web3; @@ -12,14 +14,16 @@ public class IndexModel : PageModel private readonly ChainSettings _chainSettings; private readonly Account _account; private readonly Rebalancer _rebalancer; + private readonly PotatoStorage _potatoStorage; - public IndexModel(ILogger<IndexModel> logger, Web3 web3, ChainSettings chainSettings, Account account, Rebalancer rebalancer) + public IndexModel(ILogger<IndexModel> logger, Web3 web3, ChainSettings chainSettings, Account account, Rebalancer rebalancer, PotatoStorage potatoStorage) { _logger = logger; _poolV3Client = new PoolV3Client(web3, chainSettings, account); _chainSettings = chainSettings; _account = account; _rebalancer = rebalancer; + _potatoStorage = potatoStorage; } public void OnGet() @@ -57,5 +61,14 @@ public class IndexModel : PageModel if(Request.Query.ContainsKey("ensureRWA")){ _rebalancer.EnsureCoinSupplyMatchesRwaSupplyAsync().Wait(); } + if(Request.Query.ContainsKey("buyRwa")){ + amount = decimal.Parse(Request.Query["buyRwa"]); + if(amount>0){ + _potatoStorage.AddPotatoes(new PotatoTransaction{Weight=(double)amount}).Wait(); + }else if(amount<0){ + _potatoStorage.RemovePotatoes((double)Math.Abs(amount)).Wait(); + } + } + } } diff --git a/Frontend/PoolV3Client.cs b/Frontend/PoolV3Client.cs index ab1074f41565cf08b29ed81bb0689886b10af7ab..d3b8a840e405d38e82d41c8d4148facadd9eb241 100644 --- a/Frontend/PoolV3Client.cs +++ b/Frontend/PoolV3Client.cs @@ -232,7 +232,7 @@ public class PoolV3Client amount = (double)(liquidity * BigInteger.Pow(2, 96) * (sqrtPriceX96 - desiredSqrtPriceX96)) / (double)(desiredSqrtPriceX96 * sqrtPriceX96); balance = await Token0Client.BalanceOf(_account.Address); } - amount *= 1.0 + (double)await QueryPoolFee() / 1000000.0; // add the pool fees (fee/1000)=% + amount /= 1.0 - (double)await QueryPoolFee() / 1000000.0; // add the pool fees (fee/1000)=% var bigIntAmount = new BigInteger(amount); if (balance < bigIntAmount) diff --git a/Frontend/Program.cs b/Frontend/Program.cs index 7dbadc8118a1b9817cb561d0cc929ddb80bb12cf..524f8ccd92040d221267bbfa8ecc349e14783278 100644 --- a/Frontend/Program.cs +++ b/Frontend/Program.cs @@ -40,6 +40,7 @@ chainConfiguration.Bind(chainSettings); // Add services to the container. builder.Services.AddHostedService<PrometheusService>(); +builder.Services.AddHostedService<RebalanceService>(); builder.Services.AddSingleton<Erc20TokenMetrics>(); builder.Services.AddSingleton<PotatoStorageMetrics>(); builder.Services.AddSingleton<PotatoMarketplaceMetrics>(); diff --git a/grafana/dashboards/totalSupply.json b/grafana/dashboards/totalSupply.json index 8b02d01c0cba88df6609f4de068359392baf2817..efdbdd19f4b45134adfe7f7e1c674f0e3eb29ec5 100644 --- a/grafana/dashboards/totalSupply.json +++ b/grafana/dashboards/totalSupply.json @@ -169,6 +169,7 @@ "mode": "off" } }, + "decimals": 8, "mappings": [], "thresholds": { "mode": "absolute", @@ -567,13 +568,13 @@ }, "id": 11, "options": { - "displayLabels": [ - "percent" - ], "legend": { "displayMode": "list", "placement": "bottom", - "showLegend": true + "showLegend": true, + "values": [ + "percent" + ] }, "pieType": "pie", "reduceOptions": { @@ -687,7 +688,9 @@ "id": 10, "options": { "legend": { - "calcs": [], + "calcs": [ + "last" + ], "displayMode": "list", "placement": "bottom", "showLegend": true @@ -965,6 +968,6 @@ "timezone": "browser", "title": "Total Supply of ROC", "uid": "ce3nybz6khudcd", - "version": 1, + "version": 15, "weekStart": "" } \ No newline at end of file