From 2db0b7f40ec81794488a6fa90cd0bc4567b1f8c4 Mon Sep 17 00:00:00 2001 From: David Hintermann <David.Hintermann@ost.ch> Date: Sat, 30 Nov 2024 13:39:25 +0000 Subject: [PATCH] feat(pool): implement rebalance swap --- Frontend/Functions/LiquidityFunction.cs | 9 ++++ Frontend/PoolV3Client.cs | 56 +++++++++++++++---------- 2 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 Frontend/Functions/LiquidityFunction.cs diff --git a/Frontend/Functions/LiquidityFunction.cs b/Frontend/Functions/LiquidityFunction.cs new file mode 100644 index 0000000..fdc7cb2 --- /dev/null +++ b/Frontend/Functions/LiquidityFunction.cs @@ -0,0 +1,9 @@ +using Nethereum.ABI.FunctionEncoding.Attributes; +using Nethereum.Contracts; + +namespace Frontend.Functions; + +[Function("liquiditry", "uint128")] +public class LiquidityFunction : FunctionMessage{ + +} \ No newline at end of file diff --git a/Frontend/PoolV3Client.cs b/Frontend/PoolV3Client.cs index 5d1cba4..af1e6a5 100644 --- a/Frontend/PoolV3Client.cs +++ b/Frontend/PoolV3Client.cs @@ -93,12 +93,16 @@ public class PoolV3Client } public async Task<decimal> GetPairRatio() + { + return (decimal)SqrtPriceX96ToPrice(await GetSqrtPriceX96()); + } + + public async Task<BigInteger> GetSqrtPriceX96() { var handler = _web3.Eth.GetContractQueryHandler<Slot0Funtion>(); var func = new Slot0Funtion(); var slot0Result = await handler.QueryDeserializingToObjectAsync<Slot0OutputDTO>(func, _pool.Address); - var sqrtPriceX96 = slot0Result.SqrtPriceX96; - return (decimal)SqrtPriceX96ToPrice(sqrtPriceX96); + return slot0Result.SqrtPriceX96; } public double SqrtPriceX96ToPrice(BigInteger sqrtPriceX96) @@ -138,7 +142,7 @@ public class PoolV3Client return _token1Address; } - public async Task<uint> getPoolFeeTier() + public async Task<uint> QueryPoolFee() { if (null == _poolFeeTier) { @@ -150,6 +154,12 @@ public class PoolV3Client return (uint)_poolFeeTier; } + public async Task<BigInteger> QueryLiquidity(){ + var handler = _web3.Eth.GetContractQueryHandler<LiquidityFunction>(); + var func = new LiquidityFunction(); + return await handler.QueryAsync<BigInteger>(_pool.Address, func); + } + /* this function should swap the tokens in the pool @@ -181,7 +191,7 @@ public class PoolV3Client { TokenIn = fromTokenAddress, TokenOut = toTokenAddress, - Fee = await getPoolFeeTier(), + Fee = await QueryPoolFee(), Recipient = _account.Address, AmountIn = Web3.Convert.ToWei(amount), AmountOutMinimum = Web3.Convert.ToWei(amountOutMinimum), // Set your minimum amount out @@ -201,26 +211,30 @@ public class PoolV3Client /// This function should swap the tokens in the pool to create a desired quote /// </summary> /// <param name="desiredQuote">the ration between token1/token0</param> - /// <returns></returns> + /// <returns>Quote after the swap</returns> public async Task<decimal> PerformSwapToCreatDesiredQuote(decimal desiredQuote) { - var currentQuote = await GetPairRatio(); - throw new NotImplementedException(); - var amount = 0.0M; - if (currentQuote < desiredQuote) - { - // we sell some of token1 to buy token0 - amount = (desiredQuote - currentQuote) / desiredQuote; - throw new NotImplementedException(); - await SwapAsync(Token1Address, Token0Address, amount); - } - else - { - amount = 1; - throw new NotImplementedException(); - await SwapAsync(Token1Address, Token0Address, amount); + var sqrtPriceX96= await GetSqrtPriceX96(); + var desiredSqrtPriceX96=PriceToSqrtPriceX96((double)desiredQuote); + string[] tokenAddresses=[Token0Address,Token1Address]; + var fromTokenIndex=0; + var amount = 0.0; + var liquidity=await QueryLiquidity(); + if(desiredSqrtPriceX96>sqrtPriceX96){ // we have to by token0 to increase demand and drive the price up + fromTokenIndex=1; // we want to swap from token1 to token0 + + // Taken from getNextSqrtPriceFromAmount1RoundingDown see https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/SqrtPriceMath.sol + amount=(double)(liquidity*(desiredSqrtPriceX96-sqrtPriceX96)); + }else{ // whe have to sell token0 to lower the price + + // Taken from getNextSqrtPriceFromAmount0ReoundingUp see https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/SqrtPriceMath.sol + amount=(double)(liquidity*(sqrtPriceX96-desiredSqrtPriceX96))/(double)(desiredSqrtPriceX96*sqrtPriceX96); } - throw new NotImplementedException(); + amount *= 1+ (int)await QueryPoolFee()/1000.0; // add the fees + + var receipt=await SwapAsync(tokenAddresses[fromTokenIndex],tokenAddresses[(fromTokenIndex+1)%2],Web3.Convert.FromWei(new BigInteger(amount))); + + return await GetPairRatio(); } } \ No newline at end of file -- GitLab