diff --git a/packages/web3-contracts/abis/ERC1155.json b/packages/web3-contracts/abis/ERC1155.json new file mode 100644 index 000000000000..6e166b582309 --- /dev/null +++ b/packages/web3-contracts/abis/ERC1155.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/web3-shared/evm/contracts/index.ts b/packages/web3-shared/evm/contracts/index.ts index b2d0c88afead..d4c4b3335ed6 100644 --- a/packages/web3-shared/evm/contracts/index.ts +++ b/packages/web3-shared/evm/contracts/index.ts @@ -1,3 +1,4 @@ export * from './useERC20TokenContract' export * from './useERC721TokenContract' export * from './useERC721TokenContracts' +export * from './useERC1155TokenContract' diff --git a/packages/web3-shared/evm/contracts/useERC1155TokenContract.ts b/packages/web3-shared/evm/contracts/useERC1155TokenContract.ts new file mode 100644 index 000000000000..a4b9512b8507 --- /dev/null +++ b/packages/web3-shared/evm/contracts/useERC1155TokenContract.ts @@ -0,0 +1,7 @@ +import ERC1155 from '@masknet/web3-contracts/abis/ERC1155.json' +import type { AbiItem } from 'web3-utils' +import { useContract } from '../hooks' + +export function useERC1155TokenContract(address: string) { + return useContract(address, ERC1155 as AbiItem[]) +} diff --git a/packages/web3-shared/evm/hooks/index.ts b/packages/web3-shared/evm/hooks/index.ts index 489ef4a6a64a..7761258ba2ce 100644 --- a/packages/web3-shared/evm/hooks/index.ts +++ b/packages/web3-shared/evm/hooks/index.ts @@ -68,3 +68,5 @@ export * from './useImageChecker' export * from './useTrustedERC20Tokens' export * from './useTrustERC20TokenCallback' export * from './useAddERC20TokenCallback' + +export * from './useEthereumTokenType' diff --git a/packages/web3-shared/evm/hooks/useEthereumTokenType.ts b/packages/web3-shared/evm/hooks/useEthereumTokenType.ts new file mode 100644 index 000000000000..c5615bcab09b --- /dev/null +++ b/packages/web3-shared/evm/hooks/useEthereumTokenType.ts @@ -0,0 +1,42 @@ +import { useAsyncRetry } from 'react-use' +import { useERC1155TokenContract, useERC721TokenContract } from '../contracts' +import { useWeb3 } from './useWeb3' + +import { useERC165 } from '.' +import { EthereumTokenType } from '../types' + +const ERC721_ENUMERABLE_INTERFACE_ID = '0x780e9d63' +const ERC1155_ENUMERABLE_INTERFACE_ID = '0xd9b67a26' + +function useCheckContract(address: string) { + const web3 = useWeb3() + return useAsyncRetry(async () => { + const result = await web3.eth.getCode(address) + return result !== '0x' + }, [address, web3]) +} + +function useCheckERC721(address: string) { + const erc721Contract = useERC721TokenContract(address) + return useERC165(erc721Contract, address, ERC721_ENUMERABLE_INTERFACE_ID) +} + +function useCheckERC1155(address: string) { + const erc1155Contract = useERC1155TokenContract(address) + return useERC165(erc1155Contract, address, ERC1155_ENUMERABLE_INTERFACE_ID) +} + +export function useEthereumTokenType(address: string): EthereumTokenType | undefined { + const { value: isContract, loading: loadingContract } = useCheckContract(address) + const { value: isERC721, loading: loadingERC721 } = useCheckERC721(address) + const { value: isERC1155, loading: loadingERC1155 } = useCheckERC1155(address) + + if (loadingERC1155 || loadingERC721 || loadingContract) return + return isERC1155 + ? EthereumTokenType.ERC1155 + : isERC721 + ? EthereumTokenType.ERC721 + : isContract + ? EthereumTokenType.ERC20 + : undefined +}