< Summary

Class:TheGraph
Assembly:TheGraph
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/ServiceProviders/TheGraph/TheGraph.cs
Covered lines:2
Uncovered lines:92
Coverable lines:94
Total lines:211
Line coverage:2.1% (2 of 94)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
TheGraph()0%110100%
Query(...)0%2100%
Query(...)0%72800%
QueryLands(...)0%2100%
QueryLands(...)0%42600%
QueryPolygonMana(...)0%2100%
QueryNftCollections(...)0%12300%
Dispose()0%110100%
ProcessReceivedLandsData(...)0%12300%
ProcessReceivedNftData(...)0%12300%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/ServiceProviders/TheGraph/TheGraph.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Text.RegularExpressions;
 5using DCL;
 6using DCL.Helpers;
 7using Newtonsoft.Json.Linq;
 8using UnityEngine;
 9using UnityEngine.Networking;
 10
 11public class TheGraph : ITheGraph
 12{
 13    private const float DEFAULT_CACHE_TIME = 5 * 60;
 14    private const string LAND_SUBGRAPH_URL_ORG = "https://api.thegraph.com/subgraphs/name/decentraland/land-manager";
 15    private const string LAND_SUBGRAPH_URL_ZONE = "https://api.thegraph.com/subgraphs/name/decentraland/land-manager-rop
 16    private const string LAND_SUBGRAPH_URL_MATIC = "https://api.thegraph.com/subgraphs/name/decentraland/mana-matic-main
 17    private const string NFT_COLLECTIONS_SUBGRAPH_URL_ETHEREUM = "https://api.thegraph.com/subgraphs/name/decentraland/c
 18    private const string NFT_COLLECTIONS_SUBGRAPH_URL_MATIC = "https://api.thegraph.com/subgraphs/name/decentraland/coll
 19
 7220    private readonly IDataCache<List<Land>> landQueryCache = new DataCache<List<Land>>();
 21
 022    public Promise<string> Query(string url, string query) { return Query(url, query, null); }
 23
 24    public Promise<string> Query(string url, string query, QueryVariablesBase variables)
 25    {
 026        Promise<string> promise = new Promise<string>();
 27
 028        if (string.IsNullOrEmpty(query) || string.IsNullOrEmpty(url))
 29        {
 030            promise.Reject($"error: {(string.IsNullOrEmpty(url) ? "url" : "query")} is empty");
 031            return promise;
 32        }
 33
 034        string queryJson = $"\"query\":\"{Regex.Replace(query, @"\p{C}+", string.Empty)}\"";
 035        string variablesJson = variables != null ? $",\"variables\":{JsonUtility.ToJson(variables)}" : string.Empty;
 036        string bodyString = $"{{{queryJson}{variablesJson}}}";
 37
 038        var request = new UnityWebRequest();
 039        request.url = url;
 040        request.method = UnityWebRequest.kHttpVerbPOST;
 041        request.downloadHandler = new DownloadHandlerBuffer();
 042        request.uploadHandler = new UploadHandlerRaw(string.IsNullOrEmpty(bodyString) ? null : Encoding.UTF8.GetBytes(bo
 043        request.SetRequestHeader("Content-Type", "application/json");
 044        request.timeout = 60;
 45
 046        var operation = request.SendWebRequest();
 47
 048        operation.completed += asyncOperation =>
 49        {
 050            if (request.WebRequestSucceded())
 51            {
 052                promise.Resolve(request.downloadHandler.text);
 053            }
 54            else
 55            {
 056                promise.Reject($"error: {request.error} response: {request.downloadHandler.text}");
 57            }
 58
 059            request.Dispose();
 060        };
 61
 062        return promise;
 63    }
 64
 065    public Promise<List<Land>> QueryLands(string network, string address) { return QueryLands(network, address, DEFAULT_
 66
 67    public Promise<List<Land>> QueryLands(string network, string address, float cacheMaxAgeSeconds)
 68    {
 069        string lowerCaseAddress = address.ToLower();
 70
 071        Promise<List<Land>> promise = new Promise<List<Land>>();
 72
 073        if (cacheMaxAgeSeconds >= 0)
 74        {
 075            if (landQueryCache.TryGet(lowerCaseAddress, out List<Land> cacheValue, out float lastUpdate))
 76            {
 077                if (Time.unscaledTime - lastUpdate <= cacheMaxAgeSeconds)
 78                {
 079                    promise.Resolve(cacheValue);
 080                    return promise;
 81                }
 82            }
 83        }
 84
 085        string url = network == "mainnet" ? LAND_SUBGRAPH_URL_ORG : LAND_SUBGRAPH_URL_ZONE;
 86
 087        Query(url, TheGraphQueries.getLandQuery, new AddressVariable() { address = lowerCaseAddress })
 88            .Then(resultJson =>
 89            {
 090                ProcessReceivedLandsData(promise, resultJson, lowerCaseAddress, true);
 091            })
 092            .Catch(error => promise.Reject(error));
 93
 094        return promise;
 95    }
 96
 97    public Promise<double> QueryPolygonMana(string address)
 98    {
 099        Promise<double> promise = new Promise<double>();
 100
 0101        string lowerCaseAddress = address.ToLower();
 0102        Query(LAND_SUBGRAPH_URL_MATIC, TheGraphQueries.getPolygonManaQuery, new AddressVariable() { address = lowerCaseA
 103            .Then(resultJson =>
 104            {
 105                try
 106                {
 0107                    JObject result = JObject.Parse(resultJson);
 0108                    JToken manaObject = result["data"]?["accounts"].First?["mana"];
 0109                    if (manaObject == null || !double.TryParse(manaObject.Value<string>(), out double parsedMana))
 0110                        throw new Exception($"QueryMana response couldn't be parsed: {resultJson}");
 111
 0112                    promise.Resolve(parsedMana / 1e18);
 0113                }
 0114                catch (Exception e)
 115                {
 0116                    promise.Reject(e.ToString());
 0117                }
 0118            })
 0119            .Catch(error => promise.Reject(error));
 0120        return promise;
 121    }
 122
 123    public Promise<List<Nft>> QueryNftCollections(string address, NftCollectionsLayer layer)
 124    {
 0125        Promise<List<Nft>> promise = new Promise<List<Nft>>();
 126
 0127        string url = "";
 128        switch (layer)
 129        {
 130            case NftCollectionsLayer.ETHEREUM:
 0131                url = NFT_COLLECTIONS_SUBGRAPH_URL_ETHEREUM;
 0132                break;
 133            case NftCollectionsLayer.MATIC:
 0134                url = NFT_COLLECTIONS_SUBGRAPH_URL_MATIC;
 135                break;
 136        }
 137
 0138        Query(url, TheGraphQueries.getNftCollectionsQuery, new AddressVariable() { address = address.ToLower() })
 139            .Then(resultJson =>
 140            {
 0141                ProcessReceivedNftData(promise, resultJson);
 0142            })
 0143            .Catch(error => promise.Reject(error));
 144
 0145        return promise;
 146    }
 147
 144148    public void Dispose() { landQueryCache.Dispose(); }
 149
 150    private void ProcessReceivedLandsData(Promise<List<Land>> landPromise, string jsonValue, string lowerCaseAddress, bo
 151    {
 0152        bool hasException = false;
 0153        List<Land> lands = null;
 154
 155        try
 156        {
 0157            LandQueryResultWrapped result = JsonUtility.FromJson<LandQueryResultWrapped>(jsonValue);
 0158            lands = LandHelper.ConvertQueryResult(result.data, lowerCaseAddress);
 159
 0160            if (cache)
 161            {
 0162                landQueryCache.Add(lowerCaseAddress, lands, DEFAULT_CACHE_TIME);
 163            }
 0164        }
 0165        catch (Exception exception)
 166        {
 0167            landPromise.Reject(exception.Message);
 0168            hasException = true;
 0169        }
 170        finally
 171        {
 0172            if (!hasException)
 173            {
 0174                landPromise.Resolve(lands);
 175            }
 0176        }
 0177    }
 178
 179    private void ProcessReceivedNftData(Promise<List<Nft>> nftPromise, string jsonValue)
 180    {
 0181        bool hasException = false;
 0182        List<Nft> nfts = new List<Nft>();
 183
 184        try
 185        {
 0186            NftQueryResultWrapped result = JsonUtility.FromJson<NftQueryResultWrapped>(jsonValue);
 187
 0188            foreach (var nft in result.data.nfts)
 189            {
 0190                nfts.Add(new Nft
 191                {
 192                    collectionId = nft.collection.id,
 193                    tokenId = nft.tokenId,
 194                    urn = nft.urn
 195                });
 196            }
 0197        }
 0198        catch (Exception exception)
 199        {
 0200            nftPromise.Reject(exception.Message);
 0201            hasException = true;
 0202        }
 203        finally
 204        {
 0205            if (!hasException)
 206            {
 0207                nftPromise.Resolve(nfts);
 208            }
 0209        }
 0210    }
 211}