From 09548f7ec6c2e2e1a98286e4b68d93e8fb0b8c1f Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Wed, 11 Dec 2024 12:52:37 -0500 Subject: [PATCH] WIP for adding collection list --- src/components/helpers/index.tsx | 6 - .../{helpers => misc}/ButtonWithIcon.tsx | 0 .../{helpers => misc}/ExternalIcon.tsx | 0 .../{helpers => misc}/FilledCheckBox.tsx | 0 .../{helpers => misc}/FilledRoundCheckBox.tsx | 0 src/components/misc/index.tsx | 6 + src/components/network/NetworkItem.tsx | 2 +- src/components/recovery/WalletList.tsx | 2 +- src/components/signing/ConnectionList.tsx | 4 +- .../collectibles/CollectibleBalanceItem.tsx | 4 +- .../wallet/collectibles/CollectibleList.tsx | 2 +- .../wallet/collectibles/ImportCollectible.tsx | 698 +++++++++++++----- .../wallet/collectibles/SendCollectible.tsx | 2 +- .../externalprovider/ExternalWallet.tsx | 4 +- src/components/wallet/tokens/ImportToken.tsx | 43 +- src/components/wallet/tokens/SendToken.tsx | 2 +- .../wallet/tokens/TokenBalanceItem.tsx | 4 +- src/components/wallet/tokens/TokenList.tsx | 3 +- src/routes/Recovery.tsx | 2 +- src/stores/CollectibleStore.ts | 20 + 20 files changed, 560 insertions(+), 244 deletions(-) delete mode 100644 src/components/helpers/index.tsx rename src/components/{helpers => misc}/ButtonWithIcon.tsx (100%) rename src/components/{helpers => misc}/ExternalIcon.tsx (100%) rename src/components/{helpers => misc}/FilledCheckBox.tsx (100%) rename src/components/{helpers => misc}/FilledRoundCheckBox.tsx (100%) create mode 100644 src/components/misc/index.tsx diff --git a/src/components/helpers/index.tsx b/src/components/helpers/index.tsx deleted file mode 100644 index 5072296..0000000 --- a/src/components/helpers/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { FilledCheckBox } from '~/components/helpers/FilledCheckBox' -import { FilledRoundCheckBox, ROUND_CHECKBOX_SIZE } from '~/components/helpers/FilledRoundCheckBox' -import { ButtonWithIcon } from '~/components/helpers/ButtonWithIcon' -import { ExternalIcon } from '~/components/helpers/ExternalIcon' - -export { FilledCheckBox, FilledRoundCheckBox, ROUND_CHECKBOX_SIZE, ButtonWithIcon, ExternalIcon } \ No newline at end of file diff --git a/src/components/helpers/ButtonWithIcon.tsx b/src/components/misc/ButtonWithIcon.tsx similarity index 100% rename from src/components/helpers/ButtonWithIcon.tsx rename to src/components/misc/ButtonWithIcon.tsx diff --git a/src/components/helpers/ExternalIcon.tsx b/src/components/misc/ExternalIcon.tsx similarity index 100% rename from src/components/helpers/ExternalIcon.tsx rename to src/components/misc/ExternalIcon.tsx diff --git a/src/components/helpers/FilledCheckBox.tsx b/src/components/misc/FilledCheckBox.tsx similarity index 100% rename from src/components/helpers/FilledCheckBox.tsx rename to src/components/misc/FilledCheckBox.tsx diff --git a/src/components/helpers/FilledRoundCheckBox.tsx b/src/components/misc/FilledRoundCheckBox.tsx similarity index 100% rename from src/components/helpers/FilledRoundCheckBox.tsx rename to src/components/misc/FilledRoundCheckBox.tsx diff --git a/src/components/misc/index.tsx b/src/components/misc/index.tsx new file mode 100644 index 0000000..1b18c49 --- /dev/null +++ b/src/components/misc/index.tsx @@ -0,0 +1,6 @@ +import { FilledCheckBox } from '~/components/misc/FilledCheckBox' +import { FilledRoundCheckBox, ROUND_CHECKBOX_SIZE } from '~/components/misc/FilledRoundCheckBox' +import { ButtonWithIcon } from '~/components/misc/ButtonWithIcon' +import { ExternalIcon } from '~/components/misc/ExternalIcon' + +export { FilledCheckBox, FilledRoundCheckBox, ROUND_CHECKBOX_SIZE, ButtonWithIcon, ExternalIcon } \ No newline at end of file diff --git a/src/components/network/NetworkItem.tsx b/src/components/network/NetworkItem.tsx index da4f239..cfcfebf 100644 --- a/src/components/network/NetworkItem.tsx +++ b/src/components/network/NetworkItem.tsx @@ -13,7 +13,7 @@ import { ChangeEvent, useEffect, useState } from 'react' import { useObservable, useStore } from '~/stores' import { NetworkStore, createDebugLocalRelayer } from '~/stores/NetworkStore' -import { FilledCheckBox } from '~/components/helpers' +import { FilledCheckBox } from '~/components/misc' export default function NetworkItem({ network }: { network: NetworkConfig }) { const networkStore = useStore(NetworkStore) diff --git a/src/components/recovery/WalletList.tsx b/src/components/recovery/WalletList.tsx index 6fed155..c02b894 100644 --- a/src/components/recovery/WalletList.tsx +++ b/src/components/recovery/WalletList.tsx @@ -1,7 +1,7 @@ import { Box, Text, truncateAddress } from '@0xsequence/design-system' import { useState } from 'react' -import { FilledRoundCheckBox, ROUND_CHECKBOX_SIZE } from '~/components/helpers' +import { FilledRoundCheckBox, ROUND_CHECKBOX_SIZE } from '~/components/misc' export default function WalletList({ possibleWallets, diff --git a/src/components/signing/ConnectionList.tsx b/src/components/signing/ConnectionList.tsx index 6239497..f1f646f 100644 --- a/src/components/signing/ConnectionList.tsx +++ b/src/components/signing/ConnectionList.tsx @@ -4,8 +4,8 @@ import { SessionTypes } from '@walletconnect/types' import { useStore } from '~/stores' import { WalletConnectSignClientStore } from '~/stores/WalletConnectSignClientStore' -import { ButtonWithIcon } from '~/components/helpers/ButtonWithIcon' -import { ExternalIcon } from '~/components/helpers/ExternalIcon' +import { ButtonWithIcon } from '~/components/misc/ButtonWithIcon' +import { ExternalIcon } from '~/components/misc/ExternalIcon' export default function ConnectionList({ sessionList }: { sessionList: SessionTypes.Struct[] }) { const walletConnectSignClientStore = useStore(WalletConnectSignClientStore) diff --git a/src/components/wallet/collectibles/CollectibleBalanceItem.tsx b/src/components/wallet/collectibles/CollectibleBalanceItem.tsx index 814b206..812eccb 100644 --- a/src/components/wallet/collectibles/CollectibleBalanceItem.tsx +++ b/src/components/wallet/collectibles/CollectibleBalanceItem.tsx @@ -3,8 +3,8 @@ import { BigNumberish, ethers } from 'ethers' import { CollectibleInfo } from '~/stores/CollectibleStore' -import { ButtonWithIcon } from '~/components/helpers/ButtonWithIcon' -import { ExternalIcon } from '~/components/helpers/ExternalIcon' +import { ButtonWithIcon } from '~/components/misc/ButtonWithIcon' +import { ExternalIcon } from '~/components/misc/ExternalIcon' import NetworkTag from '~/components/network/NetworkTag' import SendIcon from '~/assets/icons/send.svg' diff --git a/src/components/wallet/collectibles/CollectibleList.tsx b/src/components/wallet/collectibles/CollectibleList.tsx index 9ff6e15..2b4e1fe 100644 --- a/src/components/wallet/collectibles/CollectibleList.tsx +++ b/src/components/wallet/collectibles/CollectibleList.tsx @@ -97,7 +97,7 @@ export default function CollectibleList({ {isImportCollectibleViewOpen && ( - setIsImportCollectibleViewOpen(false)}> + setIsImportCollectibleViewOpen(false)}> setIsImportCollectibleViewOpen(false)} /> )} diff --git a/src/components/wallet/collectibles/ImportCollectible.tsx b/src/components/wallet/collectibles/ImportCollectible.tsx index 1ca1fea..397ab5f 100644 --- a/src/components/wallet/collectibles/ImportCollectible.tsx +++ b/src/components/wallet/collectibles/ImportCollectible.tsx @@ -4,6 +4,7 @@ import { Card, Divider, Image, + SearchIcon, Select, Spinner, Text, @@ -11,9 +12,7 @@ import { useToast } from '@0xsequence/design-system' import { NetworkConfig, NetworkType } from '@0xsequence/network' -import { BigNumberish } from 'ethers' -import { ethers } from 'ethers' -import { ChangeEvent, useEffect, useState } from 'react' +import { ChangeEvent, useEffect, useRef, useState } from 'react' import { useObservable, useStore } from '~/stores' import { @@ -24,6 +23,8 @@ import { } from '~/stores/CollectibleStore' import { NetworkStore } from '~/stores/NetworkStore' +import { FilledRoundCheckBox } from '~/components/misc' + export default function ImportCollectible({ onClose }: { onClose: () => void }) { const networkStore = useStore(NetworkStore) const networks = networkStore.networks.get() @@ -35,50 +36,55 @@ export default function ImportCollectible({ onClose }: { onClose: () => void }) const toast = useToast() const [selectedNetwork, setSelectedNetwork] = useState() - const [collectibleAddress, setCollectibleAddress] = useState() - const [collectibleTokenId, setCollectibleTokenId] = useState() + const [collectibleManualAddress, setCollectibleManualAddress] = useState() + const [collectibleManualTokenId, setCollectibleManualTokenId] = useState() const [contractType, setContractType] = useState() - const [collectibleInfoResponse, setCollectibleInfoResponse] = useState< - CollectibleInfoResponse | undefined - >() + const [collectibleInfo, setCollectibleInfo] = useState() const [isAddingCollectible, setIsAddingCollectible] = useState(false) - const [tokenDirectory, setTokenDirectory] = useState() - const [isAddingCollectibleManually, setIsAddingCollectibleManually] = useState(false) - const [collectibleList, setCollectibleList] = useState(undefined) + const [collectionList, setCollectionList] = useState([]) + const [collectionListFilter, setCollectionListFilter] = useState('') + const [filteredCollectionList, setFilteredCollectionList] = useState([]) + + const [selectedCollection, setSelectedCollection] = useState([]) + + const fileInputRef = useRef(null) + + useEffect(() => { + console.log(filteredCollectionList) + }, [filteredCollectionList]) useEffect(() => { const fetchCollectibleList = async () => { - if (selectedNetwork) { - setTokenDirectory(networks.find(n => n.chainId === selectedNetwork.chainId)?.blockExplorer?.rootUrl) + if (selectedNetwork && contractType) { if (contractType === CollectibleContractTypeValues.ERC721) { - setCollectibleList(await collectibleStore.getDefaultERC721List(selectedNetwork.chainId)) + setCollectionList(await collectibleStore.getDefaultERC721List(selectedNetwork.chainId)) } else if (contractType === CollectibleContractTypeValues.ERC1155) { - setCollectibleList(await collectibleStore.getDefaultERC1155List(selectedNetwork.chainId)) + setCollectionList(await collectibleStore.getDefaultERC1155List(selectedNetwork.chainId)) } } } fetchCollectibleList() - if (selectedNetwork && collectibleAddress && collectibleTokenId && contractType) { + if (selectedNetwork && collectibleManualAddress && collectibleManualTokenId && contractType) { collectibleStore .getCollectibleInfo({ chainId: selectedNetwork.chainId, - address: collectibleAddress, - tokenId: collectibleTokenId, + address: collectibleManualAddress, + tokenId: collectibleManualTokenId, contractType }) .then(response => { - setCollectibleInfoResponse(response) + setCollectibleInfo(response) }) } else { - setCollectibleInfoResponse(undefined) + setCollectibleInfo(undefined) } - }, [selectedNetwork, collectibleAddress, collectibleTokenId, contractType]) + }, [selectedNetwork, collectibleManualAddress, collectibleManualTokenId, contractType]) const selectOptions = mainnetNetworks .filter(network => !network.disabled) @@ -92,22 +98,59 @@ export default function ImportCollectible({ onClose }: { onClose: () => void }) value: network.chainId.toString() })) + useEffect(() => { + const fetchCollectionList = async () => { + if (selectedNetwork) { + if (contractType === CollectibleContractTypeValues.ERC721) { + setCollectionList(await collectibleStore.getDefaultERC721List(selectedNetwork.chainId)) + } else if (contractType === CollectibleContractTypeValues.ERC1155) { + setCollectionList(await collectibleStore.getDefaultERC1155List(selectedNetwork.chainId)) + } + } + } + + fetchCollectionList() + }, [selectedNetwork]) + + useEffect(() => { + if (!collectionListFilter) return setFilteredCollectionList(collectionList?.slice(0, 8)) + setFilteredCollectionList( + collectionList + ?.filter( + collection => + collection.name && collection.name.toLowerCase().includes(collectionListFilter.toLowerCase()) + ) + .slice(0, 8) + ) + }, [collectionList, collectionListFilter]) + + const toggleSelectCollectible = async (collectionAddress: string) => { + const isSelected = selectedCollection.some(collection => collection.address === collectionAddress) + if (isSelected) { + setSelectedCollection( + selectedCollection.filter(collectible => collectible.address !== collectionAddress) + ) + } else { + setSelectedCollection([...selectedCollection, { address: collectionAddress, info: undefined }]) + } + } + const handleAdd = async () => { if ( selectedNetwork && - collectibleAddress && - collectibleInfoResponse && - collectibleTokenId && + collectibleManualAddress && + collectibleInfo && + collectibleManualTokenId && contractType ) { await collectibleStore.addCollectible({ collectibleInfoParams: { chainId: selectedNetwork.chainId, - address: collectibleAddress, - tokenId: collectibleTokenId, + address: collectibleManualAddress, + tokenId: collectibleManualTokenId, contractType }, - collectibleInfoResponse: collectibleInfoResponse + collectibleInfoResponse: collectibleInfo }) setIsAddingCollectible(false) toast({ @@ -125,203 +168,456 @@ export default function ImportCollectible({ onClose }: { onClose: () => void }) } const resetInputs = () => { - setCollectibleAddress(undefined) + setCollectibleManualAddress(undefined) setSelectedNetwork(undefined) - setCollectibleTokenId(undefined) + setCollectibleManualTokenId(undefined) setContractType(undefined) } - return ( - - - - Import ERC721 or ERC1155 Collectibles - - - - - - Collectible Network - - - setContractType(value as CollectibleContractType)} - /> - + const handleImportCustomCollectibleList = () => { + fileInputRef.current?.click() + } + + return ( + // + // + // + // Import ERC721 or ERC1155 Collectibles + // + + // + // + // + // Collectible Network + // + + // setContractType(value as CollectibleContractType)} + // /> + // + + // + // + // Token + // + + // {}} + // width="fit" + // cursor="pointer" + // paddingBottom="0.5" + // opacity={{ base: '100', hover: '80' }} + // > + // + // Import external token list + // + // + + // setSelectedNetwork(networks.find(n => n.chainId === Number(value)))} + /> + - - - Token - - - {}} - width="fit" - cursor="pointer" - paddingBottom="0.5" - opacity={{ base: '100', hover: '80' }} - > - - Import external token list + + + setContractType(CollectibleContractTypeValues.ERC721)}> + + ERC721 + {contractType === CollectibleContractTypeValues.ERC721 && ( + + )} - + - - - {collectibleInfoResponse.name ?? ''} - - - Your Balance: - - - {Number( - ethers.formatUnits( - collectibleInfoResponse.balance as BigNumberish, - collectibleInfoResponse.decimals ?? 0 - ) - )} + + + {isAddingCollectibleManually && ( + + + Collectible Address + + ) => { + setCollectibleManualAddress(ev.target.value) + }} + /> - - )} - + )} - + {isFetchingCollectibleInfo && collectibleManualAddress ? ( + + + + ) : ( + collectibleInfo && ( + + + {collectibleInfo.name ?? ''} + + + Your Balance: + + + {collectibleInfo.balance} + + + ) + )} + - - {!isAddingCollectibleManually && ( -