Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ import { Controller, useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import {
useWeb3Connection,
useChainId,
useNonFungibleTokenContract,
useAccount,
useWeb3State,
useTrustedNonFungibleTokens,
useCurrentWeb3NetworkPluginID,
useWeb3Hub,
Web3Helper,
} from '@masknet/plugin-infra/web3'
import { SchemaType } from '@masknet/web3-shared-evm'
import type { ChainId } from '@masknet/web3-shared-evm'

export interface AddCollectibleDialogProps {
selectedNetwork: Web3Helper.NetworkDescriptorAll
open: boolean
onClose: () => void
}
Expand All @@ -34,22 +35,24 @@ enum FormErrorType {
NotExist = 'NOT_EXIST',
}

export const AddCollectibleDialog = memo<AddCollectibleDialogProps>(({ open, onClose }) => {
export const AddCollectibleDialog = memo<AddCollectibleDialogProps>(({ open, onClose, selectedNetwork }) => {
const currentNetworkPluginID = useCurrentWeb3NetworkPluginID()
const account = useAccount(NetworkPluginID.PLUGIN_EVM)
const { Token } = useWeb3State<'all'>()
const trustedNonFungibleTokens = useTrustedNonFungibleTokens(currentNetworkPluginID)
const hub = useWeb3Hub()
const connection = useWeb3Connection(NetworkPluginID.PLUGIN_EVM)
const chainId = useChainId(NetworkPluginID.PLUGIN_EVM)

const [address, setAddress] = useState('')
const [tokenId, setTokenId] = useState('')

const { value, loading } = useNonFungibleTokenContract(NetworkPluginID.PLUGIN_EVM, address)
const { value: contract, loading } = useNonFungibleTokenContract(NetworkPluginID.PLUGIN_EVM, address, undefined, {
chainId: selectedNetwork.chainId as ChainId,
})

const onSubmit = useCallback(async () => {
if (loading || !account || !value || !hub?.getNonFungibleAsset) return
if (loading || !account || !hub?.getNonFungibleAsset) return
if (address && tokenId && !contract) throw new Error(FormErrorType.NotExist)

// If the NonFungible token is added
const tokenInDB = trustedNonFungibleTokens.find(
Expand All @@ -58,16 +61,17 @@ export const AddCollectibleDialog = memo<AddCollectibleDialogProps>(({ open, onC
)
if (tokenInDB) throw new Error(FormErrorType.Added)

const tokenAsset = await hub?.getNonFungibleAsset(address ?? '', tokenId)
const token = await connection?.getNonFungibleToken(address ?? '', tokenId, SchemaType.ERC721)
const tokenAsset = await hub?.getNonFungibleAsset(address ?? '', tokenId, { chainId: selectedNetwork.chainId })
const token = await connection?.getNonFungibleToken(address ?? '', tokenId, undefined, {
chainId: selectedNetwork.chainId as ChainId,
})
const tokenDetailed = { ...token, ...tokenAsset }
const isOwner = await connection?.getNonFungibleTokenOwnership(address, account, tokenId, undefined, {
chainId: selectedNetwork.chainId as ChainId,
})

// If the NonFungible token is belong this account
if (
(tokenDetailed && !isSameAddress(tokenDetailed?.contract?.owner, account)) ||
!tokenDetailed ||
!tokenDetailed.contract?.owner
) {
if (!isOwner) {
throw new Error(FormErrorType.NotExist)
} else {
await Token?.addToken?.(tokenDetailed)
Expand All @@ -77,7 +81,7 @@ export const AddCollectibleDialog = memo<AddCollectibleDialogProps>(({ open, onC
account,
address,
tokenId,
value,
contract,
loading,
hub?.getNonFungibleAsset,
connection?.getNonFungibleToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const Assets = memo<TokenAssetsProps>(({ network }) => {
<Tab key={key} value={key} label={assetTabsLabel[key]} />
))}
</TabList>
{pluginId === NetworkPluginID.PLUGIN_EVM && (
{pluginId === NetworkPluginID.PLUGIN_EVM && (currentTab === AssetTab.Token ? true : !!network) && (
<Button
size="small"
color="secondary"
Expand Down Expand Up @@ -109,7 +109,9 @@ export const Assets = memo<TokenAssetsProps>(({ network }) => {
</TabPanel>
</TabContext>
</ContentContainer>
{addCollectibleOpen && <AddCollectibleDialog open onClose={() => setAddCollectibleOpen(false)} />}
{addCollectibleOpen && network && (
<AddCollectibleDialog selectedNetwork={network} open onClose={() => setAddCollectibleOpen(false)} />
)}
</>
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const CollectibleList = memo<CollectibleListProps>(({ selectedChain }) =>
navigate(DashboardRoutes.WalletsTransfer, {
state: {
type: TransferTab.Collectibles,
erc721Token: detail,
nonFungibleToken: detail,
},
})
},
Expand Down Expand Up @@ -146,12 +146,7 @@ export const CollectibleListUI = memo<CollectibleListUIProps>(
<div className={classes.root}>
{dataSource.map((x, index) => (
<div className={classes.card} key={index}>
<CollectibleCard
token={x}
renderOrder={index}
// TODO: transfer not support multi chain, should remove is after supported
onSend={() => onSend(x as unknown as any)}
/>
<CollectibleCard token={x} renderOrder={index} onSend={() => onSend(x)} />
</div>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import {
multipliedBy,
NetworkPluginID,
} from '@masknet/web3-shared-base'
import { SchemaType, formatWeiToEther, NetworkType, ChainId, explorerResolver } from '@masknet/web3-shared-evm'
import {
SchemaType,
formatWeiToEther,
NetworkType,
ChainId,
explorerResolver,
isValidAddress,
} from '@masknet/web3-shared-evm'
// import { useERC721TokenDetailedOwnerList } from '@masknet/web3-providers'
import { FormattedAddress } from '@masknet/shared'
import { useDashboardI18N } from '../../../../locales'
Expand Down Expand Up @@ -38,6 +45,7 @@ import {
useWeb3State,
useNativeToken,
useNativeTokenPrice,
useWeb3Connection,
} from '@masknet/plugin-infra/web3'
import { RightIcon } from '@masknet/icons'
import { useGasLimit, useNonFungibleOwnerTokens, useTokenTransferCallback } from '@masknet/plugin-infra/web3-evm'
Expand All @@ -60,10 +68,12 @@ export const TransferERC721 = memo(() => {
const t = useDashboardI18N()
const chainId = useChainId(NetworkPluginID.PLUGIN_EVM)
const anchorEl = useRef<HTMLDivElement | null>(null)
const connection = useWeb3Connection(NetworkPluginID.PLUGIN_EVM)

const { state } = useLocation() as {
state: { erc721Token?: NonFungibleToken<ChainId, SchemaType>; type?: TransferTab } | null
state: { nonFungibleToken?: NonFungibleToken<ChainId, SchemaType>; type?: TransferTab } | null
}

const { classes } = useStyles()
const [defaultToken, setDefaultToken] = useState<NonFungibleToken<ChainId, SchemaType> | null>(null)
const navigate = useNavigate()
Expand Down Expand Up @@ -108,14 +118,13 @@ export const TransferERC721 = memo(() => {

useEffect(() => {
if (!state) return
if (!state.erc721Token || state.type !== TransferTab.Collectibles) return
if (state.erc721Token.chainId !== chainId) return
if (!isSameAddress(contract?.address, state.erc721Token.address)) return
if (!state.nonFungibleToken || state.type !== TransferTab.Collectibles) return
if (state.nonFungibleToken.chainId !== chainId) return

setContract(state.erc721Token.contract)
setValue('contract', state.erc721Token.contract?.name ?? '')
setValue('tokenId', state.erc721Token.tokenId)
setDefaultToken(state.erc721Token)
setContract(state.nonFungibleToken.contract)
setValue('contract', state.nonFungibleToken.contract?.name ?? '')
setValue('tokenId', state.nonFungibleToken.tokenId)
setDefaultToken(state.nonFungibleToken)
}, [state])

const allFormFields = watch()
Expand All @@ -130,25 +139,26 @@ export const TransferERC721 = memo(() => {

// #region check contract address and account address
useAsync(async () => {
// const recipient = allFormFields.recipient
// setRecipientError(null)
// if (!recipient && !registeredAddress) return
// if (!isValidAddress(recipient) && !isValidAddress(registeredAddress)) return
// clearErrors()
// if (isSameAddress(recipient, account) || isSameAddress(registeredAddress, account)) {
// setRecipientError({
// type: 'account',
// message: t.wallets_transfer_error_same_address_with_current_account(),
// })
// }
// const result = await EVM_RPC.getCode(recipient)
// if (result !== '0x') {
// setRecipientError({
// type: 'contractAddress',
// message: t.wallets_transfer_error_is_contract_address(),
// })
// }
}, [allFormFields.recipient, clearErrors, registeredAddress])
const recipient = allFormFields.recipient
setRecipientError(null)
if (!recipient && !registeredAddress) return
if (!isValidAddress(recipient) && !isValidAddress(registeredAddress)) return
clearErrors()
if (isSameAddress(recipient, account) || isSameAddress(registeredAddress, account)) {
setRecipientError({
type: 'account',
message: t.wallets_transfer_error_same_address_with_current_account(),
})
}
if (!connection) return
const result = await connection?.getCode(recipient)
if (result !== '0x') {
setRecipientError({
type: 'contractAddress',
message: t.wallets_transfer_error_is_contract_address(),
})
}
}, [allFormFields.recipient, clearErrors, registeredAddress, connection])
// #endregion

const erc721GasLimit = useGasLimit(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const Transfer = memo(() => {
const { state } = useLocation() as {
state: {
token?: FungibleToken<ChainId, SchemaType>
erc721Token?: FungibleToken<ChainId, SchemaType>
nonFungibleToken?: FungibleToken<ChainId, SchemaType>
type?: TransferTab
} | null
}
Expand All @@ -34,7 +34,7 @@ export const Transfer = memo(() => {

useEffect(() => {
if (!state) return
if (!state.erc721Token || state.type !== TransferTab.Collectibles) return
if (!state.nonFungibleToken || state.type !== TransferTab.Collectibles) return

setTab(TransferTab.Collectibles)
}, [state])
Expand Down
4 changes: 3 additions & 1 deletion packages/plugins/EVM/src/state/Connection/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,9 @@ class Connection implements EVM_Connection {

if (actualSchema !== SchemaType.ERC1155) {
const contract = await this.getERC721Contract(address, options)
ownerId = await contract?.methods.ownerOf(tokenId).call()
try {
ownerId = await contract?.methods.ownerOf(tokenId).call()
} catch {}
}

return createNonFungibleToken<ChainId, SchemaType>(
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/EVM/src/state/Hub/hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class Hub implements EVM_Hub {
account: string,
options?: HubOptions<ChainId> | undefined,
): Promise<Pageable<NonFungibleTokenCollection<ChainId>>> {
return OpenSea.getCollections(account, options)
return OpenSea.getCollections(account, { ...options, chainId: options?.chainId ?? this.chainId })
}
getFungibleTokenPrice(
chainId: ChainId,
Expand Down
1 change: 1 addition & 0 deletions packages/web3-providers/src/opensea/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ export class OpenSeaAPI implements NonFungibleTokenAPI.Provider<ChainId, SchemaT
address: string,
{ chainId = ChainId.Mainnet, indicator, size = 50 }: HubOptions<ChainId> = {},
) {
if (chainId !== ChainId.Mainnet) return createPageable([], createIndicator(indicator))
const response = await fetchFromOpenSea<OpenSeaCollection[]>(
urlcat('/api/v1/collections', {
asset_owner: address,
Expand Down