diff --git a/src/Net.Cache.DynamoDb.ERC20/Net.Cache.DynamoDb.ERC20.csproj b/src/Net.Cache.DynamoDb.ERC20/Net.Cache.DynamoDb.ERC20.csproj index 9130c80..00a1827 100644 --- a/src/Net.Cache.DynamoDb.ERC20/Net.Cache.DynamoDb.ERC20.csproj +++ b/src/Net.Cache.DynamoDb.ERC20/Net.Cache.DynamoDb.ERC20.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Net.Cache.DynamoDb.ERC20/RPC/ERC20Service.cs b/src/Net.Cache.DynamoDb.ERC20/RPC/ERC20Service.cs index 10dd35d..3b81356 100644 --- a/src/Net.Cache.DynamoDb.ERC20/RPC/ERC20Service.cs +++ b/src/Net.Cache.DynamoDb.ERC20/RPC/ERC20Service.cs @@ -9,6 +9,7 @@ using Net.Cache.DynamoDb.ERC20.Rpc.Extensions; using Net.Cache.DynamoDb.ERC20.Rpc.Models; using Net.Cache.DynamoDb.ERC20.Rpc.Validators; +using Nethereum.Contracts.QueryHandlers.MultiCall; using Nethereum.Contracts.Standards.ERC20.ContractDefinition; namespace Net.Cache.DynamoDb.ERC20.Rpc @@ -37,23 +38,24 @@ public async Task GetErc20TokenAsync(EthereumAddress token) { if (token == null) throw new ArgumentNullException(nameof(token)); - var multiCallFunction = new MultiCallFunction( - calls: new[] + var multiCallFunction = new Aggregate3Function + { + Calls = new List { - new MultiCall(to: token, data: new NameFunction().GetCallData()), - new MultiCall(to: token, data: new SymbolFunction().GetCallData()), - new MultiCall(to: token, data: new DecimalsFunction().GetCallData()), - new MultiCall(to: token, data: new TotalSupplyFunction().GetCallData()) + new Call3 { Target = token, CallData = new NameFunction().GetCallData() }, + new Call3 { Target = token, CallData = new SymbolFunction().GetCallData() }, + new Call3 { Target = token, CallData = new DecimalsFunction().GetCallData() }, + new Call3 { Target = token, CallData = new TotalSupplyFunction().GetCallData() } } - ); - - var handler = _web3.Eth.GetContractQueryHandler(); + }; + + var handler = _web3.Eth.GetContractQueryHandler(); var response = await handler - .QueryAsync>(_multiCall, multiCallFunction) + .QueryAsync(_multiCall, multiCallFunction) .ConfigureAwait(false); - var responseValidator = new MultiCallResponseValidator(multiCallFunction.Calls.Length); + var responseValidator = new MultiCallResponseValidator(multiCallFunction.Calls.Count); var validation = await responseValidator - .ValidateAsync(response) + .ValidateAsync(response.ReturnData.Select(x => x.ReturnData).ToArray()) .ConfigureAwait(false); if (!validation.IsValid) { @@ -61,10 +63,10 @@ public async Task GetErc20TokenAsync(EthereumAddress token) throw new Erc20QueryException(token, error); } - var name = response[0].Decode().Name; - var symbol = response[1].Decode().Symbol; - var decimals = response[2].Decode().Decimals; - var supply = response[3].Decode().TotalSupply; + var name = response.ReturnData[0].ReturnData.Decode().Name; + var symbol = response.ReturnData[1].ReturnData.Decode().Symbol; + var decimals = response.ReturnData[2].ReturnData.Decode().Decimals; + var supply = response.ReturnData[3].ReturnData.Decode().TotalSupply; var tokenResult = new Erc20TokenData(token, name, symbol, decimals, supply); var tokenValidator = new Erc20TokenValidator(); diff --git a/src/Net.Cache.DynamoDb.ERC20/RPC/Models/MultiCall.cs b/src/Net.Cache.DynamoDb.ERC20/RPC/Models/MultiCall.cs deleted file mode 100644 index 308fdb8..0000000 --- a/src/Net.Cache.DynamoDb.ERC20/RPC/Models/MultiCall.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Net.Web3.EthereumWallet; -using Nethereum.ABI.FunctionEncoding.Attributes; - -namespace Net.Cache.DynamoDb.ERC20.Rpc.Models -{ - /// - /// Represents a single call item for the Multicall contract. - /// - public class MultiCall - { - /// - /// Gets the address of the contract to call. - /// - [Parameter("address", "to", order: 1)] - public string To { get; } - - /// - /// Gets the encoded call data. - /// - [Parameter("bytes", "data", order: 2)] - public byte[] Data { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The contract address to call. - /// The encoded function data. - public MultiCall(EthereumAddress to, byte[] data) - { - To = to; - Data = data; - } - } -} diff --git a/src/Net.Cache.DynamoDb.ERC20/RPC/Models/MultiCallFunction.cs b/src/Net.Cache.DynamoDb.ERC20/RPC/Models/MultiCallFunction.cs deleted file mode 100644 index c3bee62..0000000 --- a/src/Net.Cache.DynamoDb.ERC20/RPC/Models/MultiCallFunction.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Linq; -using Nethereum.Contracts; -using System.Collections.Generic; -using Nethereum.ABI.FunctionEncoding.Attributes; - -namespace Net.Cache.DynamoDb.ERC20.Rpc.Models -{ - /// - /// Represents a multicall function message that aggregates multiple calls. - /// - [Function("multicall", "bytes[]")] - public class MultiCallFunction : FunctionMessage - { - /// - /// Gets the collection of calls to execute. - /// - [Parameter("tuple[]", "calls", order: 1)] - public MultiCall[] Calls { get; } - - /// - /// Initializes a new instance of the class with the specified calls. - /// - /// The calls to execute within the multicall. - public MultiCallFunction(IEnumerable calls) - { - Calls = calls.ToArray(); - } - - /// - /// Initializes a new instance of the class with no calls. - /// - public MultiCallFunction() : this(Enumerable.Empty()) { } - } -} diff --git a/tests/Net.Cache.DynamoDb.ERC20.Tests/Rpc/Erc20ServiceTests.cs b/tests/Net.Cache.DynamoDb.ERC20.Tests/Rpc/Erc20ServiceTests.cs index f4f8dff..ae11626 100644 --- a/tests/Net.Cache.DynamoDb.ERC20.Tests/Rpc/Erc20ServiceTests.cs +++ b/tests/Net.Cache.DynamoDb.ERC20.Tests/Rpc/Erc20ServiceTests.cs @@ -8,9 +8,9 @@ using Net.Web3.EthereumWallet; using Nethereum.Contracts.Services; using Net.Cache.DynamoDb.ERC20.Rpc; -using Net.Cache.DynamoDb.ERC20.Rpc.Models; using Nethereum.Contracts.ContractHandlers; using Net.Cache.DynamoDb.ERC20.Rpc.Exceptions; +using Nethereum.Contracts.QueryHandlers.MultiCall; namespace Net.Cache.DynamoDb.ERC20.Tests.Rpc; @@ -39,7 +39,7 @@ public class GetErc20TokenAsync [Fact] public async Task WhenTokenNull_ShouldThrow() { - var handler = new Mock>(); + var handler = new Mock>(); var service = CreateService(handler.Object); var act = async () => await service.GetErc20TokenAsync(null!); await act.Should().ThrowAsync(); @@ -49,9 +49,9 @@ public async Task WhenTokenNull_ShouldThrow() public async Task WhenResponseValid_ShouldReturnToken() { var response = BuildResponse("Token", "TKN", 18, new BigInteger(1000)); - var handlerMock = new Mock>(); + var handlerMock = new Mock>(); handlerMock - .Setup(h => h.QueryAsync>(It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(h => h.QueryAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(response); var service = CreateService(handlerMock.Object); @@ -68,9 +68,9 @@ public async Task WhenResponseValid_ShouldReturnToken() public async Task WhenTokenInvalid_ShouldThrow() { var response = BuildResponse(string.Empty, "TKN", 18, new BigInteger(1000)); - var handlerMock = new Mock>(); + var handlerMock = new Mock>(); handlerMock - .Setup(h => h.QueryAsync>(It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(h => h.QueryAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(response); var service = CreateService(handlerMock.Object); @@ -81,24 +81,26 @@ await act.Should().ThrowAsync() } } - private static Erc20Service CreateService(IContractQueryHandler handler) + private static Erc20Service CreateService(IContractQueryHandler handler) { var web3Mock = new Mock(); var ethMock = new Mock(); - ethMock.Setup(e => e.GetContractQueryHandler()).Returns(handler); + ethMock.Setup(e => e.GetContractQueryHandler()).Returns(handler); web3Mock.SetupGet(w => w.Eth).Returns(ethMock.Object); return new Erc20Service(web3Mock.Object, EthereumAddress.ZeroAddress); } - private static List BuildResponse(string name, string symbol, byte decimals, BigInteger supply) + private static Aggregate3OutputDTO BuildResponse(string name, string symbol, byte decimals, BigInteger supply) { var abiEncode = new ABIEncode(); - return - [ - abiEncode.GetABIEncoded(new ABIValue("string", name)), - abiEncode.GetABIEncoded(new ABIValue("string", symbol)), - abiEncode.GetABIEncoded(new ABIValue("uint8", decimals)), - abiEncode.GetABIEncoded(new ABIValue("uint256", supply)) - ]; + return new Aggregate3OutputDTO + { + ReturnData = [ + new Result { ReturnData = abiEncode.GetABIEncoded(new ABIValue("string", name)) }, + new Result { ReturnData = abiEncode.GetABIEncoded(new ABIValue("string", symbol)) }, + new Result { ReturnData = abiEncode.GetABIEncoded(new ABIValue("uint8", decimals)) }, + new Result { ReturnData = abiEncode.GetABIEncoded(new ABIValue("uint256", supply)) } + ] + }; } }