diff --git a/Thirdweb.Tests/Thirdweb.Contracts/Thirdweb.Contracts.Tests.cs b/Thirdweb.Tests/Thirdweb.Contracts/Thirdweb.Contracts.Tests.cs index 2e88ce8b..b2c9293a 100644 --- a/Thirdweb.Tests/Thirdweb.Contracts/Thirdweb.Contracts.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Contracts/Thirdweb.Contracts.Tests.cs @@ -102,6 +102,26 @@ public async Task PrepareTest_NoSig() Assert.Contains("Method signature not found in contract ABI.", exception.Message); } + [Fact(Timeout = 120000)] + public async Task ReadTest_TupleIntoArray() + { + var contract = await ThirdwebContract.Create(this.Client, "0xEb4AAB0253a50918a2Cbb7ADBaab78Ad19C07Bb1", 421614); + var result = await contract.Read>("getReserves"); + Assert.NotNull(result); + Assert.NotEmpty(result); + Assert.True(result.Count == 3); + } + + [Fact(Timeout = 120000)] + public async Task ReadTest_TupleIntoList() + { + var contract = await ThirdwebContract.Create(this.Client, "0xEb4AAB0253a50918a2Cbb7ADBaab78Ad19C07Bb1", 421614); + var result = await contract.Read>("getReserves"); + Assert.NotNull(result); + Assert.NotEmpty(result); + Assert.True(result.Count == 3); + } + private sealed class AllowlistProof { public List Proof { get; set; } = new List(); diff --git a/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs b/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs index 3f7a45eb..dfcff81d 100644 --- a/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs +++ b/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs @@ -1,6 +1,9 @@ using System.Numerics; +using Nethereum.ABI.FunctionEncoding; +using Nethereum.ABI.Model; using Nethereum.Contracts; using Nethereum.Hex.HexTypes; +using Newtonsoft.Json; namespace Thirdweb; @@ -119,7 +122,39 @@ public static async Task Read(ThirdwebContract contract, string method, pa var data = function.GetData(parameters); var resultData = await rpc.SendRequestAsync("eth_call", new { to = contract.Address, data }, "latest").ConfigureAwait(false); - return function.DecodeTypeOutput(resultData); + if ((typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(List<>)) || typeof(T).IsArray) + { + var functionAbi = contractRaw.ContractBuilder.ContractABI.FindFunctionABIFromInputData(data); + var decoder = new FunctionCallDecoder(); + var outputList = new FunctionCallDecoder().DecodeDefaultData(resultData.HexToBytes(), functionAbi.OutputParameters); + var resultList = outputList.Select(x => x.Result).ToList(); + + if (typeof(T) == typeof(List)) + { + return (T)(object)resultList; + } + + if (typeof(T) == typeof(object[])) + { + return (T)(object)resultList.ToArray(); + } + + try + { + var json = JsonConvert.SerializeObject(resultList); + return JsonConvert.DeserializeObject(json); + } + catch (Exception) + { + var dict = outputList.ConvertToObjectDictionary(); + var ser = JsonConvert.SerializeObject(dict.First().Value); + return JsonConvert.DeserializeObject(ser); + } + } + else + { + return function.DecodeTypeOutput(resultData); + } } ///