-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wallet-ext] - Updated Kiosk UI / Enable Transfer for Sui Kiosk (#13068)
## Description This PR updates the UI for displaying Kiosks in the wallet. It also includes updates to allow transfer of items within a Sui Kiosk for non-locked items. Also includes UI for representing assets that are locked in a Kiosk https://github.com/MystenLabs/sui/assets/122397493/e76b86a6-5648-4b90-ae2e-d4811072ba77 ## Test Plan How did you test the new or updated feature? --- If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process. ### Type of Change (Check all that apply) - [ ] protocol change - [ ] user-visible impact - [ ] breaking change for a client SDKs - [ ] breaking change for FNs (FN binary must upgrade) - [ ] breaking change for validators or node operators (must upgrade binaries) - [ ] breaking change for on-chain data layout - [ ] necessitate either a data wipe or data migration ### Release notes --------- Co-authored-by: Pavlos Chrysochoidis <[email protected]>
- Loading branch information
1 parent
52a6e7b
commit 13df03f
Showing
18 changed files
with
479 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { | ||
SuiObjectData, | ||
SuiObjectResponse, | ||
getSuiObjectData, | ||
isSuiObjectResponse, | ||
getObjectFields, | ||
} from '@mysten/sui.js'; | ||
import { KIOSK_OWNER_CAP } from '@mysten/kiosk'; | ||
|
||
export const ORIGINBYTE_KIOSK_MODULE = | ||
'0x95a441d389b07437d00dd07e0b6f05f513d7659b13fd7c5d3923c7d9d847199b::ob_kiosk'; | ||
|
||
export const ORIGINBYTE_KIOSK_OWNER_TOKEN = `${ORIGINBYTE_KIOSK_MODULE}::OwnerToken`; | ||
|
||
export function isKioskOwnerToken(object?: SuiObjectResponse | SuiObjectData) { | ||
if (!object) return false; | ||
const objectData = isSuiObjectResponse(object) ? getSuiObjectData(object) : object; | ||
return [KIOSK_OWNER_CAP, ORIGINBYTE_KIOSK_OWNER_TOKEN].includes(objectData?.type ?? ''); | ||
} | ||
|
||
export function getKioskIdFromOwnerCap(object: SuiObjectResponse | SuiObjectData) { | ||
const objectData = isSuiObjectResponse(object) ? getSuiObjectData(object) : object; | ||
const fields = getObjectFields(objectData!); | ||
return fields?.for ?? fields?.kiosk; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
import { getKioskIdFromOwnerCap, hasDisplayData, useGetKioskContents } from '@mysten/core'; | ||
import { getObjectDisplay, type SuiObjectResponse } from '@mysten/sui.js'; | ||
import cl from 'classnames'; | ||
|
||
import { NftImage, type NftImageProps } from './NftImage'; | ||
import { useActiveAddress } from '../../hooks'; | ||
import { Text } from '../../shared/text'; | ||
|
||
type KioskProps = { | ||
object: SuiObjectResponse; | ||
orientation?: 'vertical' | 'horizontal' | null; | ||
} & Partial<NftImageProps>; | ||
|
||
// used to prevent the top image from overflowing the bottom of the container | ||
// (clip-path is used instead of overflow-hidden as it can be animated) | ||
const clipPath = '[clip-path:inset(0_0_7px_0_round_12px)] group-hover:[clip-path:inset(0_0_0_0)]'; | ||
|
||
const timing = 'transition-all duration-300 ease-[cubic-bezier(0.68,-0.55,0.265,1.55)]'; | ||
const cardStyles = [ | ||
`scale-100 group-hover:scale-95 object-cover origin-bottom z-20 group-hover:translate-y-0 translate-y-2 group-hover:shadow-md`, | ||
`scale-[0.95] group-hover:-rotate-6 group-hover:-translate-x-5 group-hover:-translate-y-2 z-10 translate-y-0 group-hover:shadow-md`, | ||
`scale-[0.90] group-hover:rotate-6 group-hover:translate-x-5 group-hover:-translate-y-2 z-0 -translate-y-2 group-hover:shadow-xl`, | ||
]; | ||
|
||
export function Kiosk({ object, orientation, ...nftImageProps }: KioskProps) { | ||
const address = useActiveAddress(); | ||
const { data: kioskData, isLoading } = useGetKioskContents(address); | ||
|
||
if (isLoading) return null; | ||
const kioskId = getKioskIdFromOwnerCap(object); | ||
const kiosk = kioskData?.kiosks.get(kioskId!); | ||
const itemsWithDisplay = kiosk?.items.filter((item) => hasDisplayData(item)) ?? []; | ||
const items = kiosk?.items?.sort((item) => (hasDisplayData(item) ? -1 : 1)) ?? []; | ||
|
||
const showCardStackAnimation = itemsWithDisplay.length > 1 && orientation !== 'horizontal'; | ||
const imagesToDisplay = orientation !== 'horizontal' ? 3 : 1; | ||
|
||
return ( | ||
<div | ||
className={cl( | ||
'relative hover:bg-transparent group rounded-xl transform-gpu overflow-visible w-36 h-36', | ||
)} | ||
> | ||
<div className="absolute z-0"> | ||
{itemsWithDisplay.length === 0 ? ( | ||
<NftImage animateHover src={null} name="Kiosk" {...nftImageProps} /> | ||
) : items?.length ? ( | ||
items.slice(0, imagesToDisplay).map((item, idx) => { | ||
const display = getObjectDisplay(item)?.data; | ||
return ( | ||
<div | ||
key={item.data?.objectId} | ||
className={cl( | ||
'absolute rounded-xl border', | ||
timing, | ||
showCardStackAnimation ? cardStyles[idx] : '', | ||
)} | ||
> | ||
<div className={`${idx === 0 && showCardStackAnimation ? clipPath : ''} ${timing}`}> | ||
<NftImage | ||
{...nftImageProps} | ||
src={display?.image_url!} | ||
animateHover={items.length <= 1} | ||
name="Kiosk" | ||
/> | ||
</div> | ||
</div> | ||
); | ||
}) | ||
) : null} | ||
</div> | ||
{orientation !== 'horizontal' && ( | ||
<div | ||
className={cl( | ||
timing, | ||
'right-1.5 bottom-1.5 flex items-center justify-center absolute h-6 w-6 bg-gray-100 text-white rounded-md', | ||
{ 'group-hover:-translate-x-0.5 group-hover:scale-95': showCardStackAnimation }, | ||
)} | ||
> | ||
<Text variant="subtitle" weight="medium"> | ||
{items?.length} | ||
</Text> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} |
Oops, something went wrong.