Nethereum / Nethereum.Playground

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

Example: Multicall using TokenLists (Uniswap default lists) #40

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;
using System.Collections;
using Newtonsoft.Json;
using System.Linq;

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

    public class Version
    {
        public int Major { get; set; }
        public int Minor { get; set; }
        public int Patch { get; set; }
    }

    public class Token
    {
        public int ChainId { get; set; }
        public string Address { get; set; }
        public string Symbol { get; set; }
        public string Name { get; set; }
        public int Decimals { get; set; }
    }

    public class Root
    {
        public string Name { get; set; }
        public DateTime Timestamp { get; set; }
        public List<string> Keywords { get; set; }
        public Version Version { get; set; }
        public List<Token> Tokens { get; set; }
        public string LogoURI { get; set; }
    }

    [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; }
    }

    //https://tokenlists.org/
    public static string TokensJSON = @"{""name"":""Uniswap Default List"",""timestamp"":""2021-01-21T23:57:10.982Z"",""version"":{""major"":2,""minor"":0,""patch"":0},""tags"":{},""logoURI"":""ipfs://QmNa8mQkrNKp1WEEeGjFezDmDeodkWRevGFN8JCV7b4Xir"",""keywords"":[""uniswap"",""default""],""tokens"":[{""chainId"":1,""address"":""0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9"",""name"":""Aave"",""symbol"":""AAVE"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110""},{""chainId"":1,""address"":""0xfF20817765cB7f73d4bde2e66e067E58D11095C2"",""name"":""Amp"",""symbol"":""AMP"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397""},{""name"":""Aragon Network Token"",""address"":""0x960b236A07cf122663c4303350609A66A7B288C0"",""symbol"":""ANT"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x960b236A07cf122663c4303350609A66A7B288C0/logo.png""},{""name"":""Balancer"",""address"":""0xba100000625a3754423978a60c9317c58a424e3D"",""symbol"":""BAL"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png""},{""chainId"":1,""address"":""0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55"",""name"":""Band Protocol"",""symbol"":""BAND"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326""},{""name"":""Bancor Network Token"",""address"":""0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C"",""symbol"":""BNT"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png""},{""name"":""Compound"",""address"":""0xc00e94Cb662C3520282E6f5717214004A7f26888"",""symbol"":""COMP"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png""},{""name"":""Curve DAO Token"",""address"":""0xD533a949740bb3306d119CC777fa900bA034cd52"",""symbol"":""CRV"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png""},{""chainId"":1,""address"":""0x41e5560054824eA6B0732E656E3Ad64E20e94E45"",""name"":""Civic"",""symbol"":""CVC"",""decimals"":8,""logoURI"":""https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556""},{""name"":""Dai Stablecoin"",""address"":""0x6B175474E89094C44Da98b954EedeAC495271d0F"",""symbol"":""DAI"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png""},{""chainId"":1,""address"":""0x0AbdAce70D3790235af448C88547603b945604ea"",""name"":""district0x"",""symbol"":""DNT"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762""},{""name"":""Gnosis Token"",""address"":""0x6810e776880C02933D47DB1b9fc05908e5386b96"",""symbol"":""GNO"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png""},{""chainId"":1,""address"":""0xc944E90C64B2c07662A292be6244BDf05Cda44a7"",""name"":""The Graph"",""symbol"":""GRT"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566""},{""chainId"":1,""address"":""0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC"",""name"":""Keep Network"",""symbol"":""KEEP"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336""},{""name"":""Kyber Network Crystal"",""address"":""0xdd974D5C2e2928deA5F71b9825b8b646686BD200"",""symbol"":""KNC"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png""},{""name"":""ChainLink Token"",""address"":""0x514910771AF9Ca656af840dff83E8264EcF986CA"",""symbol"":""LINK"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png""},{""name"":""Loom Network"",""address"":""0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0"",""symbol"":""LOOM"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png""},{""name"":""LoopringCoin V2"",""address"":""0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD"",""symbol"":""LRC"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png""},{""chainId"":1,""address"":""0x0F5D2fB29fb7d3CFeE444a200298f468908cC942"",""name"":""Decentraland"",""symbol"":""MANA"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745""},{""name"":""Maker"",""address"":""0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2"",""symbol"":""MKR"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png""},{""chainId"":1,""address"":""0xec67005c4E498Ec7f55E092bd1d35cbC47C91892"",""name"":""Melon"",""symbol"":""MLN"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295""},{""name"":""Numeraire"",""address"":""0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671"",""symbol"":""NMR"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png""},{""chainId"":1,""address"":""0x4fE83213D56308330EC302a8BD641f1d0113A4Cc"",""name"":""NuCypher"",""symbol"":""NU"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/3318/thumb/photo1198982838879365035.jpg?1547037916""},{""name"":""Orchid"",""address"":""0x4575f41308EC1483f3d399aa9a2826d74Da13Deb"",""symbol"":""OXT"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png""},{""name"":""Republic Token"",""address"":""0x408e41876cCCDC0F92210600ef50372656052a38"",""symbol"":""REN"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png""},{""name"":""Reputation Augur v1"",""address"":""0x1985365e9f78359a9B6AD760e32412f4a445E862"",""symbol"":""REP"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1985365e9f78359a9B6AD760e32412f4a445E862/logo.png""},{""name"":""Reputation Augur v2"",""address"":""0x221657776846890989a759BA2973e427DfF5C9bB"",""symbol"":""REPv2"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png""},{""name"":""Synthetix Network Token"",""address"":""0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F"",""symbol"":""SNX"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png""},{""name"":""Storj Token"",""address"":""0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC"",""symbol"":""STORJ"",""decimals"":8,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png""},{""chainId"":1,""address"":""0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa"",""name"":""tBTC"",""symbol"":""TBTC"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/11224/thumb/tBTC.png?1589620754""},{""name"":""UMA Voting Token v1"",""address"":""0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828"",""symbol"":""UMA"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png""},{""name"":""Uniswap"",""address"":""0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"",""symbol"":""UNI"",""decimals"":18,""chainId"":1,""logoURI"":""ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg""},{""name"":""USDCoin"",""address"":""0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"",""symbol"":""USDC"",""decimals"":6,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png""},{""name"":""Tether USD"",""address"":""0xdAC17F958D2ee523a2206206994597C13D831ec7"",""symbol"":""USDT"",""decimals"":6,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png""},{""name"":""Wrapped BTC"",""address"":""0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"",""symbol"":""WBTC"",""decimals"":8,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png""},{""name"":""Wrapped Ether"",""address"":""0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"",""symbol"":""WETH"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png""},{""chainId"":1,""address"":""0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e"",""name"":""yearn finance"",""symbol"":""YFI"",""decimals"":18,""logoURI"":""https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330""},{""name"":""0x Protocol Token"",""address"":""0xE41d2489571d322189246DaFA5ebDe1F4699F498"",""symbol"":""ZRX"",""decimals"":18,""chainId"":1,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png""},{""name"":""Dai Stablecoin"",""address"":""0xaD6D458402F60fD3Bd25163575031ACDce07538D"",""symbol"":""DAI"",""decimals"":18,""chainId"":3,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xaD6D458402F60fD3Bd25163575031ACDce07538D/logo.png""},{""name"":""Uniswap"",""address"":""0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"",""symbol"":""UNI"",""decimals"":18,""chainId"":3,""logoURI"":""ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg""},{""name"":""Wrapped Ether"",""address"":""0xc778417E063141139Fce010982780140Aa0cD5Ab"",""symbol"":""WETH"",""decimals"":18,""chainId"":3,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc778417E063141139Fce010982780140Aa0cD5Ab/logo.png""},{""name"":""Dai Stablecoin"",""address"":""0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735"",""symbol"":""DAI"",""decimals"":18,""chainId"":4,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735/logo.png""},{""name"":""Maker"",""address"":""0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85"",""symbol"":""MKR"",""decimals"":18,""chainId"":4,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85/logo.png""},{""name"":""Uniswap"",""address"":""0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"",""symbol"":""UNI"",""decimals"":18,""chainId"":4,""logoURI"":""ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg""},{""name"":""Wrapped Ether"",""address"":""0xc778417E063141139Fce010982780140Aa0cD5Ab"",""symbol"":""WETH"",""decimals"":18,""chainId"":4,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc778417E063141139Fce010982780140Aa0cD5Ab/logo.png""},{""name"":""Uniswap"",""address"":""0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"",""symbol"":""UNI"",""decimals"":18,""chainId"":5,""logoURI"":""ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg""},{""name"":""Wrapped Ether"",""address"":""0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"",""symbol"":""WETH"",""decimals"":18,""chainId"":5,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6/logo.png""},{""name"":""Dai Stablecoin"",""address"":""0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa"",""symbol"":""DAI"",""decimals"":18,""chainId"":42,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa/logo.png""},{""name"":""Maker"",""address"":""0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD"",""symbol"":""MKR"",""decimals"":18,""chainId"":42,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD/logo.png""},{""name"":""Uniswap"",""address"":""0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"",""symbol"":""UNI"",""decimals"":18,""chainId"":42,""logoURI"":""ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg""},{""name"":""Wrapped Ether"",""address"":""0xd0A1E359811322d97991E03f863a0C30C2cF029C"",""symbol"":""WETH"",""decimals"":18,""chainId"":42,""logoURI"":""https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xd0A1E359811322d97991E03f863a0C30C2cF029C/logo.png""}]}";

    //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");
        var tokens = JsonConvert.DeserializeObject<Root>(TokensJSON);
        var aggregateFunction = new AggregateFunction();
        aggregateFunction.Calls = new List<Call>();
        var tokenCount = 30;

        for (int i = 0; i < tokenCount; i++)
        {
            //Setting the owner https://etherscan.io/tokenholdings?a=0x8ee7d9235e01e6b42345120b5d270bdb763624c7
            var balanceOfMessage = new BalanceOfFunction() { Owner = "0x8ee7d9235e01e6b42345120b5d270bdb763624c7" };
            var call = new Call();
            call.CallData = balanceOfMessage.GetCallData();
            call.Target = tokens.Tokens[i].Address;
            aggregateFunction.Calls.Add(call);
        }

        //Creating a new query handler
        var queryHandler = web3.Eth.GetContractQueryHandler<AggregateFunction>();

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

        for (int i = 0; i < tokenCount; i++)
        {
            var balance = new BalanceOfOutputDTO().DecodeOutput(returnCalls.ReturnData[i].ToHex());
            Console.WriteLine("Balance of " + tokens.Tokens[i].Name);
            Console.WriteLine(Web3.Convert.FromWei(balance.Balance, tokens.Tokens[i].Decimals));
        }

    }