From 0bb6815c9ccf95fa23e3f6722098b6497d3f8f2f Mon Sep 17 00:00:00 2001 From: Natalie Bunduwongse Date: Mon, 14 Oct 2024 21:25:58 +1300 Subject: [PATCH] refactor: marketplace --- .../Shared/Scripts/Domain/OrderbookManager.cs | 104 +++++++++++++++--- Assets/Shared/Scripts/Helpers.meta | 8 -- Assets/Shared/Scripts/Helpers/JsonHelper.cs | 38 ------- .../Shared/Scripts/Helpers/JsonHelper.cs.meta | 11 -- .../Shared/Scripts/Helpers/PollingHelper.cs | 62 ----------- .../Scripts/Helpers/PollingHelper.cs.meta | 11 -- .../Shared/Scripts/InfiniteScrollGridView.cs | 6 +- .../Shared/Scripts/Model/ListingsResponse.cs | 5 +- .../UI/Inventory/InventoryAssetDetailsView.cs | 29 ++--- .../UI/Inventory/InventoryListObject.cs | 10 +- .../Scripts/UI/Inventory/InventoryScreen.cs | 57 +++++----- .../Scripts/UI/Marketplace/ListingObject.cs | 22 ++-- .../MarketplaceAssetDetailsView.cs | 69 ++---------- .../UI/Marketplace/MarketplaceScreen.cs | 60 +++------- 14 files changed, 175 insertions(+), 317 deletions(-) delete mode 100644 Assets/Shared/Scripts/Helpers.meta delete mode 100644 Assets/Shared/Scripts/Helpers/JsonHelper.cs delete mode 100644 Assets/Shared/Scripts/Helpers/JsonHelper.cs.meta delete mode 100644 Assets/Shared/Scripts/Helpers/PollingHelper.cs delete mode 100644 Assets/Shared/Scripts/Helpers/PollingHelper.cs.meta diff --git a/Assets/Shared/Scripts/Domain/OrderbookManager.cs b/Assets/Shared/Scripts/Domain/OrderbookManager.cs index e6ed2440..75a02377 100644 --- a/Assets/Shared/Scripts/Domain/OrderbookManager.cs +++ b/Assets/Shared/Scripts/Domain/OrderbookManager.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; using Cysharp.Threading.Tasks; +using Immutable.Api.Model; using Immutable.Orderbook.Api; using Immutable.Orderbook.Client; using Immutable.Orderbook.Model; @@ -18,7 +20,7 @@ namespace HyperCasual.Runner public class OrderbookManager { private static readonly Lazy s_Instance = new(() => new OrderbookManager()); - + private readonly OrderbookApi m_OrderbookApi = new(new Configuration { BasePath = Config.BASE_URL }); private OrderbookManager() { } @@ -50,6 +52,11 @@ public async UniTask CreateListing( { try { + if (contractType == "ERC721" && amountToSell != "1") + { + throw new ArgumentException("Invalid arguments: 'amountToSell' must be '1' when listing an ERC721."); + } + var listingData = await PrepareListing(contractAddress, contractType, tokenId, price, amountToSell); await SignAndSubmitApproval(listingData); @@ -58,8 +65,7 @@ public async UniTask CreateListing( var listingId = await ListAsset(signature, listingData); - if (confirmListing) - await ConfirmListingStatus(listingId, "ACTIVE"); + if (confirmListing) await ConfirmListingStatus(listingId, "ACTIVE"); return listingId; } @@ -186,8 +192,52 @@ public async UniTask CancelListing(string listingId, bool confirmListing = true) if (txResponse.status != "1") throw new Exception("Failed to cancel listing."); - if (confirmListing) - await ConfirmListingStatus(listingId, "CANCELLED"); + if (confirmListing) await ConfirmListingStatus(listingId, "CANCELLED"); + } + catch (ApiException e) + { + HandleApiException(e); + throw; + } + } + + /// + /// Executes an order by fulfilling a listing and optionally confirming its status. + /// + /// The listing to fulfill. + /// + /// If true, the function will poll the listing endpoint to confirm that the listing status + /// has changed to "FILLED". If false, the function will not verify the listing status. + /// + public async UniTask ExecuteOrder(Listing listing, bool confirmListing = true) + { + try + { + var fees = listing.PriceDetails.Fees + .Select(fee => new FulfillOrderRequestTakerFeesInner(fee.Amount, fee.RecipientAddress)).ToList(); + + var request = new FulfillOrderRequest( + takerAddress: SaveManager.Instance.WalletAddress, + listingId: listing.ListingId, + takerFees: fees); + + var createListingResponse = await m_OrderbookApi.FulfillOrderAsync(request); + + if (createListingResponse.Actions.Count > 0) + { + foreach (var transaction in createListingResponse.Actions) + { + var transactionHash = await Passport.Instance.ZkEvmSendTransaction(new TransactionRequest + { + to = transaction.PopulatedTransactions.To, + data = transaction.PopulatedTransactions.Data, + value = "0" + }); + Debug.Log($"Transaction hash: {transactionHash}"); + } + + if (confirmListing) await ConfirmListingStatus(listing.ListingId, "FILLED"); + } } catch (ApiException e) { @@ -201,17 +251,43 @@ public async UniTask CancelListing(string listingId, bool confirmListing = true) /// private async UniTask ConfirmListingStatus(string listingId, string desiredStatus) { - var isConfirmed = await PollingHelper.PollAsync( - $"{Config.BASE_URL}/v1/chains/{Config.CHAIN_NAME}/orders/listings/{listingId}", - response => + const int timeoutDuration = 60000; // Timeout duration in milliseconds + const int pollDelay = 2000; // Delay between polls in milliseconds + + using var client = new HttpClient(); + var startTimeMs = Time.time * 1000; + var url = $"{Config.BASE_URL}/v1/chains/{Config.CHAIN_NAME}/orders/listings/{listingId}"; + + while (true) + { + if (Time.time * 1000 - startTimeMs > timeoutDuration) { - var listingResponse = JsonUtility.FromJson(response); - return listingResponse.result?.status.name == desiredStatus; - }); + Debug.Log($"Failed to confirm listing status: {desiredStatus}."); + return; + } + + try + { + var response = await client.GetAsync(url); + if (response.IsSuccessStatusCode) + { + var responseBody = await response.Content.ReadAsStringAsync(); + var listingResponse = JsonUtility.FromJson(responseBody); + + if (listingResponse.result?.status.name == desiredStatus) + { + Debug.Log($"Listing {listingId} is {desiredStatus}."); + return; + } + } + } + catch (Exception ex) + { + Debug.LogException(ex); + } - Debug.Log(isConfirmed - ? $"Listing {listingId} is {desiredStatus.ToLower()}." - : $"Failed to confirm listing status: {desiredStatus.ToLower()}."); + await UniTask.Delay(pollDelay); + } } /// diff --git a/Assets/Shared/Scripts/Helpers.meta b/Assets/Shared/Scripts/Helpers.meta deleted file mode 100644 index 50cb548c..00000000 --- a/Assets/Shared/Scripts/Helpers.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ceeefbe6611f4409b851096e9748d6d6 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Shared/Scripts/Helpers/JsonHelper.cs b/Assets/Shared/Scripts/Helpers/JsonHelper.cs deleted file mode 100644 index 95faf41b..00000000 --- a/Assets/Shared/Scripts/Helpers/JsonHelper.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using UnityEngine; - -namespace HyperCasual.Runner -{ - public static class JsonExtensions - { - public static string ToJson(this T[] array) - { - // Need a wrapper to serialise arrays - var wrapper = new Wrapper(); - wrapper.Items = array; - var wrapped = JsonUtility.ToJson(wrapper); - // Remove the wrapper - return wrapped.ReplaceFirst("{\"Items\":", "").ReplaceLast("}", ""); - } - - private static string ReplaceFirst(this string source, string search, string replace) - { - var pos = source.IndexOf(search); - if (pos < 0) return source; - return source.Substring(0, pos) + replace + source.Substring(pos + search.Length); - } - - private static string ReplaceLast(this string source, string search, string replace) - { - var place = source.LastIndexOf(search); - if (place == -1) return source; - return source.Remove(place, search.Length).Insert(place, replace); - } - - [Serializable] - public class Wrapper - { - public T[] Items; - } - } -} \ No newline at end of file diff --git a/Assets/Shared/Scripts/Helpers/JsonHelper.cs.meta b/Assets/Shared/Scripts/Helpers/JsonHelper.cs.meta deleted file mode 100644 index e860c7f6..00000000 --- a/Assets/Shared/Scripts/Helpers/JsonHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f4d7a1659ab254a0c9fa678d35dcd0d1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Shared/Scripts/Helpers/PollingHelper.cs b/Assets/Shared/Scripts/Helpers/PollingHelper.cs deleted file mode 100644 index fc038a87..00000000 --- a/Assets/Shared/Scripts/Helpers/PollingHelper.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Net.Http; -using Cysharp.Threading.Tasks; -using UnityEngine; - -namespace HyperCasual.Runner -{ - public static class PollingHelper - { - /// - /// Polls a given URL until a condition is met or the operation times out. - /// - /// The URL to poll. - /// A function that takes the response body as input and returns true if the condition is met. - /// The polling interval in milliseconds (default is 2000 ms). - /// The timeout duration in milliseconds (default is 60000 ms). - /// Returns true if the condition was met before timing out, false otherwise. - public static async UniTask PollAsync(string url, Func condition, int pollIntervalMs = 2000, - int timeoutMs = 60000) - { - using var client = new HttpClient(); - var startTimeMs = Time.time * 1000; - var conditionMet = false; - - while (!conditionMet) - { - try - { - var response = await client.GetAsync(url); - if (response.IsSuccessStatusCode) - { - var responseBody = await response.Content.ReadAsStringAsync(); - conditionMet = condition(responseBody); - } - else - { - Debug.LogWarning($"Polling received non-success status code: {response.StatusCode}"); - } - } - catch (Exception ex) - { - Debug.LogException(ex); - } - - if (conditionMet) continue; - - // Check if timeout has been reached - if (Time.time * 1000 - startTimeMs > timeoutMs) - { - Debug.LogWarning("Polling timed out."); - return false; - } - - await UniTask.Delay( - pollIntervalMs); // Wait for the specified polling interval before checking again - } - - Debug.Log("Condition met, polling completed."); - return true; - } - } -} \ No newline at end of file diff --git a/Assets/Shared/Scripts/Helpers/PollingHelper.cs.meta b/Assets/Shared/Scripts/Helpers/PollingHelper.cs.meta deleted file mode 100644 index b8941cff..00000000 --- a/Assets/Shared/Scripts/Helpers/PollingHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aa1e2656e195742b7ae78ffc98e3ed8b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Shared/Scripts/InfiniteScrollGridView.cs b/Assets/Shared/Scripts/InfiniteScrollGridView.cs index 089aa3c8..bf75d536 100644 --- a/Assets/Shared/Scripts/InfiniteScrollGridView.cs +++ b/Assets/Shared/Scripts/InfiniteScrollGridView.cs @@ -26,17 +26,17 @@ public int TotalItemCount private void Awake() { - if (!m_IsInitialised) InitializeScrollView(); + if (!m_IsInitialised) InitialiseScrollView(); } private void Start() { - if (!m_IsInitialised) InitializeScrollView(); + if (!m_IsInitialised) InitialiseScrollView(); } public event Action OnCreateItemView; // Event for item setup - private void InitializeScrollView() + private void InitialiseScrollView() { m_IsInitialised = true; m_ScrollRect.onValueChanged.AddListener(OnScroll); diff --git a/Assets/Shared/Scripts/Model/ListingsResponse.cs b/Assets/Shared/Scripts/Model/ListingsResponse.cs index a484373f..0355829a 100644 --- a/Assets/Shared/Scripts/Model/ListingsResponse.cs +++ b/Assets/Shared/Scripts/Model/ListingsResponse.cs @@ -6,13 +6,12 @@ namespace HyperCasual.Runner [Serializable] public class ListingResponse { - public OldListing result; + public ListingResult result; } [Serializable] - public class OldListing + public class ListingResult { - public string id; public ListingStatus status; } diff --git a/Assets/Shared/Scripts/UI/Inventory/InventoryAssetDetailsView.cs b/Assets/Shared/Scripts/UI/Inventory/InventoryAssetDetailsView.cs index 31d9b4ff..b6103abd 100644 --- a/Assets/Shared/Scripts/UI/Inventory/InventoryAssetDetailsView.cs +++ b/Assets/Shared/Scripts/UI/Inventory/InventoryAssetDetailsView.cs @@ -32,7 +32,7 @@ public class InventoryAssetDetailsView : View [SerializeField] private HyperCasualButton m_CancelButton; [SerializeField] private GameObject m_Progress; [SerializeField] private CustomDialog m_CustomDialog; - + private StacksApi m_StacksApi = new(new Configuration { BasePath = Config.BASE_URL }); private readonly List m_Attributes = new(); private NFTBundle? m_Asset; @@ -98,9 +98,9 @@ public async void Initialise(NFTBundle asset) attributeView.Initialise(attribute); m_Attributes.Add(attributeView); } - + UpdateListingStateAndPrice(); - + // Market data var floorListing = m_Asset!.Market?.FloorListing; m_FloorPriceText.text = floorListing != null @@ -122,7 +122,7 @@ private void UpdateListingStateAndPrice() { // Determine the listing ID based on the asset's listings m_ListingId = m_Asset!.Listings.Count > 0 ? m_Asset.Listings[0].ListingId : null; - + // Set the visibility of the sell and cancel buttons m_SellButton.gameObject.SetActive(m_ListingId == null); m_CancelButton.gameObject.SetActive(m_ListingId != null); @@ -157,7 +157,7 @@ private static decimal GetQuantity(string value) => /// private async UniTask LoadAssetImage() => await m_Image.LoadUrl(m_Asset!.NftWithStack.Image); - + /// /// Fetches the latest NFT bundle data. /// @@ -169,14 +169,17 @@ private async UniTask LoadAssetImage() => { var result = await m_StacksApi.SearchNFTsAsync( chainName: Config.CHAIN_NAME, - new List { m_Asset.NftWithStack.ContractAddress }, + contractAddress: new List { m_Asset.NftWithStack.ContractAddress }, + accountAddress: SaveManager.Instance.WalletAddress, stackId: new List { m_Asset.NftWithStack.StackId }, onlyIncludeOwnerListings: true); - - // Check if the result contains any NFT bundles + if (result.Result.Count > 0) { - return result.Result[0]; // Return the first NFT bundle + return result.Result + .Where(n => n.NftWithStack.TokenId == m_Asset.NftWithStack.TokenId) + .DefaultIfEmpty(null) + .FirstOrDefault(); } } catch (Exception ex) @@ -184,7 +187,7 @@ private async UniTask LoadAssetImage() => Debug.LogError($"Failed to fetch NFT bundle data: {ex.Message}"); } - return null; // Return null if fetching fails or no data is available + return null; } /// @@ -253,7 +256,7 @@ private async void OnSellButtonClicked() var nftBundle = await GetNftBundle(); if (nftBundle != null) { - m_Asset.Listings.AddRange(nftBundle.Listings); + m_Asset.Listings = new List { nftBundle.Listings[0] }; } } catch (Exception ex) @@ -292,7 +295,7 @@ private async void OnCancelButtonClicked() await HandleError(ex, "Failed to cancel listing"); } } - + private async UniTask HandleError(Exception ex, string errorMessage) { Debug.LogException(ex); @@ -307,7 +310,7 @@ private void ClearAttributes() foreach (var attribute in m_Attributes) Destroy(attribute.gameObject); m_Attributes.Clear(); } - + private void OnDisable() { m_NameText.text = ""; diff --git a/Assets/Shared/Scripts/UI/Inventory/InventoryListObject.cs b/Assets/Shared/Scripts/UI/Inventory/InventoryListObject.cs index 4a3d88a9..e2d6d4cd 100644 --- a/Assets/Shared/Scripts/UI/Inventory/InventoryListObject.cs +++ b/Assets/Shared/Scripts/UI/Inventory/InventoryListObject.cs @@ -1,3 +1,4 @@ +using System.Linq; using System.Numerics; using Immutable.Api.Model; using TMPro; @@ -11,7 +12,6 @@ namespace HyperCasual.Runner public class InventoryListObject : MonoBehaviour { [SerializeField] private TextMeshProUGUI m_NameText; - [SerializeField] private TextMeshProUGUI m_TokenIdText; [SerializeField] private TextMeshProUGUI m_AmountText; [SerializeField] private ImageUrlObject m_Image; @@ -40,7 +40,7 @@ private void UpdateUI() if (m_NFT == null) return; // Display the asset name based on its contract type. - m_NameText.text = m_NFT.NftWithStack.ContractType.ToUpper() switch + m_NameText.text = m_NFT?.NftWithStack.ContractType.ToUpper() switch { "ERC721" => $"{m_NFT.NftWithStack.Name} #{m_NFT.NftWithStack.TokenId}", "ERC1155" => $"{m_NFT.NftWithStack.Name} x{m_NFT.NftWithStack.Balance}", @@ -71,5 +71,11 @@ private void UpdateUI() m_Image.LoadUrl(m_NFT.NftWithStack.Image); #pragma warning restore CS4014 } + + private void OnDisable() + { + m_NameText.text = ""; + m_AmountText.text = ""; + } } } \ No newline at end of file diff --git a/Assets/Shared/Scripts/UI/Inventory/InventoryScreen.cs b/Assets/Shared/Scripts/UI/Inventory/InventoryScreen.cs index b0a50dde..68b184b4 100644 --- a/Assets/Shared/Scripts/UI/Inventory/InventoryScreen.cs +++ b/Assets/Shared/Scripts/UI/Inventory/InventoryScreen.cs @@ -36,25 +36,18 @@ public enum AssetType { Skin, Powerups } private void OnEnable() { m_InventoryObj.gameObject.SetActive(false); - ConfigureButtons(); - ConfigureFilters(); - - m_ScrollView.OnCreateItemView += OnCreateItemView; - - if (!m_Assets.Any()) LoadAssets(); - m_Balance.UpdateBalance(); - } - /// - /// Configures the back and add buttons with their respective listeners. - /// - private void ConfigureButtons() - { m_BackButton.RemoveListener(OnBackButtonClick); m_BackButton.AddListener(OnBackButtonClick); - m_AddButton.RemoveListener(OnAddFundsButtonClick); m_AddButton.AddListener(OnAddFundsButtonClick); + + m_ScrollView.OnCreateItemView += OnCreateItemView; + if (m_Assets.Count == 0) LoadAssets(); + + ConfigureFilters(); + + m_Balance.UpdateBalance(); } /// @@ -75,36 +68,36 @@ private void ConfigureFilters() } /// - /// Handles the creation of each item in the inventory list. + /// Configures each item view in the inventory list. /// /// The index of the asset in the list. /// The game object representing the asset view. private void OnCreateItemView(int index, GameObject item) { - if (index >= m_Assets.Count) return; - - var asset = m_Assets[index]; - var itemComponent = item.GetComponent(); - itemComponent.Initialise(asset); - - var clickable = item.GetComponent(); - if (clickable != null) + if (index < m_Assets.Count) { - clickable.ClearAllSubscribers(); - clickable.OnClick += () => + var asset = m_Assets[index]; + var itemComponent = item.GetComponent(); + itemComponent.Initialise(asset); + + var clickable = item.GetComponent(); + if (clickable != null) { - var view = UIManager.Instance.GetView(); - UIManager.Instance.Show(view); - view.Initialise(asset); - }; + clickable.ClearAllSubscribers(); + clickable.OnClick += () => + { + var view = UIManager.Instance.GetView(); + UIManager.Instance.Show(view); + view.Initialise(asset); + }; + } } - if (index >= m_Assets.Count - 8 && !m_IsLoadingMore) - LoadAssets(); + if (index >= m_Assets.Count - 8 && !m_IsLoadingMore) LoadAssets(); } /// - /// Loads the player's assets and adds them to the inventory view. + /// Loads the player's assets and adds them to the scroll view /// private async void LoadAssets() { diff --git a/Assets/Shared/Scripts/UI/Marketplace/ListingObject.cs b/Assets/Shared/Scripts/UI/Marketplace/ListingObject.cs index 1f97ffed..da9f5cbd 100644 --- a/Assets/Shared/Scripts/UI/Marketplace/ListingObject.cs +++ b/Assets/Shared/Scripts/UI/Marketplace/ListingObject.cs @@ -24,17 +24,6 @@ public class ListingObject : View private Listing m_Listing; private Func> m_OnBuy; - /// - /// Clears any displayed listing data when the object is disabled. - /// - private void OnDisable() - { - m_TokenIdText.text = string.Empty; - m_PriceText.text = string.Empty; - m_AmountText.text = string.Empty; - m_Listing = null; - } - /// /// Initialises the UI with the given listing details. /// @@ -88,5 +77,16 @@ private async void OnBuyButtonClick() m_BuyButton.gameObject.SetActive(!success); m_Progress.SetActive(false); } + + /// + /// Clears any displayed listing data when the object is disabled. + /// + private void OnDisable() + { + m_TokenIdText.text = string.Empty; + m_PriceText.text = string.Empty; + m_AmountText.text = string.Empty; + m_Listing = null; + } } } diff --git a/Assets/Shared/Scripts/UI/Marketplace/MarketplaceAssetDetailsView.cs b/Assets/Shared/Scripts/UI/Marketplace/MarketplaceAssetDetailsView.cs index 491562cc..0a620d72 100644 --- a/Assets/Shared/Scripts/UI/Marketplace/MarketplaceAssetDetailsView.cs +++ b/Assets/Shared/Scripts/UI/Marketplace/MarketplaceAssetDetailsView.cs @@ -169,48 +169,20 @@ private void ClearListings() } /// - /// Handles the buy button click event. Sends a request to fulfil an order, - /// processes the response, and updates the UI accordingly. + /// Handles the buy button click event. /// private async UniTask OnBuyButtonClick(Listing listing) { try { - var fees = listing.PriceDetails.Fees - .Select(fee => new FulfillOrderRequestTakerFeesInner - ( - fee.Amount, - fee.RecipientAddress - )).ToList(); - var request = new FulfillOrderRequest( - takerAddress: SaveManager.Instance.WalletAddress, - listingId: listing.ListingId, - takerFees: fees); - var createListingResponse = await m_OrderbookApi.FulfillOrderAsync(request); + await OrderbookManager.Instance.ExecuteOrder(listing); - if (createListingResponse.Actions.Count > 0) - { - foreach (var transaction in createListingResponse.Actions) - { - var transactionHash = await Passport.Instance.ZkEvmSendTransaction(new TransactionRequest - { - to = transaction.PopulatedTransactions.To, // Immutable seaport contract - data = transaction.PopulatedTransactions.Data, // 87201b41 fulfillAvailableAdvancedOrders - value = "0" - }); - Debug.Log($"Transaction hash: {transactionHash}"); - } + m_Balance.UpdateBalance(); - // Validate that order is fulfilled - await ConfirmListingStatus(); - m_Balance.UpdateBalance(); // Update user's balance on successful buy + // Locally update stack listing + m_Order.Listings.RemoveAll(l => l.ListingId == listing.ListingId); - // Locally update stack listing - var listingToRemove = m_Order.Listings.FirstOrDefault(l => l.ListingId == listing.ListingId); - if (listingToRemove != null) m_Order.Listings.Remove(listingToRemove); - - return true; - } + return true; } catch (ApiException e) { @@ -229,33 +201,6 @@ private async UniTask OnBuyButtonClick(Listing listing) return false; } - /// - /// Polls the order status until it transitions to FULFILLED or the operation times out after 1 minute. - /// - private async UniTask ConfirmListingStatus() - { - Debug.Log("Confirming order is filled..."); - - var conditionMet = await PollingHelper.PollAsync( - $"{Config.BASE_URL}/v1/chains/{Config.CHAIN_NAME}/orders/listings/{m_Order.Listings[0].ListingId}", - responseBody => - { - var listingResponse = JsonUtility.FromJson(responseBody); - return listingResponse.result?.status.name == "FILLED"; - }); - - if (conditionMet) - await m_CustomDialog.ShowDialog("Success", "Order is filled.", "OK"); - else - await m_CustomDialog.ShowDialog("Error", "Failed to confirm if order is filled.", "OK"); - } - - /// - /// Handles the back button click - /// - private void OnBackButtonClick() - { - UIManager.Instance.GoBack(); - } + private void OnBackButtonClick() => UIManager.Instance.GoBack(); } } \ No newline at end of file diff --git a/Assets/Shared/Scripts/UI/Marketplace/MarketplaceScreen.cs b/Assets/Shared/Scripts/UI/Marketplace/MarketplaceScreen.cs index cd0be01b..e9e311cf 100644 --- a/Assets/Shared/Scripts/UI/Marketplace/MarketplaceScreen.cs +++ b/Assets/Shared/Scripts/UI/Marketplace/MarketplaceScreen.cs @@ -23,82 +23,55 @@ public class MarketplaceScreen : View private static readonly List s_Speeds = new() { "All", "Slow", "Medium", "Fast" }; - // Back button and its event [SerializeField] private HyperCasualButton m_BackButton; [SerializeField] private AbstractGameEvent m_BackEvent; - - // Player's balance display [SerializeField] private BalanceObject m_Balance; - - // Dropdown filters for colours and speeds [SerializeField] private TMP_Dropdown m_ColoursDropdown; [SerializeField] private TMP_Dropdown m_SpeedDropdown; - - // Infinite scrolling list of stacks [SerializeField] private InfiniteScrollGridView m_ScrollView; - - // Template for displaying a stack [SerializeField] private MarketplaceListObject m_StackObj; - private StacksApi m_StacksApi; - - // List to store the loaded stacks + private StacksApi m_StacksApi = new StacksApi(new Configuration { BasePath = Config.BASE_URL }); private readonly List m_Stacks = new(); - - // Pagination and loading state private bool m_IsLoadingMore; private Page m_Page; - public MarketplaceScreen() - { - var config = new Configuration { BasePath = Config.BASE_URL }; - m_StacksApi = new StacksApi(config); - } - /// - /// Resets the marketplace view, clearing the current stacks and resetting pagination. + /// Resets the marketplace view, clearing the current stacks and resetting pagination. /// private void Reset() { m_Stacks.Clear(); m_Page = null; - - // Reset the scroll view m_ScrollView.TotalItemCount = 0; m_ScrollView.Clear(); } /// - /// Sets up the marketplace screen and loads initial stacks. + /// Sets up the marketplace screen and loads initial stacks. /// private void OnEnable() { - // Hide the stack template m_StackObj.gameObject.SetActive(false); - // Attach back button listener m_BackButton.RemoveListener(OnBackButtonClick); m_BackButton.AddListener(OnBackButtonClick); if (Passport.Instance == null) return; - // Set up the infinite scroll view and load stacks m_ScrollView.OnCreateItemView += OnCreateItemView; if (m_Stacks.Count == 0) LoadStacks(); - // Initialise dropdown filters - SetupFilters(); + ConfigureFilters(); - // Update player's balance m_Balance.UpdateBalance(); } /// - /// Configures the dropdown filters for colours and speeds. + /// Configures the dropdown filters for colours and speeds. /// - private void SetupFilters() + private void ConfigureFilters() { - // Set up colour dropdown m_ColoursDropdown.ClearOptions(); m_ColoursDropdown.AddOptions(s_Colours); m_ColoursDropdown.value = 0; // Default to "All" @@ -108,7 +81,6 @@ private void SetupFilters() LoadStacks(); }); - // Set up speed dropdown m_SpeedDropdown.ClearOptions(); m_SpeedDropdown.AddOptions(s_Speeds); m_SpeedDropdown.value = 0; // Default to "All" @@ -120,21 +92,19 @@ private void SetupFilters() } /// - /// Configures each item view in the stack list. + /// Configures each item view in the stack list. /// /// Index of the item in the stack list. - /// GameObject representing the item view. + /// The game object representing the item view. private void OnCreateItemView(int index, GameObject item) { if (index < m_Stacks.Count) { var stack = m_Stacks[index]; - // Initialise the item view with the stack data var itemComponent = item.GetComponent(); itemComponent.Initialise(stack); - // Set up click handling for the item var clickable = item.GetComponent(); if (clickable != null) { @@ -148,12 +118,11 @@ private void OnCreateItemView(int index, GameObject item) } } - // Load more stacks if nearing the end of the list if (index >= m_Stacks.Count - 8 && !m_IsLoadingMore) LoadStacks(); } /// - /// Loads stacks and adds them to the scroll view. + /// Loads stacks and adds them to the scroll view. /// private async void LoadStacks() { @@ -161,7 +130,6 @@ private async void LoadStacks() m_IsLoadingMore = true; - // Fetch the next set of stacks var stacks = await GetStacks(); if (stacks != null && stacks.Count > 0) { @@ -173,22 +141,20 @@ private async void LoadStacks() } /// - /// Fetches the list of stacks from the API. + /// Fetches the list of stacks from the API. /// - /// List of StackBundle objects representing the stacks. + /// List of stacks. private async UniTask> GetStacks() { Debug.Log("Fetching stacks..."); - var stacks = new List(); - try { var nextCursor = m_Page?.NextCursor ?? null; if (m_Page != null && string.IsNullOrEmpty(nextCursor)) { Debug.Log("No more assets to load"); - return stacks; + return new List(); } // Filter based on dropdown selections @@ -230,7 +196,7 @@ private async UniTask> GetStacks() Debug.LogError($"Error fetching stacks: {ex.Message}"); } - return stacks; + return new List(); } ///