diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs
index 4945a031..36c007f5 100644
--- a/Thirdweb.Console/Program.cs
+++ b/Thirdweb.Console/Program.cs
@@ -13,6 +13,7 @@
using Thirdweb;
using Thirdweb.AccountAbstraction;
using Thirdweb.AI;
+using Thirdweb.Bridge;
using Thirdweb.Indexer;
using Thirdweb.Pay;
@@ -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
diff --git a/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.Extensions.cs b/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.Extensions.cs
new file mode 100644
index 00000000..04d1428e
--- /dev/null
+++ b/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.Extensions.cs
@@ -0,0 +1,121 @@
+using System.Numerics;
+
+namespace Thirdweb.Bridge;
+
+public static class ThirdwebBridgeExtensions
+{
+ #region Execution
+
+ ///
+ /// Executes buy transaction(s) and handles status polling.
+ ///
+ /// The Thirdweb bridge.
+ /// The executor wallet.
+ /// The buy data.
+ /// The cancellation token.
+ /// The transaction receipts as a list of .
+ public static async Task> Execute(this ThirdwebBridge bridge, IThirdwebWallet executor, BuyPrepareData preparedBuy, CancellationToken cancellationToken = default)
+ {
+ return await ExecuteInternal(bridge, executor, preparedBuy.Transactions, cancellationToken);
+ }
+
+ ///
+ /// Executes sell transaction(s) and handles status polling.
+ ///
+ /// The Thirdweb bridge.
+ /// The executor wallet.
+ /// The prepared sell data.
+ /// The cancellation token.
+ /// The transaction receipts as a list of .
+ public static async Task> Execute(
+ this ThirdwebBridge bridge,
+ IThirdwebWallet executor,
+ SellPrepareData preparedSell,
+ CancellationToken cancellationToken = default
+ )
+ {
+ return await ExecuteInternal(bridge, executor, preparedSell.Transactions, cancellationToken);
+ }
+
+ ///
+ /// Executes a transfer transaction and handles status polling.
+ ///
+ /// The Thirdweb bridge.
+ /// The executor wallet.
+ /// The prepared transfer data.
+ /// The cancellation token.
+ /// The transaction receipts as a list of .
+ public static Task> Execute(
+ this ThirdwebBridge bridge,
+ IThirdwebWallet executor,
+ TransferPrepareData preparedTransfer,
+ CancellationToken cancellationToken = default
+ )
+ {
+ return ExecuteInternal(bridge, executor, preparedTransfer.Transactions, cancellationToken);
+ }
+
+ private static async Task> ExecuteInternal(
+ this ThirdwebBridge bridge,
+ IThirdwebWallet executor,
+ List transactions,
+ CancellationToken cancellationToken = default
+ )
+ {
+ var receipts = new List();
+ 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 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 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
+}
diff --git a/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.Types.cs b/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.Types.cs
new file mode 100644
index 00000000..a5a7219c
--- /dev/null
+++ b/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.Types.cs
@@ -0,0 +1,369 @@
+using System.Numerics;
+using Newtonsoft.Json;
+
+namespace Thirdweb.Bridge;
+
+///
+/// Represents the response model wrapping the result of an API call.
+///
+/// The type of the result.
+internal class ResponseModel
+{
+ ///
+ /// The result returned by the API.
+ ///
+ [JsonProperty("data")]
+ internal T Data { get; set; }
+}
+
+#region Common Types
+
+///
+/// Represents the base intent object for different types of transactions.
+///
+public class Intent
+{
+ ///
+ /// The chain ID where the transaction originates.
+ ///
+ [JsonProperty("originChainId")]
+ public BigInteger OriginChainId { get; set; }
+
+ ///
+ /// The token address in the origin chain.
+ ///
+ [JsonProperty("originTokenAddress")]
+ public string OriginTokenAddress { get; set; }
+
+ ///
+ /// The chain ID where the transaction is executed.
+ ///
+ [JsonProperty("destinationChainId")]
+ public BigInteger DestinationChainId { get; set; }
+
+ ///
+ /// The token address in the destination chain.
+ ///
+ [JsonProperty("destinationTokenAddress")]
+ public string DestinationTokenAddress { get; set; }
+
+ ///
+ /// The amount involved in the transaction (buy, sell, or transfer) in wei.
+ ///
+ public virtual string AmountWei { get; set; }
+}
+
+///
+/// Represents the common fields for both Buy and Sell transactions.
+///
+public class QuoteData
+ where TIntent : Intent
+{
+ ///
+ /// The amount (in wei) of the input token that must be paid to receive the desired amount.
+ ///
+ [JsonProperty("originAmount")]
+ public string OriginAmount { get; set; }
+
+ ///
+ /// The amount (in wei) of the output token to be received by the receiver address.
+ ///
+ [JsonProperty("destinationAmount")]
+ public string DestinationAmount { get; set; }
+
+ ///
+ /// The timestamp when the quote was generated.
+ ///
+ [JsonProperty("timestamp")]
+ public long Timestamp { get; set; }
+
+ ///
+ /// The block number when the quote was generated.
+ ///
+ [JsonProperty("blockNumber")]
+ public string BlockNumber { get; set; }
+
+ ///
+ /// The estimated execution time in milliseconds for filling the quote.
+ ///
+ [JsonProperty("estimatedExecutionTimeMs")]
+ public long EstimatedExecutionTimeMs { get; set; }
+
+ ///
+ /// The intent object containing details about the transaction.
+ ///
+ [JsonProperty("intent")]
+ public TIntent Intent { get; set; }
+}
+
+///
+/// Represents a transaction to be executed.
+///
+public class Transaction
+{
+ ///
+ /// The chain ID where the transaction will take place.
+ ///
+ [JsonProperty("chainId")]
+ public BigInteger ChainId { get; set; }
+
+ ///
+ /// The address to which the transaction is sent, or null if not applicable.
+ ///
+ [JsonProperty("to", NullValueHandling = NullValueHandling.Ignore)]
+ public string To { get; set; }
+
+ ///
+ /// The value (amount) to be sent in the transaction.
+ ///
+ [JsonProperty("value")]
+ public string Value { get; set; }
+
+ ///
+ /// The transaction data.
+ ///
+ [JsonProperty("data")]
+ public string Data { get; set; }
+
+ ///
+ /// The type of the transaction (e.g., "eip1559").
+ ///
+ [JsonProperty("type")]
+ public string Type { get; set; }
+}
+
+#endregion
+
+#region Buy
+
+///
+/// Represents the data returned in the buy quote response.
+///
+public class BuyQuoteData : QuoteData { }
+
+///
+/// Represents the data returned in the buy prepare response.
+///
+public class BuyPrepareData : QuoteData
+{
+ ///
+ /// An array of transactions to be executed to fulfill this quote (in order).
+ ///
+ [JsonProperty("transactions")]
+ public List Transactions { get; set; }
+
+ ///
+ /// The expiration timestamp for this prepared quote and its transactions (if applicable).
+ ///
+ [JsonProperty("expiration")]
+ public long? Expiration { get; set; }
+}
+
+///
+/// Represents the intent object for a buy quote.
+///
+public class BuyIntent : Intent
+{
+ ///
+ /// The desired output amount in wei for buying.
+ ///
+ [JsonProperty("buyAmountWei")]
+ public override string AmountWei { get; set; }
+}
+
+#endregion
+
+#region Sell
+
+///
+/// Represents the data returned in the sell quote response.
+///
+public class SellQuoteData : QuoteData { }
+
+///
+/// Represents the data returned in the sell prepare response.
+///
+public class SellPrepareData : QuoteData
+{
+ ///
+ /// An array of transactions to be executed to fulfill this quote (in order).
+ ///
+ [JsonProperty("transactions")]
+ public List Transactions { get; set; }
+
+ ///
+ /// The expiration timestamp for this prepared quote and its transactions (if applicable).
+ ///
+ [JsonProperty("expiration")]
+ public long? Expiration { get; set; }
+}
+
+///
+/// Represents the intent object for a sell quote.
+///
+public class SellIntent : Intent
+{
+ ///
+ /// The amount to sell in wei.
+ ///
+ [JsonProperty("sellAmountWei")]
+ public override string AmountWei { get; set; }
+}
+
+#endregion
+
+#region Transfer
+
+///
+/// Represents the data returned in the transfer prepare response.
+///
+public class TransferPrepareData
+{
+ [JsonProperty("originAmount")]
+ public string OriginAmount { get; set; }
+
+ [JsonProperty("destinationAmount")]
+ public string DestinationAmount { get; set; }
+
+ [JsonProperty("timestamp")]
+ public long Timestamp { get; set; }
+
+ [JsonProperty("blockNumber")]
+ public string BlockNumber { get; set; }
+
+ [JsonProperty("estimatedExecutionTimeMs")]
+ public long EstimatedExecutionTimeMs { get; set; }
+
+ [JsonProperty("transactions")]
+ public List Transactions { get; set; }
+
+ [JsonProperty("expiration")]
+ public long? Expiration { get; set; }
+
+ [JsonProperty("intent")]
+ public TransferIntent Intent { get; set; }
+}
+
+///
+/// Represents the intent object for the transfer prepare response.
+///
+public class TransferIntent
+{
+ [JsonProperty("chainId")]
+ public int ChainId { get; set; }
+
+ [JsonProperty("tokenAddress")]
+ public string TokenAddress { get; set; }
+
+ [JsonProperty("transferAmountWei")]
+ public string TransferAmountWei { get; set; }
+
+ [JsonProperty("sender")]
+ public string Sender { get; set; }
+
+ [JsonProperty("receiver")]
+ public string Receiver { get; set; }
+}
+
+#endregion
+
+#region Status
+
+///
+/// Represents the possible statuses for a transaction.
+///
+public enum StatusType
+{
+ FAILED,
+ PENDING,
+ COMPLETED,
+ NOT_FOUND
+}
+
+///
+/// Represents the data returned in the status response.
+///
+public class StatusData
+{
+ ///
+ /// The status of the transaction (as StatusType enum).
+ ///
+ [JsonIgnore]
+ public StatusType StatusType =>
+ this.Status switch
+ {
+ "FAILED" => StatusType.FAILED,
+ "PENDING" => StatusType.PENDING,
+ "COMPLETED" => StatusType.COMPLETED,
+ "NOT_FOUND" => StatusType.NOT_FOUND,
+ _ => throw new InvalidOperationException($"Unknown status: {this.Status}")
+ };
+
+ ///
+ /// The status of the transaction.
+ ///
+ [JsonProperty("status")]
+ public string Status { get; set; }
+
+ ///
+ /// A list of transactions involved in this status.
+ ///
+ [JsonProperty("transactions")]
+ public List Transactions { get; set; }
+
+ ///
+ /// The origin chain ID (for PENDING and COMPLETED statuses).
+ ///
+ [JsonProperty("originChainId", NullValueHandling = NullValueHandling.Ignore)]
+ public BigInteger? OriginChainId { get; set; }
+
+ ///
+ /// The origin token address (for PENDING and COMPLETED statuses).
+ ///
+ [JsonProperty("originTokenAddress", NullValueHandling = NullValueHandling.Ignore)]
+ public string OriginTokenAddress { get; set; }
+
+ ///
+ /// The destination chain ID (for PENDING and COMPLETED statuses).
+ ///
+ [JsonProperty("destinationChainId", NullValueHandling = NullValueHandling.Ignore)]
+ public BigInteger? DestinationChainId { get; set; }
+
+ ///
+ /// The destination token address (for PENDING and COMPLETED statuses).
+ ///
+ [JsonProperty("destinationTokenAddress", NullValueHandling = NullValueHandling.Ignore)]
+ public string DestinationTokenAddress { get; set; }
+
+ ///
+ /// The origin token amount in wei (for PENDING and COMPLETED statuses).
+ ///
+ [JsonProperty("originAmount", NullValueHandling = NullValueHandling.Ignore)]
+ public string OriginAmount { get; set; }
+
+ ///
+ /// The destination token amount in wei (for COMPLETED status).
+ ///
+ [JsonProperty("destinationAmount", NullValueHandling = NullValueHandling.Ignore)]
+ public string DestinationAmount { get; set; }
+}
+
+///
+/// Represents the transaction details for a specific status.
+///
+public class TransactionStatus
+{
+ ///
+ /// The chain ID where the transaction took place.
+ ///
+ [JsonProperty("chainId")]
+ public BigInteger ChainId { get; set; }
+
+ ///
+ /// The transaction hash of the transaction.
+ ///
+ [JsonProperty("transactionHash")]
+ public string TransactionHash { get; set; }
+}
+
+#endregion
diff --git a/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.cs b/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.cs
new file mode 100644
index 00000000..095fd8fd
--- /dev/null
+++ b/Thirdweb/Thirdweb.Bridge/ThirdwebBridge.cs
@@ -0,0 +1,380 @@
+using System.Numerics;
+using Newtonsoft.Json;
+
+namespace Thirdweb.Bridge;
+
+public class ThirdwebBridge
+{
+ private readonly IThirdwebHttpClient _httpClient;
+
+ internal ThirdwebBridge(ThirdwebClient client)
+ {
+ this._httpClient = client.HttpClient;
+ }
+
+ ///
+ /// Create a new instance of the ThirdwebBridge class.
+ ///
+ /// The ThirdwebClient instance.
+ /// A new instance of .
+ public static Task Create(ThirdwebClient client)
+ {
+ return Task.FromResult(new ThirdwebBridge(client));
+ }
+
+ #region Buy
+
+ ///
+ /// Get a quote for buying a specific amount of tokens on any chain.
+ ///
+ /// The chain ID of the origin chain.
+ /// The address of the token on the origin chain.
+ /// The chain ID of the destination chain.
+ /// The address of the token on the destination chain.
+ /// The amount of tokens to buy in wei.
+ /// A object representing the quote.
+ /// Thrown when one of the parameters is invalid.
+ public async Task Buy_Quote(BigInteger originChainId, string originTokenAddress, BigInteger destinationChainId, string destinationTokenAddress, BigInteger buyAmountWei)
+ {
+ if (originChainId <= 0)
+ {
+ throw new ArgumentException("originChainId cannot be less than or equal to 0", nameof(originChainId));
+ }
+
+ if (destinationChainId <= 0)
+ {
+ throw new ArgumentException("destinationChainId cannot be less than or equal to 0", nameof(destinationChainId));
+ }
+
+ if (!Utils.IsValidAddress(originTokenAddress))
+ {
+ throw new ArgumentException("originTokenAddress is not a valid address", nameof(originTokenAddress));
+ }
+
+ if (buyAmountWei <= 0)
+ {
+ throw new ArgumentException("buyAmountWei cannot be less than or equal to 0", nameof(buyAmountWei));
+ }
+
+ var url = $"{Constants.BRIDGE_API_URL}/v1/buy/quote";
+ var queryParams = new Dictionary
+ {
+ { "originChainId", originChainId.ToString() },
+ { "originTokenAddress", originTokenAddress },
+ { "destinationChainId", destinationChainId.ToString() },
+ { "destinationTokenAddress", destinationTokenAddress },
+ { "buyAmountWei", buyAmountWei.ToString() }
+ };
+ url = AppendQueryParams(url, queryParams);
+
+ var response = await this._httpClient.GetAsync(url).ConfigureAwait(false);
+ _ = response.EnsureSuccessStatusCode();
+ var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var result = JsonConvert.DeserializeObject>(responseContent);
+ return result.Data;
+ }
+
+ ///
+ /// Get the transactions required to buy a specific amount of tokens on any chain, alongside the quote.
+ ///
+ /// The chain ID of the origin chain.
+ /// The address of the token on the origin chain.
+ /// The chain ID of the destination chain.
+ /// The address of the token on the destination chain.
+ /// The amount of tokens to buy in wei.
+ /// The address of the sender.
+ /// The address of the receiver.
+ /// A object representing the prepare data.
+ /// Thrown when one of the parameters is invalid.
+ public async Task Buy_Prepare(
+ BigInteger originChainId,
+ string originTokenAddress,
+ BigInteger destinationChainId,
+ string destinationTokenAddress,
+ BigInteger buyAmountWei,
+ string sender,
+ string receiver
+ )
+ {
+ if (originChainId <= 0)
+ {
+ throw new ArgumentException("originChainId cannot be less than or equal to 0", nameof(originChainId));
+ }
+
+ if (destinationChainId <= 0)
+ {
+ throw new ArgumentException("destinationChainId cannot be less than or equal to 0", nameof(destinationChainId));
+ }
+
+ if (!Utils.IsValidAddress(originTokenAddress))
+ {
+ throw new ArgumentException("originTokenAddress is not a valid address", nameof(originTokenAddress));
+ }
+
+ if (buyAmountWei <= 0)
+ {
+ throw new ArgumentException("buyAmountWei cannot be less than or equal to 0", nameof(buyAmountWei));
+ }
+
+ if (!Utils.IsValidAddress(sender))
+ {
+ throw new ArgumentException("sender is not a valid address", nameof(sender));
+ }
+
+ if (!Utils.IsValidAddress(receiver))
+ {
+ throw new ArgumentException("receiver is not a valid address", nameof(receiver));
+ }
+
+ var url = $"{Constants.BRIDGE_API_URL}/v1/buy/prepare";
+ var queryParams = new Dictionary
+ {
+ { "originChainId", originChainId.ToString() },
+ { "originTokenAddress", originTokenAddress },
+ { "destinationChainId", destinationChainId.ToString() },
+ { "destinationTokenAddress", destinationTokenAddress },
+ { "buyAmountWei", buyAmountWei.ToString() },
+ { "sender", sender },
+ { "receiver", receiver }
+ };
+ url = AppendQueryParams(url, queryParams);
+
+ var response = await this._httpClient.GetAsync(url).ConfigureAwait(false);
+ _ = response.EnsureSuccessStatusCode();
+ var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var result = JsonConvert.DeserializeObject>(responseContent);
+ return result.Data;
+ }
+
+ #endregion
+
+ #region Sell
+
+ ///
+ /// Get a quote for selling a specific amount of tokens on any chain.
+ ///
+ /// The chain ID of the origin chain.
+ /// The address of the token on the origin chain.
+ /// The chain ID of the destination chain.
+ /// The address of the token on the destination chain.
+ /// The amount of tokens to sell in wei.
+ /// A object representing the quote.
+ /// Thrown when one of the parameters is invalid.
+ public async Task Sell_Quote(BigInteger originChainId, string originTokenAddress, BigInteger destinationChainId, string destinationTokenAddress, BigInteger sellAmountWei)
+ {
+ if (originChainId <= 0)
+ {
+ throw new ArgumentException("originChainId cannot be less than or equal to 0", nameof(originChainId));
+ }
+
+ if (destinationChainId <= 0)
+ {
+ throw new ArgumentException("destinationChainId cannot be less than or equal to 0", nameof(destinationChainId));
+ }
+
+ if (!Utils.IsValidAddress(originTokenAddress))
+ {
+ throw new ArgumentException("originTokenAddress is not a valid address", nameof(originTokenAddress));
+ }
+
+ if (sellAmountWei <= 0)
+ {
+ throw new ArgumentException("sellAmountWei cannot be less than or equal to 0", nameof(sellAmountWei));
+ }
+
+ var url = $"{Constants.BRIDGE_API_URL}/v1/sell/quote";
+ var queryParams = new Dictionary
+ {
+ { "originChainId", originChainId.ToString() },
+ { "originTokenAddress", originTokenAddress },
+ { "destinationChainId", destinationChainId.ToString() },
+ { "destinationTokenAddress", destinationTokenAddress },
+ { "sellAmountWei", sellAmountWei.ToString() }
+ };
+ url = AppendQueryParams(url, queryParams);
+
+ var response = await this._httpClient.GetAsync(url).ConfigureAwait(false);
+ _ = response.EnsureSuccessStatusCode();
+ var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var result = JsonConvert.DeserializeObject>(responseContent);
+ return result.Data;
+ }
+
+ ///
+ /// Get the transactions required to sell a specific amount of tokens on any chain, alongside the quote.
+ ///
+ /// The chain ID of the origin chain.
+ /// The address of the token on the origin chain.
+ /// The chain ID of the destination chain.
+ /// The address of the token on the destination chain.
+ /// The amount of tokens to sell in wei.
+ /// The address of the sender.
+ /// The address of the receiver.
+ /// A object representing the prepare data.
+ /// Thrown when one of the parameters is invalid.
+ public async Task Sell_Prepare(
+ BigInteger originChainId,
+ string originTokenAddress,
+ BigInteger destinationChainId,
+ string destinationTokenAddress,
+ BigInteger sellAmountWei,
+ string sender,
+ string receiver
+ )
+ {
+ if (originChainId <= 0)
+ {
+ throw new ArgumentException("originChainId cannot be less than or equal to 0", nameof(originChainId));
+ }
+
+ if (destinationChainId <= 0)
+ {
+ throw new ArgumentException("destinationChainId cannot be less than or equal to 0", nameof(destinationChainId));
+ }
+
+ if (!Utils.IsValidAddress(originTokenAddress))
+ {
+ throw new ArgumentException("originTokenAddress is not a valid address", nameof(originTokenAddress));
+ }
+
+ if (sellAmountWei <= 0)
+ {
+ throw new ArgumentException("sellAmountWei cannot be less than or equal to 0", nameof(sellAmountWei));
+ }
+
+ if (!Utils.IsValidAddress(sender))
+ {
+ throw new ArgumentException("sender is not a valid address", nameof(sender));
+ }
+
+ if (!Utils.IsValidAddress(receiver))
+ {
+ throw new ArgumentException("receiver is not a valid address", nameof(receiver));
+ }
+
+ var url = $"{Constants.BRIDGE_API_URL}/v1/sell/prepare";
+ var queryParams = new Dictionary
+ {
+ { "originChainId", originChainId.ToString() },
+ { "originTokenAddress", originTokenAddress },
+ { "destinationChainId", destinationChainId.ToString() },
+ { "destinationTokenAddress", destinationTokenAddress },
+ { "sellAmountWei", sellAmountWei.ToString() },
+ { "sender", sender },
+ { "receiver", receiver }
+ };
+ url = AppendQueryParams(url, queryParams);
+
+ var response = await this._httpClient.GetAsync(url).ConfigureAwait(false);
+ _ = response.EnsureSuccessStatusCode();
+ var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var result = JsonConvert.DeserializeObject>(responseContent);
+ return result.Data;
+ }
+
+ #endregion
+
+ #region Transfer
+
+ ///
+ /// Get the transactions required to transfer a specific amount of tokens on any chain.
+ ///
+ /// The chain ID of the token.
+ /// The address of the token.
+ /// The amount of tokens to transfer in wei.
+ /// The address of the sender.
+ /// The address of the receiver.
+ /// A object representing the prepare data.
+ /// Thrown when one of the parameters is invalid.
+ public async Task Transfer_Prepare(BigInteger chainId, string tokenAddress, BigInteger transferAmountWei, string sender, string receiver)
+ {
+ if (chainId <= 0)
+ {
+ throw new ArgumentException("chainId cannot be less than or equal to 0", nameof(chainId));
+ }
+
+ if (!Utils.IsValidAddress(tokenAddress))
+ {
+ throw new ArgumentException("tokenAddress is not a valid address", nameof(tokenAddress));
+ }
+
+ if (transferAmountWei <= 0)
+ {
+ throw new ArgumentException("transferAmountWei cannot be less than or equal to 0", nameof(transferAmountWei));
+ }
+
+ if (!Utils.IsValidAddress(sender))
+ {
+ throw new ArgumentException("sender is not a valid address", nameof(sender));
+ }
+
+ if (!Utils.IsValidAddress(receiver))
+ {
+ throw new ArgumentException("receiver is not a valid address", nameof(receiver));
+ }
+
+ var url = $"{Constants.BRIDGE_API_URL}/v1/transfer/prepare";
+ var queryParams = new Dictionary
+ {
+ { "chainId", chainId.ToString() },
+ { "tokenAddress", tokenAddress },
+ { "transferAmountWei", transferAmountWei.ToString() },
+ { "sender", sender },
+ { "receiver", receiver }
+ };
+ url = AppendQueryParams(url, queryParams);
+
+ var response = await this._httpClient.GetAsync(url).ConfigureAwait(false);
+ _ = response.EnsureSuccessStatusCode();
+ var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var result = JsonConvert.DeserializeObject>(responseContent);
+ return result.Data;
+ }
+
+ #endregion
+
+ #region Status
+
+ ///
+ /// Get the status of any bridge-initiated transaction.
+ ///
+ /// The hash of the transaction.
+ /// The chain ID of the transaction.
+ /// A object representing the status.
+ /// Thrown when one of the parameters is invalid.
+ public async Task Status(string transactionHash, BigInteger chainId)
+ {
+ if (string.IsNullOrWhiteSpace(transactionHash))
+ {
+ throw new ArgumentException("transactionHash cannot be null or empty", nameof(transactionHash));
+ }
+
+ if (chainId <= 0)
+ {
+ throw new ArgumentException("chainId cannot be less than or equal to 0", nameof(chainId));
+ }
+
+ var url = $"{Constants.BRIDGE_API_URL}/v1/status";
+ var queryParams = new Dictionary { { "transactionHash", transactionHash }, { "chainId", chainId.ToString() } };
+ url = AppendQueryParams(url, queryParams);
+
+ var response = await this._httpClient.GetAsync(url).ConfigureAwait(false);
+ _ = response.EnsureSuccessStatusCode();
+ var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ var result = JsonConvert.DeserializeObject>(responseContent);
+ return result.Data;
+ }
+
+ #endregion
+
+ private static string AppendQueryParams(string url, Dictionary queryParams)
+ {
+ var query = new List();
+ foreach (var param in queryParams)
+ {
+ query.Add($"{param.Key}={param.Value}");
+ }
+
+ return url + "?" + string.Join("&", query);
+ }
+}
diff --git a/Thirdweb/Thirdweb.Pay/ThirdwebPay.cs b/Thirdweb/Thirdweb.Pay/ThirdwebPay.cs
index 7d39b97f..f493cc28 100644
--- a/Thirdweb/Thirdweb.Pay/ThirdwebPay.cs
+++ b/Thirdweb/Thirdweb.Pay/ThirdwebPay.cs
@@ -1,5 +1,6 @@
namespace Thirdweb.Pay;
+[Obsolete("This class is deprecated, please use ThirdwebBridge instead.")]
public partial class ThirdwebPay
{
private const string THIRDWEB_PAY_BASE_URL = "https://pay.thirdweb.com";
diff --git a/Thirdweb/Thirdweb.Utils/Constants.cs b/Thirdweb/Thirdweb.Utils/Constants.cs
index 4d507be9..1fbbebe3 100644
--- a/Thirdweb/Thirdweb.Utils/Constants.cs
+++ b/Thirdweb/Thirdweb.Utils/Constants.cs
@@ -4,6 +4,13 @@ public static class Constants
{
public const string VERSION = "2.18.6";
+ internal const string BRIDGE_API_URL = "https://bridge.thirdweb.com";
+ internal const string NEBULA_API_URL = "https://nebula-api.thirdweb.com";
+ internal const string INSIGHT_API_URL = "https://insight.thirdweb.com";
+ internal const string SOCIAL_API_URL = "https://social.thirdweb.com";
+ internal const string PIN_URI = "https://storage.thirdweb.com/ipfs/upload";
+ internal const string FALLBACK_IPFS_GATEWAY = "https://ipfs.io/ipfs/";
+
public const string IERC20_INTERFACE_ID = "0x36372b07";
public const string IERC721_INTERFACE_ID = "0x80ac58cd";
public const string IERC1155_INTERFACE_ID = "0xd9b67a26";
@@ -31,16 +38,10 @@ public static class Constants
internal const string DUMMY_SIG = "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c";
internal const string DUMMY_PAYMASTER_AND_DATA_HEX =
"0x0101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000001010101010100000000000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101";
- internal const string FALLBACK_IPFS_GATEWAY = "https://ipfs.io/ipfs/";
- internal const string PIN_URI = "https://storage.thirdweb.com/ipfs/upload";
internal const string ENS_REGISTRY_ADDRESS = "0xce01f8eee7E479C928F8919abD53E553a36CeF67";
- internal const string SOCIAL_API_URL = "https://social.thirdweb.com";
- internal const string NEBULA_API_URL = "https://nebula-api.thirdweb.com";
internal const string NEBULA_DEFAULT_MODEL = "t0-001";
- internal const string INSIGHT_API_URL = "https://insight.thirdweb.com";
-
internal const string ENTRYPOINT_V06_ABI =
/*lang=json,strict*/
"[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]";