Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Assets/SequenceSDK/Indexer/Tests/MockHttpHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ public Task<string> HttpPost(string chainID, string endPoint, object args, int r
return Task.FromResult(_response);
}

public void HttpStream<T>(string chainID, string endPoint, object args, WebRPCStreamOptions<T> options, int retries = 0)
public Task<T> HttpPost<T>(string url, object args)
{
throw new NotImplementedException();
}

public void HttpStream<T>(string chainID, string endPoint, object args, WebRPCStreamOptions<T> options)
{
throw new NotImplementedException();
}
Expand Down
28 changes: 28 additions & 0 deletions Assets/SequenceSDK/Indexer/Tests/PriceFeedTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Threading.Tasks;
using NUnit.Framework;

namespace Sequence.Indexer.Tests
{
public class PriceFeedTests
{
[Test]
public async Task TestGetCoinPrices()
{
Address polygonUSDC = new Address("0x3c499c542cef5e3811e1192ce70d8cc03d5c3359");
Address arbitrumNovaUSDC = new Address("0x750ba8b76187092B0D1E87E28daaf484d1b5273b");
PriceFeed.Token polygonUSDCtoken = new PriceFeed.Token(Chain.Polygon, polygonUSDC);
PriceFeed.Token arbitrumNovaUSDCtoken = new PriceFeed.Token(Chain.ArbitrumNova, arbitrumNovaUSDC);
PriceFeed priceFeed = new PriceFeed();

TokenPrice[] prices = await priceFeed.GetCoinPrices(polygonUSDCtoken, arbitrumNovaUSDCtoken);

Assert.NotNull(prices);
Assert.AreEqual(2, prices.Length);
Assert.AreEqual(polygonUSDC, prices[0].token.Contract);
Assert.AreEqual(arbitrumNovaUSDC, prices[1].token.Contract);
Assert.AreEqual(1, Math.Round(prices[0].price.value));
Assert.AreEqual(1, Math.Round(prices[1].price.value));
}
}
}
3 changes: 3 additions & 0 deletions Assets/SequenceSDK/Indexer/Tests/PriceFeedTests.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using UnityEngine.Scripting;

namespace Sequence
{
[Serializable]
internal class GetTokenPricesArgs
{
public PriceFeed.Token[] tokens;

public GetTokenPricesArgs(PriceFeed.Token[] tokens)
{
this.tokens = tokens;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using UnityEngine.Scripting;

namespace Sequence
{
[Serializable]
internal class GetTokenPricesReturn
{
public TokenPrice[] tokenPrices;

[Preserve]
public GetTokenPricesReturn(TokenPrice[] tokenPrices)
{
this.tokenPrices = tokenPrices;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace Sequence
{
[Serializable]
public class Price
{
public decimal value;
public string currency;

public Price(decimal value, string currency)
{
this.value = value;
this.currency = currency;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using UnityEngine.Scripting;

namespace Sequence
{
[Serializable]
public class TokenPrice
{
public PriceFeed.Token token;
public Price price;
public Price price24hChange;
public Price floorPrice;
public Price buyPrice;
public Price sellPrice;
public DateTime updatedAt;

[Preserve]
public TokenPrice(PriceFeed.Token token, Price price, Price price24hChange, Price floorPrice, Price buyPrice, Price sellPrice, DateTime updatedAt)
{
this.token = token;
this.price = price;
this.price24hChange = price24hChange;
this.floorPrice = floorPrice;
this.buyPrice = buyPrice;
this.sellPrice = sellPrice;
this.updatedAt = updatedAt;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Sequence.Utils;
Expand Down Expand Up @@ -106,7 +107,65 @@ public async Task<string> HttpPost(string chainID, string endPoint, object args,
return "";
}

public async void HttpStream<T>(string chainID, string endPoint, object args, WebRPCStreamOptions<T> options, int retries = 0)
public async Task<T> HttpPost<T>(string url, object args)
{
string requestJson = JsonConvert.SerializeObject(args, serializerSettings);
using var req = UnityWebRequest.Put(url, requestJson);
req.SetRequestHeader("Content-Type", "application/json");
req.SetRequestHeader("Accept", "application/json");
req.SetRequestHeader("X-Access-Key", _builderApiKey);
req.method = UnityWebRequest.kHttpVerbPOST;
req.timeout = 10;

string curlRequest =
$"curl -X POST -H \"Content-Type: application/json\" -H \"Accept: application/json\" -H \"X-Access-Key: {req.GetRequestHeader("X-Access-Key")}\" -d '{requestJson}' {url}";

try
{
await req.SendWebRequest();
if (req.responseCode < 200 || req.responseCode > 299 || req.error != null ||
req.result == UnityWebRequest.Result.ConnectionError ||
req.result == UnityWebRequest.Result.ProtocolError)
{
throw new Exception("Failed to make request, non-200 status code " + req.responseCode +
" with error: " + req.error + "\nCurl-equivalent request: " + curlRequest);
}

byte[] results = req.downloadHandler.data;
var responseJson = Encoding.UTF8.GetString(results);
try
{
T result = JsonConvert.DeserializeObject<T>(responseJson);
return result;
}
catch (Exception e)
{
throw new Exception(
$"Error unmarshalling response from {url}: {e.Message} | given: {responseJson}");
}
}
catch (HttpRequestException e)
{
throw new HttpRequestException("HTTP Request failed: " + e.Message + "\nCurl-equivalent request: " + curlRequest);
}
catch (FormatException e)
{
throw new FormatException("Invalid URL format: " + e.Message + "\nCurl-equivalent request: " + curlRequest);
}
catch (FileLoadException e)
{
throw new FileLoadException("File load exception: " + e.Message + "\nCurl-equivalent request: " + curlRequest);
}
catch (Exception e) {
throw new Exception("An unexpected error occurred: " + e.Message + "\nCurl-equivalent request: " + curlRequest);
}
finally
{
req.Dispose();
}
}

public async void HttpStream<T>(string chainID, string endPoint, object args, WebRPCStreamOptions<T> options)
{
var requestJson = JsonConvert.SerializeObject(args, serializerSettings);
using var req = UnityWebRequest.Put(Url(chainID, endPoint), requestJson);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public interface IHttpHandler
/// </summary>
/// <returns></returns>
public Task<string> HttpPost(string chainID, string endPoint, object args, int retries = 0);
public void HttpStream<T>(string chainID, string endPoint, object args, WebRPCStreamOptions<T> options, int retries = 0);
public Task<T> HttpPost<T>(string url, object args);
public void HttpStream<T>(string chainID, string endPoint, object args, WebRPCStreamOptions<T> options);
public void AbortStreams();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sequence.Config;
using Sequence.Utils;
using UnityEngine.Scripting;

namespace Sequence
{
public class PriceFeed
{
[Serializable]
[JsonConverter(typeof(TokenConverter))]
public class Token
{
public Chain Chain;
public Address Contract;

public Token(Chain chain, Address contract)
{
Chain = chain;
Contract = contract;
}

[Preserve]
[JsonConstructor]
public Token(BigInteger chainId, string contractAddress)
{
Chain = ChainDictionaries.ChainById[chainId.ToString()];
Contract = new Address(contractAddress);
}
}

private class TokenConverter : JsonConverter<Token>
{
public override void WriteJson(JsonWriter writer, Token value, JsonSerializer serializer)
{
var jsonObject = new JObject
{
["chainId"] = ulong.Parse(ChainDictionaries.ChainIdOf[value.Chain]),
["contractAddress"] = value.Contract.ToString(),
};
jsonObject.WriteTo(writer);
}

public override Token ReadJson(JsonReader reader, Type objectType, Token existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);

BigInteger chainId = jsonObject["chainId"]?.Value<ulong>() ?? 0;
string contractAddress = jsonObject["contractAddress"]?.Value<string>();

return new Token(chainId, contractAddress);
}
}

private const string _devUrl = "https://dev-api.sequence.app/rpc/API";
private const string _prodUrl = "https://api.sequence.app/rpc/API";

private IHttpHandler _httpHandler;
private string _baseUrl;

public PriceFeed(IHttpHandler httpHandler = null)
{
_httpHandler = httpHandler;
if (_httpHandler == null)
{
_httpHandler = new HttpHandler(SequenceConfig.GetConfig(SequenceService.Stack).BuilderAPIKey);
}

#if SEQUENCE_DEV_STACK || SEQUENCE_DEV
_baseUrl = _devUrl;
#else
_baseUrl = _prodUrl;
#endif
}

public async Task<TokenPrice[]> GetCoinPrices(params Token[] tokens)
{
GetTokenPricesArgs args = new GetTokenPricesArgs(tokens);
GetTokenPricesReturn response = await _httpHandler.HttpPost<GetTokenPricesReturn>(_baseUrl.AppendTrailingSlashIfNeeded() + "GetCoinPrices", args);
return response.tokenPrices;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Packages/Sequence-Unity/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "xyz.0xsequence.waas-unity",
"version": "3.19.3",
"version": "3.20.0",
"displayName": "Sequence Embedded Wallet SDK",
"description": "A Unity SDK for the Sequence WaaS API",
"unity": "2021.3",
Expand Down