import Fuse from "fuse.js"; import { useMemo, useState } from "react"; import { FlatList, Image, Linking, ScrollView, StyleSheet, TouchableOpacity, View, } from "react-native"; import type { Chain } from "../../../../chains/types.js"; import type { ThirdwebClient } from "../../../../client/client.js"; import walletInfos from "../../../../wallets/__generated__/wallet-infos.js"; import { NON_SEARCHABLE_WALLETS } from "../../../../wallets/constants.js"; import type { Wallet } from "../../../../wallets/interfaces/wallet.js"; import { createWallet } from "../../../../wallets/native/create-wallet.js"; import type { WalletId } from "../../../../wallets/wallet-types.js"; import type { Theme } from "../../../core/design-system/index.js"; import { useWalletImage, useWalletInfo } from "../../../core/utils/wallet.js"; import { spacing } from "../../design-system/index.js"; import type { ContainerType } from "../components/Header.js"; import { ThemedInput } from "../components/input.js"; import { RNImage } from "../components/RNImage.js"; import { Skeleton } from "../components/Skeleton.js"; import { Spacer } from "../components/spacer.js"; import { ThemedText } from "../components/text.js"; import { SEARCH_ICON } from "../icons/svgs.js"; type ExternalWalletsUiProps = { theme: Theme; client: ThirdwebClient; connector: (args: { wallet: Wallet; connectFn: (chain?: Chain) => Promise; }) => Promise; containerType: ContainerType; }; export function ExternalWalletsList( props: ExternalWalletsUiProps & { externalWallets: Wallet[]; showAllWalletsButton: boolean; onShowAllWallets: () => void; }, ) { const { connector, client, theme, externalWallets, onShowAllWallets } = props; const connectWallet = (wallet: Wallet) => { connector({ connectFn: async (chain) => { await wallet.connect({ chain, client, }); return wallet; }, wallet, }); }; return ( {externalWallets.map((wallet) => ( ))} {props.showAllWalletsButton && ( )} ); } export function AllWalletsList( props: ExternalWalletsUiProps & { externalWallets: Wallet[] }, ) { const { connector, client, theme, externalWallets } = props; const [searchQuery, setSearchQuery] = useState(""); const walletsToShow = useMemo(() => { const filteredWallets = walletInfos .filter( (info) => !externalWallets.find((wallet) => wallet.id === info.id), ) .filter((info) => !NON_SEARCHABLE_WALLETS.includes(info.id)) .filter((info) => info.hasMobileSupport); const fuse = new Fuse(filteredWallets, { keys: ["name"], threshold: 0.3, }); return searchQuery ? fuse.search(searchQuery).map((result) => result.item.id) : filteredWallets.map((info) => info.id); }, [externalWallets, searchQuery]); const connectWallet = (wallet: Wallet) => { connector({ connectFn: async (chain) => { await wallet.connect({ chain, client, }); return wallet; }, wallet, }); }; return ( } onChangeText={setSearchQuery} placeholder="Search Wallet" theme={theme} value={searchQuery} /> } keyExtractor={(walletId) => walletId} renderItem={({ item: walletId }) => ( )} style={{ flex: 1, paddingBottom: spacing.md, paddingHorizontal: props.containerType === "modal" ? spacing.lg : 0, }} /> ); } function ExternalWalletRow(props: { theme: Theme; wallet: Wallet; connectWallet: (wallet: Wallet) => void; }) { const { wallet, theme, connectWallet } = props; const imageQuery = useWalletImage(wallet.id); const infoQuery = useWalletInfo(wallet.id); return ( connectWallet(wallet)} style={styles.row}> {imageQuery.data ? ( ) : ( )} {infoQuery.data?.name || ""} ); } function ShowAllWalletsRow(props: { theme: Theme; onPress: () => void }) { const { theme, onPress } = props; return ( {[...Array(4)].map((_, index) => ( ))} Show all wallets ); } function NewToWallets({ theme, containerType, }: { theme: Theme; containerType: ContainerType; }) { return ( New to wallets? Linking.openURL("https://blog.thirdweb.com/web3-wallet/") } style={{ color: theme.colors.primaryText }} theme={theme} type="subtext" > Get started ); } const styles = StyleSheet.create({ container: { flex: 1, flexDirection: "column", }, row: { alignItems: "center", flexDirection: "row", gap: spacing.md, justifyContent: "flex-start", }, searchContainer: { alignItems: "center", flexDirection: "row", gap: spacing.md, justifyContent: "flex-start", paddingHorizontal: spacing.lg, }, });