Nethereum / Nethereum.Playground

Compile and run Nethereum snippets on the browser
MIT License
28 stars 17 forks source link

Example: Multicall #39

Open juanfranblanco opened 3 years ago

juanfranblanco commented 3 years ago
using System;
using System.Numerics;
using System.Threading.Tasks;
using Nethereum.Web3;
using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.Contracts;
using System.Collections.Generic;
using Nethereum.Hex.HexConvertors.Extensions;

public class Program
{
    //Example of using multicall https://github.com/makerdao/multicall/blob/master/src/Multicall.sol
    //calling contract deployed at https://etherscan.io/address/0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441#code

    [Function("balanceOf", "uint256")]
    public class BalanceOfFunction : FunctionMessage
    {
        [Parameter("address", "_owner", 1)] public string Owner { get; set; }
    }

    public partial class Call : CallBase { }

    public class CallBase
    {
        [Parameter("address", "target", 1)]
        public virtual string Target { get; set; }
        [Parameter("bytes", "callData", 2)]
        public virtual byte[] CallData { get; set; }
    }

    public partial class AggregateFunction : AggregateFunctionBase { }

    [Function("aggregate", typeof(AggregateOutputDTO))]
    public class AggregateFunctionBase : FunctionMessage
    {
        [Parameter("tuple[]", "calls", 1)]
        public virtual List<Call> Calls { get; set; }
    }

    public partial class AggregateOutputDTO : AggregateOutputDTOBase { }

    [FunctionOutput]
    public class AggregateOutputDTOBase : IFunctionOutputDTO
    {
        [Parameter("uint256", "blockNumber", 1)]
        public virtual BigInteger BlockNumber { get; set; }
        [Parameter("bytes[]", "returnData", 2)]
        public virtual List<byte[]> ReturnData { get; set; }
    }

    [FunctionOutput]
    public class BalanceOfOutputDTO : IFunctionOutputDTO
    {
        [Parameter("uint256", "balance", 1)]
        public BigInteger Balance { get; set; }
    }

    //async Task Main to enable async methods

    private static async Task Main(string[] args)
    {
        //Connecting to Ethereum mainnet using Infura
        var web3 = new Web3("https://mainnet.infura.io/v3/7238211010344719ad14a89db874158c");

        //Setting the owner https://etherscan.io/tokenholdings?a=0x8ee7d9235e01e6b42345120b5d270bdb763624c7
        var balanceOfMessage1 = new BalanceOfFunction() { Owner = "0x8ee7d9235e01e6b42345120b5d270bdb763624c7" };
        var call1 = new Call();
        call1.CallData = balanceOfMessage1.GetCallData();
        call1.Target = "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2";

        var balanceOfMessage2 = new BalanceOfFunction() { Owner = "0x8ee7d9235e01e6b42345120b5d270bdb763624c7" };
        var call2 = new Call();
        call2.CallData = balanceOfMessage2.GetCallData();
        call2.Target = "0xc12d1c73ee7dc3615ba4e37e4abfdbddfa38907e";

        var aggregateFunction = new AggregateFunction();
        aggregateFunction.Calls = new List<Call>();
        aggregateFunction.Calls.Add(call1);
        aggregateFunction.Calls.Add(call2);
        //Creating a new query handler
        var queryHandler = web3.Eth.GetContractQueryHandler<AggregateFunction>();

        var returnCalls = await queryHandler
            .QueryDeserializingToObjectAsync<AggregateOutputDTO>(aggregateFunction, "0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441")
            .ConfigureAwait(false);

        var balance1 = new BalanceOfOutputDTO().DecodeOutput(returnCalls.ReturnData[0].ToHex());
        Console.WriteLine(Web3.Convert.FromWei(balance1.Balance));

        var balance2 = new BalanceOfOutputDTO().DecodeOutput(returnCalls.ReturnData[1].ToHex());
        Console.WriteLine(Web3.Convert.FromWei(balance2.Balance, 8));
    }
}
Eternity714 commented 2 years ago

thanks for share

juanfranblanco commented 2 years ago

@Eternity714 Multicall is part of Nethereum now, hence this example is not in the playground, but another.