Skip to content
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
88 changes: 88 additions & 0 deletions Thirdweb.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Thirdweb;
using Thirdweb.AccountAbstraction;
using Thirdweb.AI;
using Thirdweb.Bridge;
using Thirdweb.Indexer;
using Thirdweb.Pay;

Expand Down Expand Up @@ -41,6 +42,93 @@

#endregion

#region Bridge

// // Create a ThirdwebBridge instance
// var bridge = await ThirdwebBridge.Create(client);

// // Buy - Get a quote for buying a specific amount of tokens
// var buyQuote = await bridge.Buy_Quote(
// originChainId: 1,
// originTokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC on Ethereum
// destinationChainId: 324,
// destinationTokenAddress: Constants.NATIVE_TOKEN_ADDRESS, // ETH on zkSync
// buyAmountWei: BigInteger.Parse("0.1".ToWei())
// );
// Console.WriteLine($"Buy quote: {JsonConvert.SerializeObject(buyQuote, Formatting.Indented)}");

// // Buy - Get an executable set of transactions (alongside a quote) for buying a specific amount of tokens
// var preparedBuy = await bridge.Buy_Prepare(
// originChainId: 1,
// originTokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC on Ethereum
// destinationChainId: 324,
// destinationTokenAddress: Constants.NATIVE_TOKEN_ADDRESS, // ETH on zkSync
// buyAmountWei: BigInteger.Parse("0.1".ToWei()),
// sender: await Utils.GetAddressFromENS(client, "vitalik.eth"),
// receiver: await myWallet.GetAddress()
// );
// Console.WriteLine($"Prepared Buy contains {preparedBuy.Transactions.Count} transaction(s)!");

// // Sell - Get a quote for selling a specific amount of tokens
// var sellQuote = await bridge.Sell_Quote(
// originChainId: 324,
// originTokenAddress: Constants.NATIVE_TOKEN_ADDRESS, // ETH on zkSync
// destinationChainId: 1,
// destinationTokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC on Ethereum
// sellAmountWei: BigInteger.Parse("0.1".ToWei())
// );
// Console.WriteLine($"Sell quote: {JsonConvert.SerializeObject(sellQuote, Formatting.Indented)}");

// // Sell - Get an executable set of transactions (alongside a quote) for selling a specific amount of tokens
// var preparedSell = await bridge.Sell_Prepare(
// originChainId: 324,
// originTokenAddress: Constants.NATIVE_TOKEN_ADDRESS, // ETH on zkSync
// destinationChainId: 1,
// destinationTokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC on Ethereum
// sellAmountWei: BigInteger.Parse("0.1".ToWei()),
// sender: await Utils.GetAddressFromENS(client, "vitalik.eth"),
// receiver: await myWallet.GetAddress()
// );
// Console.WriteLine($"Prepared Sell contains {preparedSell.Transactions.Count} transaction(s)!");

// // Transfer - Get an executable transaction for transferring a specific amount of tokens
// var preparedTransfer = await bridge.Transfer_Prepare(
// chainId: 137,
// tokenAddress: Constants.NATIVE_TOKEN_ADDRESS, // ETH on zkSync
// transferAmountWei: BigInteger.Parse("0.1".ToWei()),
// sender: await Utils.GetAddressFromENS(client, "vitalik.eth"),
// receiver: await myWallet.GetAddress()
// );
// Console.WriteLine($"Prepared Transfer: {JsonConvert.SerializeObject(preparedTransfer, Formatting.Indented)}");

// // You may use our extensions to execute yourself...
// var myTx = await preparedTransfer.Transactions[0].ToThirdwebTransaction(myWallet);
// var myHash = await ThirdwebTransaction.Send(myTx);

// // ...and poll for the status...
// var status = await bridge.Status(transactionHash: myHash, chainId: 1);
// var isComplete = status.StatusType == StatusType.COMPLETED;
// Console.WriteLine($"Status: {JsonConvert.SerializeObject(status, Formatting.Indented)}");

// // Or use our Execute extensions directly to handle everything for you!

// // Execute a prepared Buy
// var buyResult = await bridge.Execute(myWallet, preparedBuy);
// var buyHashes = buyResult.Select(receipt => receipt.TransactionHash).ToList();
// Console.WriteLine($"Buy hashes: {JsonConvert.SerializeObject(buyHashes, Formatting.Indented)}");

// // Execute a prepared Sell
// var sellResult = await bridge.Execute(myWallet, preparedSell);
// var sellHashes = sellResult.Select(receipt => receipt.TransactionHash).ToList();
// Console.WriteLine($"Sell hashes: {JsonConvert.SerializeObject(sellHashes, Formatting.Indented)}");

// // Execute a prepared Transfer
// var transferResult = await bridge.Execute(myWallet, preparedTransfer);
// var transferHashes = transferResult.Select(receipt => receipt.TransactionHash).ToList();
// Console.WriteLine($"Transfer hashes: {JsonConvert.SerializeObject(transferHashes, Formatting.Indented)}");

#endregion

#region Indexer

// // Create a ThirdwebInsight instance
Expand Down
121 changes: 121 additions & 0 deletions Thirdweb/Thirdweb.Bridge/ThirdwebBridge.Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System.Numerics;

namespace Thirdweb.Bridge;

public static class ThirdwebBridgeExtensions
{
#region Execution

/// <summary>
/// Executes buy transaction(s) and handles status polling.
/// </summary>
/// <param name="bridge">The Thirdweb bridge.</param>
/// <param name="executor">The executor wallet.</param>
/// <param name="preparedBuy">The buy data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The transaction receipts as a list of <see cref="ThirdwebTransactionReceipt"/>.</returns>
public static async Task<List<ThirdwebTransactionReceipt>> Execute(this ThirdwebBridge bridge, IThirdwebWallet executor, BuyPrepareData preparedBuy, CancellationToken cancellationToken = default)
{
return await ExecuteInternal(bridge, executor, preparedBuy.Transactions, cancellationToken);
}

/// <summary>
/// Executes sell transaction(s) and handles status polling.
/// </summary>
/// <param name="bridge">The Thirdweb bridge.</param>
/// <param name="executor">The executor wallet.</param>
/// <param name="preparedSell">The prepared sell data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The transaction receipts as a list of <see cref="ThirdwebTransactionReceipt"/>.</returns>
public static async Task<List<ThirdwebTransactionReceipt>> Execute(
this ThirdwebBridge bridge,
IThirdwebWallet executor,
SellPrepareData preparedSell,
CancellationToken cancellationToken = default
)
{
return await ExecuteInternal(bridge, executor, preparedSell.Transactions, cancellationToken);
}

/// <summary>
/// Executes a transfer transaction and handles status polling.
/// </summary>
/// <param name="bridge">The Thirdweb bridge.</param>
/// <param name="executor">The executor wallet.</param>
/// <param name="preparedTransfer">The prepared transfer data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The transaction receipts as a list of <see cref="ThirdwebTransactionReceipt"/>.</returns>
public static Task<List<ThirdwebTransactionReceipt>> Execute(
this ThirdwebBridge bridge,
IThirdwebWallet executor,
TransferPrepareData preparedTransfer,
CancellationToken cancellationToken = default
)
{
return ExecuteInternal(bridge, executor, preparedTransfer.Transactions, cancellationToken);
}

private static async Task<List<ThirdwebTransactionReceipt>> ExecuteInternal(
this ThirdwebBridge bridge,
IThirdwebWallet executor,
List<Transaction> transactions,
CancellationToken cancellationToken = default
)
{
var receipts = new List<ThirdwebTransactionReceipt>();
foreach (var tx in transactions)
{
var thirdwebTx = await tx.ToThirdwebTransaction(executor);
var hash = await ThirdwebTransaction.Send(thirdwebTx);
receipts.Add(await ThirdwebTransaction.WaitForTransactionReceipt(executor.Client, tx.ChainId, hash, cancellationToken));
_ = await bridge.WaitForStatusCompletion(hash, tx.ChainId, cancellationToken);
}
return receipts;
}

#endregion

#region Helpers

public static async Task<ThirdwebTransaction> ToThirdwebTransaction(this Transaction transaction, IThirdwebWallet executor)
{
return await ThirdwebTransaction.Create(
executor,
new ThirdwebTransactionInput(
chainId: transaction.ChainId,
to: transaction.To,
value: BigInteger.Parse(string.IsNullOrEmpty(transaction.Value) ? "0" : transaction.Value),
data: string.IsNullOrEmpty(transaction.Data) ? "0x" : transaction.Data
)
);
}

public static async Task<StatusData> WaitForStatusCompletion(this ThirdwebBridge bridge, string hash, BigInteger chainId, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(hash))
{
throw new ArgumentNullException(nameof(hash));
}

if (chainId == 0)
{
throw new ArgumentNullException(nameof(chainId));
}

var status = await bridge.Status(hash, chainId);
while (status.StatusType is StatusType.PENDING or StatusType.NOT_FOUND)
{
await ThirdwebTask.Delay(500, cancellationToken);
status = await bridge.Status(hash, chainId);
}

if (status.StatusType is StatusType.FAILED)
{
throw new Exception($"Transaction with hash {hash} failed.");
}

return status;
}

#endregion
}
Loading
Loading