diff --git a/apps/browser-extension-wallet/src/hooks/useNftSearch.ts b/apps/browser-extension-wallet/src/hooks/useNftSearch.ts index 87f50b3706..ef4278fd75 100644 --- a/apps/browser-extension-wallet/src/hooks/useNftSearch.ts +++ b/apps/browser-extension-wallet/src/hooks/useNftSearch.ts @@ -12,17 +12,16 @@ interface NftSearchResultProps { handleSearch: (items: NftItemProps[], searchValue: string) => void; } +export const searchNft = (item: NftItemProps, searchValue: string, assetsInfo: AssetOrHandleInfoMap): boolean => + item.name.toLowerCase().includes(searchValue.toLowerCase()) || + item.assetId === searchValue || + assetsInfo.get(Cardano.AssetId(item.assetId)).policyId === searchValue; + export const searchNfts = ( data: NftItemProps[], searchValue: string, assetsInfo: AssetOrHandleInfoMap -): NftItemProps[] => - data.filter( - (item) => - item.name.toLowerCase().includes(searchValue.toLowerCase()) || - item.assetId === searchValue || - assetsInfo.get(Cardano.AssetId(item.assetId)).policyId === searchValue - ); +): NftItemProps[] => data.filter((nft) => searchNft(nft, searchValue, assetsInfo)); export const useNftSearch = (assetsInfo: AssetOrHandleInfoMap): NftSearchResultProps => { const [isSearching, setIsSearching] = useState(false); diff --git a/apps/browser-extension-wallet/src/utils/get-token-list.ts b/apps/browser-extension-wallet/src/utils/get-token-list.ts index 459b7f50e8..a48f77b12d 100644 --- a/apps/browser-extension-wallet/src/utils/get-token-list.ts +++ b/apps/browser-extension-wallet/src/utils/get-token-list.ts @@ -13,6 +13,7 @@ import { CurrencyInfo } from '@src/types'; import { isNFT } from './is-nft'; import { getAssetImage } from './get-asset-image'; import { Asset } from '@cardano-sdk/core'; +import { TokenInformation } from '@src/views/browser-view/features/assets/types'; const DISPLAY_FALLBACK = '-'; const NAME_TRUNCATE_LENGTH = 10; @@ -132,7 +133,7 @@ const getDecimalsFromNftMetadata = (metadata?: Asset.NftMetadata): number | unde */ export const getTokenDisplayMetadata = ( info?: AssetOrHandleInfo -): Pick => { +): Pick & Partial => { const name = info?.tokenMetadata?.name || info?.nftMetadata?.name || @@ -145,7 +146,9 @@ export const getTokenDisplayMetadata = ( name, description: ticker, decimals, - logo: getTokenLogoUrl(info) + logo: getTokenLogoUrl(info), + policyId: info?.policyId, + fingerprint: info?.fingerprint }; }; @@ -167,7 +170,7 @@ export const getNftDisplayMetadata = (info?: AssetOrHandleInfo): Pick { const { assetsInfo = new Map() as AssetOrHandleInfoMap, balance, prices, tokensSpent, fiatCurrency } = params; const nfts: NFT[] = []; - const tokens: NonNFTAsset[] = []; + const tokens: (NonNFTAsset & Partial)[] = []; if (isNil(balance) || balance.size === 0) { return { tokenList: [], nftList: [] }; } @@ -209,7 +212,9 @@ export const getTokenList = (params: GetTokenListParams): { tokenList: NonNFTAss description: ftDisplayMetadata.description, logo: ftDisplayMetadata.logo, defaultLogo: getRandomIcon({ id: assetId.toString(), size: 30 }), - decimals: ftDisplayMetadata.decimals + decimals: ftDisplayMetadata.decimals, + policyId: ftDisplayMetadata.policyId, + fingerprint: ftDisplayMetadata.fingerprint }); } } diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetPortfolioContent.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetPortfolioContent.tsx index 29aa9a5ec1..2f41655c3d 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetPortfolioContent.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetPortfolioContent.tsx @@ -5,20 +5,21 @@ import { Skeleton } from 'antd'; import { AssetTable, IRow } from '@lace/core'; import { CONTENT_LAYOUT_ID } from '@components/Layout'; import { LACE_APP_ID } from '@utils/constants'; -import { IAssetDetails } from '@views/browser/features/assets/types'; +import { IAssetDetails, TokenInformation } from '@views/browser/features/assets/types'; import { useTranslation } from 'react-i18next'; import { useWalletStore } from '@stores'; import styles from './AssetsPortfolio.module.scss'; const MIN_ASSETS_COUNT_FOR_SEARCH = 10; -const searchTokens = (data: IAssetDetails[], searchValue: string) => { - const fields = ['name', 'policyId', 'fingerprint', 'ticker'] as const; +const fields = ['name', 'policyId', 'fingerprint', 'ticker'] as const; +export const searchToken = (item: Partial & Partial, searchValue: string): boolean => + fields.some((field) => field in item && item[field]?.toLowerCase().includes(searchValue)); + +export const searchTokens = (data: IAssetDetails[], searchValue: string): IAssetDetails[] => { const lowerSearchValue = searchValue.toLowerCase(); - return data.filter((item) => - fields.some((field) => field in item && item[field]?.toLowerCase().includes(lowerSearchValue)) - ); + return data.filter((item) => searchToken(item, lowerSearchValue)); }; interface AssetPortfolioContentProps { diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/assets/types.ts b/apps/browser-extension-wallet/src/views/browser-view/features/assets/types.ts index 0690f40612..ffa037b305 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/assets/types.ts +++ b/apps/browser-extension-wallet/src/views/browser-view/features/assets/types.ts @@ -2,7 +2,7 @@ import { Wallet } from '@lace/cardano'; import { AssetTableProps } from '@lace/core'; type Unpacked = T extends (infer U)[] ? U : T; -interface TokenInformation { +export interface TokenInformation { policyId: string; fingerprint: string; } diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/nfts/components/CreateFolder/AssetPicker.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/nfts/components/CreateFolder/AssetPicker.tsx index b36a9538d4..1236d02c0e 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/nfts/components/CreateFolder/AssetPicker.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/nfts/components/CreateFolder/AssetPicker.tsx @@ -1,13 +1,14 @@ /* eslint-disable max-params */ -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { ASSET_COMPONENTS, AssetSelectorOverlay } from '@lace/core'; +import { ASSET_COMPONENTS, AssetSelectorOverlay, NftItemProps } from '@lace/core'; import { useWalletStore } from '@stores'; import { useObservable } from '@lace/common'; import styles from './CreateFolderDrawer.module.scss'; import { formatNftsList } from '../utils'; import { useCurrencyStore } from '@providers'; import { useAssetInfo } from '@hooks'; +import { searchNft } from '@hooks/useNftSearch'; const nftsPerRow = { popupView: 2, @@ -71,10 +72,16 @@ export const AssetPicker = ({ onSetIsFormValid(selectedNFTs.length > 0); }, [selectedNFTs, onSetIsFormValid]); + const handleSearch = useCallback( + (item: NftItemProps, searchValue: string) => searchNft(item, searchValue, assets), + [assets] + ); + return (
{ - const { assetId, ...rest } = nft; - return { ...rest, id: assetId.toString() }; - }); + return nftList.map((nft) => ({ ...nft, id: nft.assetId.toString() })); }; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/AssetPicker.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/AssetPicker.tsx index b16016cf57..6b4d343d5a 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/AssetPicker.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/AssetPicker.tsx @@ -1,6 +1,6 @@ /* eslint-disable max-params */ -import React, { useEffect, useState } from 'react'; -import { AssetSelectorOverlay, AssetSelectorOverlayProps } from '@lace/core'; +import React, { useCallback, useEffect, useState } from 'react'; +import { AssetSelectorOverlay, AssetSelectorOverlayProps, NftItemProps } from '@lace/core'; import { Wallet } from '@lace/cardano'; import CardanoLogo from '../../../../../assets/icons/browser-view/cardano-logo.svg'; import { useFetchCoinPrice, PriceResult, AssetOrHandleInfoMap, useAssetInfo } from '@hooks'; @@ -28,6 +28,8 @@ import styles from './AssetPicker.module.scss'; import { useCurrencyStore } from '@providers'; import { isNFT } from '@src/utils/is-nft'; import { useObservable } from '@lace/common'; +import { searchToken } from '../../assets/components/AssetsPortfolio/AssetPortfolioContent'; +import { searchNft } from '@hooks/useNftSearch'; const formatAssetPickerLists = ( assetsInfo: AssetOrHandleInfoMap = new Map(), @@ -62,10 +64,7 @@ const formatAssetPickerLists = ( return { ...rest, id: assetId.toString() }; }); - const nfts = nftList.map((nft) => { - const { assetId, ...rest } = nft; - return { ...rest, id: assetId.toString() }; - }); + const nfts = nftList.map((nft) => ({ ...nft, id: nft.assetId.toString() })); if (addCardanoAsAnAsset) { tokens.push({ @@ -210,9 +209,16 @@ export const AssetPicker = ({ isPopupView }: AssetPickerProps): React.ReactEleme setSelectedTokenList(id, isNFT(assetInfo)); }; + const handleSearchNfts = useCallback( + (item: NftItemProps, searchValue: string) => searchNft(item, searchValue, assets), + [assets] + ); + return ( <> void; className?: string; groups?: Array; + searchNfts: (item: NftItemProps, searchValue: string) => boolean; + searchTokens?: (item: DropdownList, searchValue: string) => boolean; } export const AssetSelectorOverlay = ({ @@ -139,7 +141,9 @@ export const AssetSelectorOverlay = ({ removeTokenFromList, doesWalletHaveTokens, className, - groups = [ASSET_COMPONENTS.TOKENS, ASSET_COMPONENTS.NFTS] + groups = [ASSET_COMPONENTS.TOKENS, ASSET_COMPONENTS.NFTS], + searchNfts, + searchTokens }: AssetSelectorOverlayProps): React.ReactElement => { const { t } = useTranslation(); const [value, setValue] = useState(); @@ -158,21 +162,15 @@ export const AssetSelectorOverlay = ({ const filterAssets = useCallback(async () => { const filter = () => { - const filteredNfts = nfts?.filter((item) => !value || stringIncludesValue(item.name, value)); - const filteredTokens = tokens?.filter( - (item) => - !value || - item.id === value || - stringIncludesValue(item.name, value) || - stringIncludesValue(item.description, value) - ); + const filteredNfts = nfts?.filter((item) => !value || searchNfts(item, value)); + const filteredTokens = tokens?.filter((item) => !value || searchTokens?.(item, value)); return Promise.resolve({ filteredNfts, filteredTokens }); }; setIsSearching(true); const result = await filter(); setSearchResult({ nfts: result.filteredNfts ?? [], tokens: result.filteredTokens ?? [] }); setIsSearching(false); - }, [nfts, tokens, value]); + }, [nfts, searchNfts, searchTokens, tokens, value]); useEffect(() => { filterAssets(); diff --git a/packages/core/src/ui/components/Nft/NftItem.tsx b/packages/core/src/ui/components/Nft/NftItem.tsx index 4288a56818..43f666c102 100644 --- a/packages/core/src/ui/components/Nft/NftItem.tsx +++ b/packages/core/src/ui/components/Nft/NftItem.tsx @@ -44,7 +44,8 @@ const ContextMenu = ({ setClicked, children, onRender, points }: ContextMenuProp ); }; -export interface NftItemProps { +export type NftItemProps = { + id?: string; assetId?: string; image?: string; name: string; @@ -53,7 +54,7 @@ export interface NftItemProps { selected?: boolean; type?: NftsItemsTypes.NFT; contextMenu?: React.ReactElement; -} +}; export const NftItem = ({ image, name, onClick, amount, selected, contextMenu }: NftItemProps): React.ReactElement => { const bodyRef = useRef<{ clientWidth?: number }>({ clientWidth: 0 });