Leverage the CancelListingModal to cancel listings using ReservoirKit

Prerequisites ⚙️

Install and configure ReservoirKit.

CancelListingModal Setup

ReservoirKit provides a simple to configure modal for canceling a valid listing in your react app. Below is an example of a simple CancelListingModal setup.

import { CancelListingModal } from '@reservoir0x/reservoir-kit-ui'

      Cancel Listing
  onCancelComplete={(data: any) => {
    console.log('Listing Canceled', data)
  onCancelError={(error: any, data: any) => {
    console.log('Listing Cancel Error', error, data)
  onClose={(data, currentStep) => {
    console.log('CancelListingModal Closed')

Let's dive into the parameters:

triggerA react node that will be presented to the user, usually a button or something clickable.Y
listingIdAn order id representing the listing. It can be set to undefined until the data is readyY
normalizeRoyaltiesUse this to ensure that royalties are added to the listing data displayed. If royalties are missing from the order then the correct royalties are added on top. If unspecified then the global setting will be used if provided.N
openStateThis is a state tuple from react's useState, you can use this to programmatically open or close the modal. The modal will use this state when determining if the modal is open or closed.N
copyOverridesAn object containing copy overrides for titles and ctas contained in the modal. Refer to the ModalCopy type for which tokens map to what copy.N
chainIdThe chain id to force the modal to render, ensure that this is a chain that is configured in the ReservoirKit provider. If not specified then the active chain configured in the ReservoirKitProvider will be used.N
walletClientA valid WalletClient from viem or a ReservoirWallet generated from an adapter. Learn more about adaptersN
onCancelCompleteTriggered when cancelling was completed successfully, returns some useful data about the listing and the cancel step.N
onCancelErrorTriggered when the cancel resulted in an error, returns the error and the listing data.N
onCloseTriggered when the modal was closed. Returns some useful data about the listing as well as the step data and the current step.N

Conditional Rendering

ReservoirKit's CancelListingModal doesn't take care of conditionally showing the button/modal based on if the item is cancelable by the user, we leave that logic up to the developer. Below are the requirements for canceling a listing and how to go about getting that data:

  • The user needs to have a connected wallet. You can check this by looking for a signer from the useWalletClient wagmi hook.
  • The user must be the maker of the listing, you can check this by comparing maker in the listing object to the connected wallet address. You can get a full list of a wallet's listings by using the useListings hook or the underlying api.

Custom CancelListingModal

The CancelListingModal also comes with a custom renderer which can be used to just get the data layer that the CancelListingModal uses internally to handle the underlying business logic. With the renderer you can rebuild the UI completely to your liking. Below is an example of how it works in practice.

import { CancelListingModal, CancelListingStep } from '@reservoir0x/reservoir-kit-ui'

    }) => {
  { Your Custom React Elements }

The custom CancelListingModal takes a few parameters like before with one additional one being the open parameter. This is because there is no trigger, you have control over what sort of modal you want this to eventually live in and how to trigger that modal. You'll have the ability to add a custom button with a custom handler, etc. The custom CancelListingModal then passes some key data into the children which we parse above and use in our custom UI. It's also important to note the CancelListingStep here which is used to manage the internal state of the CancelListingModal's logic. You can decide to use all or some of the data passed into your custom implementation.


Nice job!

Now that we've added a cancel listing modal to your dApp, let's customize the theme to match your brand.