Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chain Fetch Util #43

Merged
merged 1 commit into from
Jul 5, 2024
Merged
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
69 changes: 45 additions & 24 deletions Thirdweb.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Diagnostics;
using Thirdweb.Pay;
using Newtonsoft.Json;
using Nethereum.Hex.HexTypes;
using System.Numerics;

DotEnv.Load();

Expand All @@ -23,6 +25,25 @@
var privateKeyWallet = await PrivateKeyWallet.Create(client: client, privateKeyHex: privateKey);
var walletAddress = await privateKeyWallet.GetAddress();

var chainData = await Utils.FetchThirdwebChainDataAsync(client, 421614);
Console.WriteLine($"Chain data: {JsonConvert.SerializeObject(chainData, Formatting.Indented)}");

// var smartWallet = await SmartWallet.Create(privateKeyWallet, 78600);

// // self transfer 0
// var tx = await ThirdwebTransaction.Create(
// smartWallet,
// new ThirdwebTransactionInput()
// {
// From = await smartWallet.GetAddress(),
// To = await smartWallet.GetAddress(),
// Value = new HexBigInteger(BigInteger.Zero)
// },
// 78600
// );
// var txHash = await ThirdwebTransaction.Send(tx);
// Console.WriteLine($"Transaction hash: {txHash}");

// // Buy with Fiat
// // Find out more about supported FIAT currencies
// var supportedCurrencies = await ThirdwebPay.GetBuyWithFiatCurrencies(client);
Expand Down Expand Up @@ -60,30 +81,30 @@
// Buy with Crypto

// Swap Polygon MATIC to Base ETH
var swapQuoteParams = new BuyWithCryptoQuoteParams(
fromAddress: walletAddress,
fromChainId: 137,
fromTokenAddress: Thirdweb.Constants.NATIVE_TOKEN_ADDRESS,
toTokenAddress: Thirdweb.Constants.NATIVE_TOKEN_ADDRESS,
toChainId: 8453,
toAmount: "0.1"
);
var swapQuote = await ThirdwebPay.GetBuyWithCryptoQuote(client, swapQuoteParams);
Console.WriteLine($"Swap quote: {JsonConvert.SerializeObject(swapQuote, Formatting.Indented)}");

// Initiate swap
var txHash = await ThirdwebPay.BuyWithCrypto(wallet: privateKeyWallet, buyWithCryptoQuote: swapQuote);
Console.WriteLine($"Swap transaction hash: {txHash}");

// Poll for status
var currentSwapStatus = SwapStatus.NONE;
while (currentSwapStatus is not SwapStatus.COMPLETED and not SwapStatus.FAILED)
{
var swapStatus = await ThirdwebPay.GetBuyWithCryptoStatus(client, txHash);
currentSwapStatus = Enum.Parse<SwapStatus>(swapStatus.Status);
Console.WriteLine($"Swap status: {JsonConvert.SerializeObject(swapStatus, Formatting.Indented)}");
await Task.Delay(5000);
}
// var swapQuoteParams = new BuyWithCryptoQuoteParams(
// fromAddress: walletAddress,
// fromChainId: 137,
// fromTokenAddress: Thirdweb.Constants.NATIVE_TOKEN_ADDRESS,
// toTokenAddress: Thirdweb.Constants.NATIVE_TOKEN_ADDRESS,
// toChainId: 8453,
// toAmount: "0.1"
// );
// var swapQuote = await ThirdwebPay.GetBuyWithCryptoQuote(client, swapQuoteParams);
// Console.WriteLine($"Swap quote: {JsonConvert.SerializeObject(swapQuote, Formatting.Indented)}");

// // Initiate swap
// var txHash = await ThirdwebPay.BuyWithCrypto(wallet: privateKeyWallet, buyWithCryptoQuote: swapQuote);
// Console.WriteLine($"Swap transaction hash: {txHash}");

// // Poll for status
// var currentSwapStatus = SwapStatus.NONE;
// while (currentSwapStatus is not SwapStatus.COMPLETED and not SwapStatus.FAILED)
// {
// var swapStatus = await ThirdwebPay.GetBuyWithCryptoStatus(client, txHash);
// currentSwapStatus = Enum.Parse<SwapStatus>(swapStatus.Status);
// Console.WriteLine($"Swap status: {JsonConvert.SerializeObject(swapStatus, Formatting.Indented)}");
// await Task.Delay(5000);
// }


// var inAppWallet = await InAppWallet.Create(client: client, email: "[email protected]"); // or email: null, phoneNumber: "+1234567890"
Expand Down
50 changes: 49 additions & 1 deletion Thirdweb.Tests/Thirdweb.Utils/Thirdweb.Utils.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
using System.Numerics;
using System.Text.Json;

namespace Thirdweb.Tests.Utilities;

public class UtilsTests : BaseTests
{
private readonly ThirdwebClient _client;

public UtilsTests(ITestOutputHelper output)
: base(output) { }
: base(output)
{
_client = ThirdwebClient.Create(secretKey: _secretKey);
}

[Fact(Timeout = 120000)]
public void ComputeClientIdFromSecretKey()
Expand Down Expand Up @@ -428,4 +434,46 @@ public void AdjustDecimals_ReturnsCorrectValue4()
var adjustedValue = value.AdjustDecimals(18, 19);
Assert.Equal(new BigInteger(15000000000000000000), adjustedValue);
}

[Fact(Timeout = 120000)]
public async Task FetchThirdwebChainDataAsync_ReturnsChainData_WhenResponseIsSuccessful()
{
var chainId = new BigInteger(1);

var chainData = await Utils.FetchThirdwebChainDataAsync(_client, chainId);

Assert.NotNull(chainData);
_ = Assert.IsType<ThirdwebChainData>(chainData);

Assert.Equal("Ethereum Mainnet", chainData.Name);
Assert.Equal("eth", chainData.ShortName);
Assert.Equal(1, chainData.ChainId);
Assert.Equal(1, chainData.NetworkId);
Assert.Equal("ethereum", chainData.Slug);
Assert.Equal("https://ethereum.org", chainData.InfoURL);
Assert.NotNull(chainData.Icon);
Assert.NotNull(chainData.NativeCurrency);
Assert.NotNull(chainData.NativeCurrency.Name);
Assert.NotNull(chainData.NativeCurrency.Symbol);
Assert.Equal(18, chainData.NativeCurrency.Decimals);
Assert.NotNull(chainData.Features);
Assert.NotNull(chainData.Faucets);
Assert.NotNull(chainData.Explorers);
Assert.NotNull(chainData.RedFlags);
Assert.Null(chainData.Parent);

chainId = 42161;
chainData = await Utils.FetchThirdwebChainDataAsync(_client, chainId);
Assert.NotNull(chainData.Parent);
}

[Fact(Timeout = 120000)]
public async Task FetchThirdwebChainDataAsync_ThrowsException_WhenResponseHasError()
{
var chainId = BigInteger.Zero;

var exception = await Assert.ThrowsAsync<Exception>(async () => await Utils.FetchThirdwebChainDataAsync(_client, chainId));

Assert.Contains("Failed to fetch chain data", exception.Message);
}
}
147 changes: 147 additions & 0 deletions Thirdweb/Thirdweb.Utils/ThirdwebChainData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using Newtonsoft.Json;

namespace Thirdweb
{
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class ThirdwebChainDataResponse
{
[JsonProperty("data")]
public ThirdwebChainData Data { get; set; }

[JsonProperty("error")]
public object Error { get; set; }
}

[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class ThirdwebChainData
{
[JsonProperty("name")]
public string Name { get; set; }

[JsonProperty("chain")]
public string Chain { get; set; }

[JsonProperty("rpc")]
public List<string> Rpc { get; set; }

[JsonProperty("nativeCurrency")]
public ThirdwebChainNativeCurrency NativeCurrency { get; set; }

[JsonProperty("shortName")]
public string ShortName { get; set; }

[JsonProperty("chainId")]
public int ChainId { get; set; }

[JsonProperty("networkId")]
public int NetworkId { get; set; }

[JsonProperty("slug")]
public string Slug { get; set; }

[JsonProperty("infoURL")]
public string InfoURL { get; set; }

[JsonProperty("icon")]
public ThirdwebChainIcon Icon { get; set; }

[JsonProperty("features")]
public List<ThirdwebChainFeature> Features { get; set; }

[JsonProperty("faucets")]
public List<object> Faucets { get; set; }

[JsonProperty("slip44")]
public int? Slip44 { get; set; }

[JsonProperty("ens")]
public ThirdwebChainEns Ens { get; set; }

[JsonProperty("explorers")]
public List<ThirdwebChainExplorer> Explorers { get; set; }

[JsonProperty("testnet")]
public bool Testnet { get; set; }

[JsonProperty("redFlags")]
public List<object> RedFlags { get; set; }

[JsonProperty("parent")]
public ThirdwebChainParent Parent { get; set; }
}

[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class ThirdwebChainNativeCurrency
{
[JsonProperty("name")]
public string Name { get; set; }

[JsonProperty("symbol")]
public string Symbol { get; set; }

[JsonProperty("decimals")]
public int Decimals { get; set; }
}

[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class ThirdwebChainIcon
{
[JsonProperty("url")]
public string Url { get; set; }

[JsonProperty("width")]
public int Width { get; set; }

[JsonProperty("height")]
public int Height { get; set; }

[JsonProperty("format")]
public string Format { get; set; }
}

[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class ThirdwebChainFeature
{
[JsonProperty("name")]
public string Name { get; set; }
}

public class ThirdwebChainEns
{
[JsonProperty("registry")]
public string Registry { get; set; }
}

public class ThirdwebChainExplorer
{
[JsonProperty("name")]
public string Name { get; set; }

[JsonProperty("url")]
public string Url { get; set; }

[JsonProperty("standard")]
public string Standard { get; set; }

[JsonProperty("icon")]
public ThirdwebChainIcon Icon { get; set; }
}

public class ThirdwebChainParent
{
[JsonProperty("type")]
public string Type { get; set; }

[JsonProperty("chain")]
public string Chain { get; set; }

[JsonProperty("bridges")]
public List<ThirdwebChainBridge> Bridges { get; set; }
}

public class ThirdwebChainBridge
{
[JsonProperty("url")]
public string Url { get; set; }
}
}
27 changes: 27 additions & 0 deletions Thirdweb/Thirdweb.Utils/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,32 @@ public static BigInteger AdjustDecimals(this BigInteger value, int fromDecimals,

return value;
}

public static async Task<ThirdwebChainData> FetchThirdwebChainDataAsync(ThirdwebClient client, BigInteger chainId)
{
var url = $"https://api.thirdweb-dev.com/v1/chains/{chainId}";
try
{
var response = await client.HttpClient.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
var deserializedResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ThirdwebChainDataResponse>(json);

return deserializedResponse == null || deserializedResponse.Error != null
? throw new Exception($"Failed to fetch chain data for chain ID {chainId}. Error: {Newtonsoft.Json.JsonConvert.SerializeObject(deserializedResponse?.Error)}")
: deserializedResponse.Data;
}
catch (HttpRequestException httpEx)
{
throw new Exception($"HTTP request error while fetching chain data for chain ID {chainId}: {httpEx.Message}", httpEx);
}
catch (Newtonsoft.Json.JsonException jsonEx)
{
throw new Exception($"JSON deserialization error while fetching chain data for chain ID {chainId}: {jsonEx.Message}", jsonEx);
}
catch (Exception ex)
{
throw new Exception($"Unexpected error while fetching chain data for chain ID {chainId}: {ex.Message}", ex);
}
}
}
}
Loading