From 0af697a76e4a25496a2facb4ca4a2bb8a9400e5c Mon Sep 17 00:00:00 2001 From: Quinn Purdy Date: Thu, 12 Dec 2024 14:25:48 -0500 Subject: [PATCH 1/4] Added smart swap docs for Unity --- docs/pages/sdk/unity/currency-swaps.mdx | 48 +++++++++++++++++++++++++ nav.ts | 1 + 2 files changed, 49 insertions(+) create mode 100644 docs/pages/sdk/unity/currency-swaps.mdx diff --git a/docs/pages/sdk/unity/currency-swaps.mdx b/docs/pages/sdk/unity/currency-swaps.mdx new file mode 100644 index 00000000000..93b4167038d --- /dev/null +++ b/docs/pages/sdk/unity/currency-swaps.mdx @@ -0,0 +1,48 @@ +# Currency Swaps + +Swapping between different ERC20/native token currencies on a given Chain is made easy by Sequence's Smart Swap API. + +## GetSwapPrice + +This method can be used to get the current `SwapPrice` for a given buyCurrency and buyAmount using a given sellCurrency. + +``` +ISwap swapper = new CurrencySwap(_chain); +SwapPrice swapPrice = await swapper.GetSwapPrice(buyCurrencyTokenAddress, usdcAddress, "1000"); // where USDC is an example sell currency +``` +You can optionally subscribe to the `OnSwapPriceReturn` and `OnSwapPriceError` events in order to handle the response elsewhere. + +You can optionally provide a maximum allowable slippagePercentage. + +## GetSwapPrices + +This method is similar to `GetSwapPrice`, it can be used to get the current `SwapPrice` for a given buyCurrency and buyAmount. Except, instead of providing a sellCurrency, you instead provide the user's wallet address. + +This method will detect the eligible currencies (ERC20s or native tokens) that can be swapped for buyAmount of the buyCurrency and will return a `SwapPrice[]`. + +``` +ISwap swapper = new CurrencySwap(_chain); +SwapPrice[] swapPrices = await swapper.GetSwapPrices(userWalletAddress, buyCurrencyTokenAddress, "1000"); +``` +You can optionally subscribe to the `OnSwapPricesReturn` and `OnSwapPricesError` events in order to handle the response elsewhere. + +You can optionally provide a maximum allowable slippagePercentage. + +## GetSwapQuote + +This method is used to get an executable `SwapQuote` for a given userWallet address to buy buyAmount of buyCurrency using sellCurrency. + +``` +ISwap swapper = new CurrencySwap(_chain); +SwapQuote quote = await swapper.GetSwapQuote(userWalletAddress, buyCurrencyTokenAddess, usdcAddress, "1000", true); // where USDC is an example sell currency +``` + +Once you've obtained a `SwapQuote`, you can transform it into a `Transaction[]` that can be submitted via your EmbeddedWallet to execute the swap. + +``` +Transaction[] swapTransactions = quote.AsTransactionArray(); + +_wallet.SendTransaction(_chain, swapTransactions); +``` + +If `includeApprove = true` the SwapQuote response will also include the information required to create the required spend approval transaction(s). These will also be added to the `Transaction[]` created above via `SwapQuote.AsTransactionArray()`. As usual, with our embedded smart contract wallets, all of these transactions can be submitted at once in a bundle; significantly improving the UX for your players who would usually need to make separate transactions to approve and swap. \ No newline at end of file diff --git a/nav.ts b/nav.ts index b8ad0b990fd..b8546e16ec4 100644 --- a/nav.ts +++ b/nav.ts @@ -662,6 +662,7 @@ export const sidebar = { { text: 'Session Management', link: '/sdk/unity/session-management' }, { text: 'On-Ramp Funds via Credit Card', link: '/sdk/unity/onboard-user-funds' }, { text: 'Marketplace', link: '/sdk/unity/marketplace' }, + { text: 'Currency Swaps', link: '/sdk/unity/currency-swaps' }, { text: 'Connect with External Wallets', link: '/sdk/unity/connecting-external-wallets', From 8f960a5061938c9ef5b55042215a908427de83bd Mon Sep 17 00:00:00 2001 From: Quinn Purdy Date: Thu, 12 Dec 2024 15:46:32 -0500 Subject: [PATCH 2/4] Added docs for marketplace beta --- 404.html | 3 +- docs/pages/sdk/unity/marketplace.mdx | 19 --- .../sdk/unity/marketplace/filling-orders.mdx | 50 +++++++ docs/pages/sdk/unity/marketplace/intro.mdx | 40 +++++ .../sdk/unity/marketplace/reading-orders.mdx | 138 ++++++++++++++++++ nav.ts | 10 +- 6 files changed, 239 insertions(+), 21 deletions(-) delete mode 100644 docs/pages/sdk/unity/marketplace.mdx create mode 100644 docs/pages/sdk/unity/marketplace/filling-orders.mdx create mode 100644 docs/pages/sdk/unity/marketplace/intro.mdx create mode 100644 docs/pages/sdk/unity/marketplace/reading-orders.mdx diff --git a/404.html b/404.html index 0d989c22ed0..822c1f5eb85 100644 --- a/404.html +++ b/404.html @@ -224,7 +224,8 @@

Page Not Found

{ oldpath: "/solutions/wallets/embedded-wallet/examples/validation", targetPath: "/solutions/wallets/embedded-wallet/examples/manage-sessions#session-management" }, { oldpath: "/sdk/unreal/authentication", targetPath: "/sdk/unreal/authentication/intro" }, { oldpath: "/guide/unity-guide", targetPath: "guide/jelly-forest-unity-guide"}, - { oldpath: "/solutions/payments/onramps/fiat-on-ramps", targetPath: "/solutions/monetization-overview"} + { oldpath: "/solutions/payments/onramps/fiat-on-ramps", targetPath: "/solutions/monetization-overview"}, + { oldpath: "/sdk/unity/marketplace", targetPath: "/sdk/unity/marketplace/intro" } ]; var currentPath = window.location.pathname; diff --git a/docs/pages/sdk/unity/marketplace.mdx b/docs/pages/sdk/unity/marketplace.mdx deleted file mode 100644 index a82b9017691..00000000000 --- a/docs/pages/sdk/unity/marketplace.mdx +++ /dev/null @@ -1,19 +0,0 @@ -# Marketplace - -In order to support the buying and selling of in-game assets between players, our Unity SDK leverages our [Marketplace API](/solutions/marketplaces/orderbook/overview). - -## Show Listings - -In order to show the marketplace listings for a given contract/collection address, you'll want to use a `ListCollectibles` object and call the `ListAllCollectiblesWithLowestListing` function or `ListCollectiblesWithLowestListing` if you want to handle pagination yourself. - -```csharp -ListCollectibles listCollectiblesOnArbitrumNova = new ListCollectibles(Chain.ArbitrumNova); -ListCollectiblesWithLowestListingReturn result = await listCollectiblesOnArbitrumNova.ListCollectiblesWithLowestListing(contractAddressString, collectiblesFilter); -CollectibleOrder[] collectibleOrders = result.collectibles; -// or -CollectibleOrder[] collectibleOrders = await listCollectiblesOnArbitrumNova.ListAllCollectiblesWithLowestListing(contractAddressString, collectiblesFilter); -``` - -where collectiblesFilter is a `CollectiblesFilter` used to filter your search criteria. - -These methods can be awaited directly or you can subscribe to the `ListCollectiblesWithLowestListingReturn` and `OnListCollectiblesWithLowestListingError` events to receive the `ListCollectiblesWithLowestListingReturn` object when successful or the error message string when unsuccessful. \ No newline at end of file diff --git a/docs/pages/sdk/unity/marketplace/filling-orders.mdx b/docs/pages/sdk/unity/marketplace/filling-orders.mdx new file mode 100644 index 00000000000..e6615ec3f42 --- /dev/null +++ b/docs/pages/sdk/unity/marketplace/filling-orders.mdx @@ -0,0 +1,50 @@ +# Filling Orders + +In order to fill an order (partially or completely) or to cancel an order, you'll be generating and submitting transactions. + +The `ICheckout` interface, implemented by `Checkout`, exposes a few helpful methods and events. + +## Building Transactions to Interact with Orders + +The following async requests will return a `Step[]` these are used to generate transactions that, when submitted, perform the desired action. + +``` +Step[] steps = await ; +TransactionReturn result = await steps.SubmitAsTransactions(_wallet, _chain); +// or +Transaction[] stepTransactions = steps.AsTransactionArray(); +``` + +All of these methods can be awaited directly. You can also subscribe to the `OnTransactionStepsReturn` and `OnTransactionStepsError` events to handle the responses elsewhere. + +1. `GenerateBuyTransaction` is used to buy a specified amount of a given collectible in the provided `Order`/listing +``` +ICheckout checkout = new Checkout(_wallet, _chain); +Step[] steps = await checkout.GenerateBuyTransaction(listing, 5); +``` + +2. `GenerateSellTransaction` is used to sell a specified amount for a given collectible in the provided `Order`/offer +``` +ICheckout checkout = new Checkout(_wallet, _chain); +Step[] steps = await checkout.GenerateSellTransaction(offer, 3); +``` + +3. `GenerateListingTransaction` is used to create a new listing for a given collectible, amount, and price. +``` +ICheckout checkout = new Checkout(_wallet, _chain); +Step[] steps = await checkout.GenerateListingTransaction(collectionContractAddress, tokenId, 17, ContractType.ERC1155, currencyTokenAddress, 1000, expiryDateTime); +``` + +4. `GenerateOfferTransaction` is used to create a new offer for a given collectible, amount, and price. +``` +ICheckout checkout = new Checkout(_wallet, _chain); +Step[] steps = await checkout.GenerateOfferTransaction(collectionContractAddress, tokenId, 46, ContractType.ERC1155, currencyTokenAddress, 850, expiryDateTime); +``` + +5. `GenerateCancelTransaction` is used to cancel an existing order created by the user. +``` +ICheckout checkout = new Checkout(_wallet, _chain); +Step[] steps = await checkout.GenerateCancelTransaction(collectionContractAddress, order); +// Or alternatively provide the order id +Step[] steps = await checkout.GenerateCancelTransaction(collectionContractAddress, orderIdString); +``` \ No newline at end of file diff --git a/docs/pages/sdk/unity/marketplace/intro.mdx b/docs/pages/sdk/unity/marketplace/intro.mdx new file mode 100644 index 00000000000..e87fa4abb94 --- /dev/null +++ b/docs/pages/sdk/unity/marketplace/intro.mdx @@ -0,0 +1,40 @@ +# Peer to Peer Trading - Intro + +Peer to Peer Trading is facilitated by our [Marketplace API](/api/marketplace/overview). + +Users will be able to purchase and sell ERC721/1155s between one another via the marketplace SDK in Unity; paying in cryptocurrency (with currency abstraction enabled by default) or via credit card where available (coming soon!). + +## Installation + +The V4 version of our SDK is currently in beta and maintained on a separate branch. We are eagerly looking for feedback on this new major update for the SDK, so please get in touch with us! + +Please [install via Package Manager with Git URL](/sdk/unity/installation#or-using-package-manager-ui): + +`https://github.com/0xsequence/sequence-unity.git?path=/Packages/Sequence-Unity#v4-beta` + +If you already have the Sequence Unity SDK installed in your project, you will likely need to remove it. + +## Understanding the Basics + +Before diving into the details behind the marketplace, let's first establish an understanding of some basic concepts. + +### Orders + +There are two basic types of Orders: listings and offers. + +Listings indicate an intent to sell a given amount of a collectible (where a collectible is the combination of a Chain, contract address, and token id) at a certain price per collectible in a given Currency. Once created, listings can be queried and bought by another user. +Offers indicate an intent to purchase a given amount of a collectible at a certain price per collectible in a given Currency. Once created, offers can be queried and sold by another user. + +In order to create, fill, or cancel an Order, you must use the appropriate Generate_Method_Transaction call based on which method you are using. This will give you a `Step[]` that can be submitted as a transaction in order to perform the desired action. More on this in the [Filling Orders section](/sdk/unity/marketplace/filling-orders) of the docs. + +### Currencies +A Currency is an ERC20 token or native token that has been whitelisted for a given project and Chain for use in the marketplace. You can add a new currency to the whitelist for you project by adding it as a custom currency when creating a white-label marketplace in the Sequence Builder. Please see [this guide](http://localhost:5173/solutions/marketplaces/white-label-marketplace/guide#add-a-custom-currency). All orders must be priced in whitelisted currencies or they will be ignored by the API. + +### Collections + +A Collection is a group of Collectibles, identified by an ERC721 or ERC1155 contract address. + +### Collectibles + +A Collectible is a specific instance of a Collection, identified by the ERC721/ERC1155 contract address and the token id. + diff --git a/docs/pages/sdk/unity/marketplace/reading-orders.mdx b/docs/pages/sdk/unity/marketplace/reading-orders.mdx new file mode 100644 index 00000000000..9523508c3fe --- /dev/null +++ b/docs/pages/sdk/unity/marketplace/reading-orders.mdx @@ -0,0 +1,138 @@ +# Reading Orders + +Reading orders from the marketplace API is done with the `IMarketplaceReader` interface, implemented by `MarketplaceReader`. + +The IMarketplaceReader interface has IntelliSense summaries to help you understand what each method is used for, but, we'll call out a few of them here as well. + +## Usage + +All IMarketplaceReader methods are asynchronous Tasks and can be awaited directly and/or you can subscribe to the associated events. + +## Methods + +### ListCurrencies + +Fetch an array of whitelisted [Currencies](/sdk/unity/marketplace/intro#currencies) that can be used in your game's marketplace. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); + +// optionally subscribe to callback events +reader.OnListCurrenciesReturn += OnCurrenciesFetched; +reader.OnListCurrenciesError += OnCurrencyFetchError; + +Currency[] currencies = await reader.ListCurrencies(); +// or if only listening to event handlers +reader.ListCurrencies(); +... + + +private void OnCurrenciesFetched(Currency[] fetchedCurrencies) { + // Do something +} + +private void OnCurrencyFetchError(string error) { + // Do something +} +``` + +### Fetching Listings + +There are a few different ways to fetch listings. + +1. `ListCollectibleListingsWithLowestPricedListingsFirst` is used to get the listings associated with a given contract address. The listings will be ordered with the lowest priced listings first. In addition, only the lowest priced listing for each collectible (i.e. each token id) will be returned. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +ListCollectiblesReturn collectiblesReturn = await reader.ListCollectibleListingsWithLowestPricedListingsFirst(myCollectionContractAddress); +CollectibleOrder[] orders = collectiblesReturn.collectibles; +``` +Optionally, you can provide a `CollectiblesFilter` to apply filters on your query. + +This request uses pagination. If you're dealing with a rather small collection and don't want to deal with pagination, you can use the `ListAllCollectibleListingsWithLowestPricedListingsFirst` helper function; this will handle the pagination for you and continue to make requests until all the relevant `CollectibleOrder`s have been retrieved. + +You can also optionally subscribe to the `OnListCollectibleOrdersReturn` and `OnListCollectibleOrdersError` events in order to handle the responses elsewhere. + +2. `GetLowestPriceListingForCollectible` and `GetHighestPriceListingForCollectible` can be used to fetch the lowest and highest priced listing for a collectible respectively. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +Order lowestPricedListing = await reader.GetLowestPriceListingForCollectible(collectionContractAddress, tokenId); +Order highestPricedListing = await reader.GetHighestPriceListingForCollectible(collectionContractAddress, tokenId); +``` +Optionally, you can provide an `OrderFilter` to apply filters on your query. + +Additionally, you have the option to subscribe to the `OnGetCollectibleOrderReturn` and `OnGetCollectibleOrderError` events in order to handle the response elsewhere. + +3. `ListListingsForCollectible` is used to get all of the listings for a given Collectible. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +ListCollectibleListingsReturn listingsReturn = await reader.ListListingsForCollectible(collectionContractAddress, tokenId); +Order[] listings = listingsReturn.listings; +``` +Optionally, you can provide an `OrderFilter` to apply filters on your query. + +This request uses pagination. If you're dealing with a rather small set of listings and don't want to deal with pagination, you can use the `ListAllListingsForCollectible` helper function; this will handle the pagination for you and continue to make requests until all the relevant `Order`s have been retrieved. + +Additionally, you have the option to subscribe to the `OnListCollectibleListingsReturn` and `OnListCollectibleListingsError` events in order to handle the response elsewhere. + +4. `ListAllPurchasableListings` is a convenience helper method that can be used to `ListAllCollectibleListingsWithLowestPricedListingsFirst`, filtering for listings not created by `purchasableBy`. Then, using a `ChainIndexer` for the configured Chain to fetch `purchasableBy`'s token balances and removing any listings they cannot afford to purchase without swapping. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +CollectibleOrder[] purchasableListings = await reader.ListAllPurchasableListings(userWalletAddress, collectionContractAddress); +``` + +This method will handle pagination for you, continuing to make requests until all `CollectibleOrder`s have been fetched. Be careful to use it on collections with a small amount of listings (as with other helper methods that handle pagination for you) so that you do not use too much memory. This method's implementation can also serve as an example for how you can work with the [Indexer](/sdk/unity/read-from-blockchain) in conjunction with the peer to peer marketplaces. + +### Fetching Offers + +There are a few different ways to fetch offers. They all function similarly to their listing-equivalent methods. + +1. `ListCollectibleOffersWithHighestPricedOfferFirst` is used to get the offers associated with a given contract address. The listings will be ordered with the highest priced offer first. In addition, only the highest priced offer for each collectible (i.e. each token id) will be returned. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +ListCollectiblesReturn collectiblesReturn = await reader.ListCollectibleOffersWithHighestPricedOfferFirst(myCollectionContractAddress); +CollectibleOrder[] orders = collectiblesReturn.collectibles; +``` +Optionally, you can provide a `CollectiblesFilter` to apply filters on your query. + +This request uses pagination. If you're dealing with a rather small collection and don't want to deal with pagination, you can use the `ListAllCollectibleOffersWithHighestPricedOfferFirst` helper function; this will handle the pagination for you and continue to make requests until all the relevant `CollectibleOrder`s have been retrieved. + +You can also optionally subscribe to the `OnListCollectibleOrdersReturn` and `OnListCollectibleOrdersError` events in order to handle the responses elsewhere. + +2. `GetLowestPriceOfferForCollectible` and `GetHighestPriceOfferForCollectible` can be used to fetch the lowest and highest priced offer for a collectible respectively. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +Order lowestPricedOffer = await reader.GetLowestPriceOfferForCollectible(collectionContractAddress, tokenId); +Order highestPricedOffer = await reader.GetHighestPriceOfferForCollectible(collectionContractAddress, tokenId); +``` +Optionally, you can provide an `OrderFilter` to apply filters on your query. + +Additionally, you have the option to subscribe to the `OnGetCollectibleOrderReturn` and `OnGetCollectibleOrderError` events in order to handle the response elsewhere. + +3. `ListOffersForCollectible` is used to get all of the offers for a given Collectible. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +ListCollectibleOffersReturn offersReturn = await reader.ListOffersForCollectible(collectionContractAddress, tokenId); +Order[] offers = offersReturn.offers; +``` +Optionally, you can provide an `OrderFilter` to apply filters on your query. + +This request uses pagination. If you're dealing with a rather small set of offers and don't want to deal with pagination, you can use the `ListAllOffersForCollectible` helper function; this will handle the pagination for you and continue to make requests until all the relevant `Order`s have been retrieved. + +Additionally, you have the option to subscribe to the `OnListCollectibleOffersReturn` and `OnListCollectibleOffersError` events in order to handle the response elsewhere. + +4. `ListAllSellableOffers` is a convenience helper method that can be used to `ListAllCollectibleOffersWithHighestPricedOfferFirst`, filtering for offers not created by `sellableBy` and where `sellableBy` has at least one of the collectibles being requested. + +``` +IMarketplaceReader reader = new MarketplaceReader(_chain); +CollectibleOrder[] sellableOffers = await reader.ListAllSellableOffers(userWalletAddress, collectionContractAddress); +``` + +This method will handle pagination for you, continuing to make requests until all `CollectibleOrder`s have been fetched. Be careful to use it on collections with a small amount of offers (as with other helper methods that handle pagination for you) so that you do not use too much memory. This method's implementation can also serve as an example for how you can work with `CollectiblesFilter`s. + diff --git a/nav.ts b/nav.ts index b8546e16ec4..4e2f57a21b1 100644 --- a/nav.ts +++ b/nav.ts @@ -661,7 +661,15 @@ export const sidebar = { { text: 'Recovering Sessions', link: '/sdk/unity/recovering-sessions' }, { text: 'Session Management', link: '/sdk/unity/session-management' }, { text: 'On-Ramp Funds via Credit Card', link: '/sdk/unity/onboard-user-funds' }, - { text: 'Marketplace', link: '/sdk/unity/marketplace' }, + { + text: 'Peer to Peer Trading / Marketplace', + collapsed: false, + items: [ + { text: 'Introduction', link: '/sdk/unity/marketplace/intro' }, + { text: 'Reading Orders', link: '/sdk/unity/marketplace/reading-orders' }, + { text: 'Filling Orders', link: '/sdk/unity/marketplace/filling-orders' }, + ] + }, { text: 'Currency Swaps', link: '/sdk/unity/currency-swaps' }, { text: 'Connect with External Wallets', From 0e220e95c5b76a177ecf12018278b94d9cc55599 Mon Sep 17 00:00:00 2001 From: Quinn Purdy Date: Fri, 13 Dec 2024 09:05:45 -0500 Subject: [PATCH 3/4] Added checkout ui docs --- docs/pages/sdk/unity/marketplace/checkout-ui.mdx | 15 +++++++++++++++ nav.ts | 1 + 2 files changed, 16 insertions(+) create mode 100644 docs/pages/sdk/unity/marketplace/checkout-ui.mdx diff --git a/docs/pages/sdk/unity/marketplace/checkout-ui.mdx b/docs/pages/sdk/unity/marketplace/checkout-ui.mdx new file mode 100644 index 00000000000..aa8b62091ab --- /dev/null +++ b/docs/pages/sdk/unity/marketplace/checkout-ui.mdx @@ -0,0 +1,15 @@ +# Checkout UI + +The SDK comes with a default Checkout UI that you are welcome to use. + +## Using the Default UI + +The SDK provides `CheckoutPanel` and `CheckoutPage` scripts, easily accessible via the `CheckoutPanel` prefab located at `/Sequence/SequenceFrontend/Prefabs/Marketplace/CheckoutPanel.prefab`. + +Once you've added the `CheckoutPanel` prefab to your scene, you can open it via the `Open()` method. When opening the `CheckoutPanel`, you'll need to provide an `ICheckoutHelper`. + +The `ICheckoutHelper` interface is implemented by `NftCheckout` and `Cart`. In general, `NftCheckout` will be more versatile and should be preferred for most use cases; in future updates, `NftCheckout` will support credit/debit card based payment flows. `Cart` on the other hand, is useful if you plan on only supporting crypto payments as it allows for purchasing multiple collectibles at once. + +## Building Your Own UI + +If you'd like to build your own UI, it is recommended to check out the `CheckoutPage` implementation as an example. The `CheckoutPage` uses the `ICheckoutHelper` interface rather heavily; it handles the majority of the logic when it comes to selecting Currencies, estimating prices, and checking out. \ No newline at end of file diff --git a/nav.ts b/nav.ts index 4e2f57a21b1..a4f50839977 100644 --- a/nav.ts +++ b/nav.ts @@ -668,6 +668,7 @@ export const sidebar = { { text: 'Introduction', link: '/sdk/unity/marketplace/intro' }, { text: 'Reading Orders', link: '/sdk/unity/marketplace/reading-orders' }, { text: 'Filling Orders', link: '/sdk/unity/marketplace/filling-orders' }, + { text: 'Checkout UI', link: '/sdk/unity/marketplace/checkout-ui' }, ] }, { text: 'Currency Swaps', link: '/sdk/unity/currency-swaps' }, From 8f42edd916c7232358a95954b306425535fdd6c2 Mon Sep 17 00:00:00 2001 From: Quinn Purdy Date: Fri, 13 Dec 2024 09:18:02 -0500 Subject: [PATCH 4/4] Add additional info to building your own UI --- docs/pages/sdk/unity/marketplace/checkout-ui.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/sdk/unity/marketplace/checkout-ui.mdx b/docs/pages/sdk/unity/marketplace/checkout-ui.mdx index aa8b62091ab..a0a2acba7c2 100644 --- a/docs/pages/sdk/unity/marketplace/checkout-ui.mdx +++ b/docs/pages/sdk/unity/marketplace/checkout-ui.mdx @@ -12,4 +12,4 @@ The `ICheckoutHelper` interface is implemented by `NftCheckout` and `Cart`. In g ## Building Your Own UI -If you'd like to build your own UI, it is recommended to check out the `CheckoutPage` implementation as an example. The `CheckoutPage` uses the `ICheckoutHelper` interface rather heavily; it handles the majority of the logic when it comes to selecting Currencies, estimating prices, and checking out. \ No newline at end of file +If you'd like to build your own UI, it is recommended to check out the `CheckoutPage` implementation as an example. The `CheckoutPage` uses the `ICheckoutHelper` interface rather heavily; it handles the majority of the logic when it comes to selecting Currencies, estimating prices, and checking out. You may also find it worthwhile to extend `CheckoutPage` and modify its behaviour as you see fit. \ No newline at end of file