From b19c967e7ee8849ea3ed0fc8bcab88e41d7009ed Mon Sep 17 00:00:00 2001
From: David Hintermann <David.Hintermann@ost.ch>
Date: Tue, 26 Nov 2024 20:59:08 +0000
Subject: [PATCH] wip: use generated functions from ABI and Bytecode
 https://playground.nethereum.com/

---
 Frontend/Functions/ApproveMaxFunctrion.cs     | 13 +++
 Frontend/Functions/ExactInputFunction.cs      | 21 +++++
 Frontend/Functions/ExactSingleParamBase.cs    | 38 +++++++++
 .../Functions/SwapExactInputSingleFunction.cs | 22 +++---
 Frontend/PoolV3Client.cs                      | 79 ++++++++++++++++---
 Frontend/TokenClient.cs                       | 21 ++++-
 6 files changed, 170 insertions(+), 24 deletions(-)
 create mode 100644 Frontend/Functions/ApproveMaxFunctrion.cs
 create mode 100644 Frontend/Functions/ExactInputFunction.cs
 create mode 100644 Frontend/Functions/ExactSingleParamBase.cs

diff --git a/Frontend/Functions/ApproveMaxFunctrion.cs b/Frontend/Functions/ApproveMaxFunctrion.cs
new file mode 100644
index 0000000..c27a0d6
--- /dev/null
+++ b/Frontend/Functions/ApproveMaxFunctrion.cs
@@ -0,0 +1,13 @@
+
+using System.Numerics;
+using Nethereum.ABI.FunctionEncoding.Attributes;
+using Nethereum.Contracts;
+
+namespace Frontend.Functions; public partial class ApproveMaxFunction : ApproveMaxFunctionBase { }
+
+[Function("approveMax")]
+public class ApproveMaxFunctionBase : FunctionMessage
+{
+    [Parameter("address", "token", 1)]
+    public virtual string Token { get; set; }
+}
\ No newline at end of file
diff --git a/Frontend/Functions/ExactInputFunction.cs b/Frontend/Functions/ExactInputFunction.cs
new file mode 100644
index 0000000..4bcff67
--- /dev/null
+++ b/Frontend/Functions/ExactInputFunction.cs
@@ -0,0 +1,21 @@
+using Nethereum.ABI.FunctionEncoding.Attributes;
+using Nethereum.Contracts;
+using System.Numerics;
+
+namespace Frontend.Functions;
+
+[Function("exactInput")]
+class ExactInputFunction : FunctionMessage
+{
+    [Parameter("uint256", "amountIn", 1)]
+    public BigInteger AmountIn { get; set; }
+
+    [Parameter("uint256", "amountOutMinimum", 2)]
+    public BigInteger AmountOutMinimum { get; set; }
+
+    [Parameter("address[]", "path", 3)]
+    public string[] Path { get; set; }
+
+    [Parameter("address", "to", 4)]
+    public string To { get; set; }
+}
\ No newline at end of file
diff --git a/Frontend/Functions/ExactSingleParamBase.cs b/Frontend/Functions/ExactSingleParamBase.cs
new file mode 100644
index 0000000..ae54ab1
--- /dev/null
+++ b/Frontend/Functions/ExactSingleParamBase.cs
@@ -0,0 +1,38 @@
+using System.Numerics;
+using Nethereum.Hex.HexTypes;
+using Nethereum.ABI.FunctionEncoding.Attributes;
+using Nethereum.Web3;
+using Nethereum.RPC.Eth.DTOs;
+using Nethereum.Contracts.CQS;
+using Nethereum.Contracts;
+
+namespace Frontend.Functions;
+    public class ExactInputSingleParamsBase 
+    {
+        [Parameter("address", "tokenIn", 1)]
+        public virtual string TokenIn { get; set; }
+        [Parameter("address", "tokenOut", 2)]
+        public virtual string TokenOut { get; set; }
+        [Parameter("uint24", "fee", 3)]
+        public virtual uint Fee { get; set; }
+        [Parameter("address", "recipient", 4)]
+        public virtual string Recipient { get; set; }
+        [Parameter("uint256", "amountIn", 5)]
+        public virtual BigInteger AmountIn { get; set; }
+        [Parameter("uint256", "amountOutMinimum", 6)]
+        public virtual BigInteger AmountOutMinimum { get; set; }
+        [Parameter("uint160", "sqrtPriceLimitX96", 7)]
+        public virtual BigInteger SqrtPriceLimitX96 { get; set; }
+    }
+
+    public partial class ExactInputSingleParams : ExactInputSingleParamsBase { }
+
+
+    [Function("exactInputSingle", "uint256")]
+    public class ExactInputSingleFunctionBase : FunctionMessage
+    {
+        [Parameter("tuple", "params", 1)]
+        public virtual ExactInputSingleParams Params { get; set; }
+    }
+
+    public partial class ExactInputSingleFunction : ExactInputSingleFunctionBase { }
\ No newline at end of file
diff --git a/Frontend/Functions/SwapExactInputSingleFunction.cs b/Frontend/Functions/SwapExactInputSingleFunction.cs
index 6629e94..4d03789 100644
--- a/Frontend/Functions/SwapExactInputSingleFunction.cs
+++ b/Frontend/Functions/SwapExactInputSingleFunction.cs
@@ -4,27 +4,29 @@ using Nethereum.Contracts;
 using HexBigInteger = Nethereum.Hex.HexTypes.HexBigInteger;
 
 namespace Frontend.Functions;
-[Function("exactInputSingle", "uint256")]
+[Function("exactInputSingle")]
 public class SwapExactInputSingleFunction : FunctionMessage
 {
-    [Parameter("address", "tokenIn",1)]
+    [Parameter("address", "tokenIn")]
     public string TokenIn { get; set; }
 
-    [Parameter("address", "tokenOut",2)]
+    [Parameter("address", "tokenOut")]
     public string TokenOut { get; set; }
-    
-    [Parameter("uint24", "fee",3)]
+
+    [Parameter("uint24", "fee")]
     public BigInteger Fee { get; set; }
-    
-    [Parameter("address", "recipient",4)]
+
+    [Parameter("address", "recipient")]
     public string Recipient { get; set; }
 
-    [Parameter("uint256", "amountIn",5)]
+    [Parameter("uint256", "amountIn")]
     public BigInteger AmountIn { get; set; }
 
-    [Parameter("uint256", "amountOutMinimum",6)]
+    [Parameter("uint256", "amountOutMinimum")]
     public BigInteger AmountOutMinimum { get; set; }
 
-    [Parameter("uint160", "sqrtPriceLimitX96",7)]
+    [Parameter("uint160", "sqrtPriceLimitX96")]
     public BigInteger SqrtPriceLimitX96 { get; set; }
+        [Parameter("uint256", "deadline")]
+    public BigInteger Deadline { get; set; }
 }
\ No newline at end of file
diff --git a/Frontend/PoolV3Client.cs b/Frontend/PoolV3Client.cs
index 73d6f5a..2aba84b 100644
--- a/Frontend/PoolV3Client.cs
+++ b/Frontend/PoolV3Client.cs
@@ -7,6 +7,9 @@ using Nethereum.Web3;
 using Nethereum.Web3.Accounts;
 
 using Frontend.Configuration;
+using Microsoft.AspNetCore.Components.Forms;
+using System.Reflection.Metadata.Ecma335;
+using Nethereum.Contracts.Extensions;
 
 namespace Frontend;
 
@@ -99,34 +102,86 @@ public class PoolV3Client
     /*
     this function should swap the tokens in the pool
     */
-    public async Task<decimal> SwapAsync(string fromTokenAddress, string toTokenAddress, decimal amount, Account account, decimal amountOutMinimum=0, uint sqrtPriceLimitX96=0)
+    public async Task<decimal> SwapAsync(string fromTokenAddress, string toTokenAddress, decimal amount, Account account, decimal amountOutMinimum = 0, uint sqrtPriceLimitX96 = 0)
     {
-        var swapFunction = new SwapExactInputSingleFunction
+        /* var swapFunction = new SwapExactInputSingleFunction
+         {
+             TokenIn = fromTokenAddress,
+             TokenOut = toTokenAddress,
+             Fee = new BigInteger(await getPoolFeeTier()),
+             Recipient = account.Address,
+             AmountIn = Web3.Convert.ToWei(amount),
+             AmountOutMinimum = Web3.Convert.ToWei(amountOutMinimum), // Set your minimum amount out
+             SqrtPriceLimitX96 = sqrtPriceLimitX96,
+             Deadline = new BigInteger(DateTimeOffset.UtcNow.ToUnixTimeSeconds() + 60 ) // 20 minutes from now
+         };
+
+         swapFunction.Gas= new BigInteger(300000);
+
+         var handler = _web3.Eth.GetContractTransactionHandler<SwapExactInputSingleFunction>();
+
+         var transactionReceipt = await handler.SendRequestAndWaitForReceiptAsync(_chainSettings.Uniswap.SwapRouterV2Address, swapFunction);
+         var swapEvent = transactionReceipt.DecodeAllEvents<SwapEventDTO>();
+         if (swapEvent.Count > 0)
+         {
+             var receivedAmount = swapEvent[0].Event.AmountOut;
+             return Web3.Convert.FromWei(receivedAmount);
+         }
+
+
+         throw new Exception("Swap event not found in transaction receipt");*/
+        var contractHandler = _web3.Eth.GetContractHandler(_chainSettings.Uniswap.SwapRouterV2Address);
+        var exactInputSingleFunction = new ExactInputSingleFunction();
+        exactInputSingleFunction.Params = new ExactInputSingleParams
         {
             TokenIn = fromTokenAddress,
             TokenOut = toTokenAddress,
+            Fee = await getPoolFeeTier(),
+            Recipient = account.Address,
             AmountIn = Web3.Convert.ToWei(amount),
             AmountOutMinimum = Web3.Convert.ToWei(amountOutMinimum), // Set your minimum amount out
-            Recipient = account.Address,
-            Fee = new BigInteger(await getPoolFeeTier()),
-            SqrtPriceLimitX96 = sqrtPriceLimitX96
+            SqrtPriceLimitX96 = sqrtPriceLimitX96,
         };
+        var exactInputSingleFunctionTxnReceipt = await contractHandler.SendRequestAndWaitForReceiptAsync(exactInputSingleFunction);
+         var swapEvent = exactInputSingleFunctionTxnReceipt.DecodeAllEvents<SwapEventDTO>();
+         if (swapEvent.Count > 0)
+         {
+             var receivedAmount = swapEvent[0].Event.AmountOut;
+             return Web3.Convert.FromWei(receivedAmount);
+         }
+         throw new Exception("Swap event not found in transaction receipt");
+    }
+    public async Task<decimal> SwapAsync2(string fromTokenAddress, string toTokenAddress, decimal amount, Account account, decimal amountOutMinimum = 0, uint sqrtPriceLimitX96 = 0)
+    {
+        var contract = _web3.Eth.GetContract(
+            File.ReadAllText(
+                Path.Combine(
+                Directory.GetCurrentDirectory(),
+                    "Configuration",
+                    "Abi",
+                    "swapRouterV2.abi.json"
+                )
+            ),
+            _chainSettings.Uniswap.SwapRouterV2Address
+        );
 
-        swapFunction.Gas= new BigInteger(300000);
+        var exactInputSingle = contract.GetFunction("exactInputSingle");
 
-        var handler = _web3.Eth.GetContractTransactionHandler<SwapExactInputSingleFunction>();
-       
-        var transactionReceipt = await handler.SendRequestAndWaitForReceiptAsync(_chainSettings.Uniswap.SwapRouterV2Address, swapFunction);
-        var swapEvent = transactionReceipt.DecodeAllEvents<SwapEventDTO>();
+        var reciept = await exactInputSingle.SendTransactionAndWaitForReceiptAsync(account.Address, null, fromTokenAddress, toTokenAddress, await getPoolFeeTier(), account.Address, Web3.Convert.ToWei(amount), Web3.Convert.ToWei(amountOutMinimum), sqrtPriceLimitX96);
+        var swapEvent = reciept.DecodeAllEvents<SwapEventDTO>();
         if (swapEvent.Count > 0)
         {
             var receivedAmount = swapEvent[0].Event.AmountOut;
             return Web3.Convert.FromWei(receivedAmount);
         }
-
-
         throw new Exception("Swap event not found in transaction receipt");
     }
 
+        public async Task approveMax(string tokenAddress){
+        var contractHandler = _web3.Eth.GetContractHandler(_chainSettings.Uniswap.SwapRouterV2Address);
+         var approveMaxFunction = new ApproveMaxFunction();
+            approveMaxFunction.Token = tokenAddress;
+            var approveMaxFunctionTxnReceipt = await contractHandler.SendRequestAndWaitForReceiptAsync(approveMaxFunction);
+    }
 
 }
\ No newline at end of file
diff --git a/Frontend/TokenClient.cs b/Frontend/TokenClient.cs
index 809e038..1a79d7b 100644
--- a/Frontend/TokenClient.cs
+++ b/Frontend/TokenClient.cs
@@ -16,7 +16,7 @@ public class TokenClient
     private readonly string _tokenAddress;
     private readonly string _tokenAbi;
 
-    private Contract Contract 
+    private Contract Contract
     {
         get => _web3Client.Eth.GetContract(_tokenAbi, _tokenAddress);
     }
@@ -27,7 +27,8 @@ public class TokenClient
         string tokenAbi,
         string accountPrivateKey,
         int chainId
-    ) {
+    )
+    {
         _tokenAddress = tokenAddress;
         _tokenAbi = tokenAbi;
         _account = new(accountPrivateKey, chainId: chainId);
@@ -69,4 +70,20 @@ public class TokenClient
     {
         return (decimal)(smallUnit / (BigInteger)Math.Pow(10, Decimals));
     }
+
+
+    public async Task<BigInteger> GetAllowanceAsync(string ownerAddress, string spenderAddress)
+    {
+        var allowanceFunction = new AllowanceFunction
+        {
+            Owner = ownerAddress,
+            Spender = spenderAddress
+        };
+
+        var handler = _web3Client.Eth.GetContractQueryHandler<AllowanceFunction>();
+        var allowance = await handler.QueryAsync<BigInteger>(_tokenAddress, allowanceFunction);
+
+        return allowance;
+    }
+
 }
-- 
GitLab