From 14dd0fe069c7664bf0742e3c6441784b42b20c4b Mon Sep 17 00:00:00 2001 From: RanaBug Date: Mon, 13 Jan 2025 11:42:43 +0000 Subject: [PATCH 1/3] nft fixes to recognise which type of nft --- .../components/SendAsset/SendAsset.tsx | 22 +-- src/apps/deposit/utils/blockchain.tsx | 128 +++++++++++++----- 2 files changed, 106 insertions(+), 44 deletions(-) diff --git a/src/apps/deposit/components/SendAsset/SendAsset.tsx b/src/apps/deposit/components/SendAsset/SendAsset.tsx index bfcdfd58..6f06f48a 100644 --- a/src/apps/deposit/components/SendAsset/SendAsset.tsx +++ b/src/apps/deposit/components/SendAsset/SendAsset.tsx @@ -5,7 +5,7 @@ import { useAppKitNetworkCore, useAppKitProvider, } from '@reown/appkit/react'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { IoMdReturnLeft } from 'react-icons/io'; // hooks @@ -37,16 +37,20 @@ const SendAsset = () => { const [error, setError] = useState(null); const [message, setMessage] = useState(null); - if (!selectedAsset || !address || !walletAddress) return null; - const assetType = - selectedAsset.type === 'AddedAsset' && selectedAsset.assetType === 'nft' - ? 'nft' - : 'token'; + (selectedAsset && 'name' in selectedAsset) || + selectedAsset?.assetType === 'token' + ? 'token' + : 'nft'; + + useEffect(() => { + if (assetType === 'nft') { + setAmount('1'); + } + }, [assetType]); + + if (!selectedAsset || !address || !walletAddress) return null; - if (assetType === 'nft') { - setAmount('1'); - } const handleSendTx = async () => { if (assetType === 'token') { try { diff --git a/src/apps/deposit/utils/blockchain.tsx b/src/apps/deposit/utils/blockchain.tsx index 2dcc0ee0..b0d9a5a9 100644 --- a/src/apps/deposit/utils/blockchain.tsx +++ b/src/apps/deposit/utils/blockchain.tsx @@ -389,54 +389,112 @@ export const transferNft = async ( accountAddress: string, pillarXAddress: string ): Promise => { + const chain = getNetworkViem(chainId); + const chainUrl = chainMapping[chain.name.toLowerCase() as Network] || null; + + if (!chainUrl) { + throw new Error(`Unsupported chain: ${chain.name}`); + } + try { const walletClient = createWalletClient({ - chain: getNetworkViem(Number(chainId)), + chain, transport: custom(walletProvider), }); - const isNft = - selectedAsset.type === 'AddedAsset' && selectedAsset.assetType === 'nft'; + const publicClient = createPublicClient({ + chain, + transport: http(chainUrl), + }); - if (!isNft) { - return ';'; - } + const supportsInterfaceABI = [ + { + name: 'supportsInterface', + type: 'function', + stateMutability: 'view', + inputs: [{ name: 'interfaceId', type: 'bytes4' }], + outputs: [{ name: '', type: 'bool' }], + }, + ]; + + const isNft = !( + (selectedAsset && 'name' in selectedAsset) || + selectedAsset?.assetType === 'token' + ); if (isNft) { - // Encode the function data - const calldataERC721 = encodeFunctionData({ - abi: ERC721_ABI, - functionName: 'safeTransferFrom', - args: [accountAddress, pillarXAddress, selectedAsset.tokenId], - }); + const checkContractType = async () => { + const ERC721_INTERFACE_ID = '0x80ac58cd'; + const ERC1155_INTERFACE_ID = '0xd9b67a26'; - const calldataERC1155 = encodeFunctionData({ - abi: ERC1155_ABI, - functionName: 'safeTransferFrom', - args: [ - accountAddress, - pillarXAddress, - selectedAsset.tokenId, - '1', - '0x', - ], - }); + try { + const isERC721 = await publicClient.readContract({ + address: selectedAsset.tokenAddress as `0x${string}`, + abi: supportsInterfaceABI, + functionName: 'supportsInterface', + args: [ERC721_INTERFACE_ID], + }); - // Try ERC721 transfer - try { - const txHash = await walletClient.sendTransaction({ - account: accountAddress as `0x${string}`, - to: selectedAsset.tokenAddress as `0x${string}`, - value: BigInt('0'), - data: calldataERC721, - }); + const isERC1155 = await publicClient.readContract({ + address: selectedAsset.tokenAddress as `0x${string}`, + abi: supportsInterfaceABI, + functionName: 'supportsInterface', + args: [ERC1155_INTERFACE_ID], + }); - return txHash; - } catch (errorERC721) { - console.error(`ERC721 transfer failed: ${errorERC721}`); + if (isERC721) { + return 'ERC721'; + } + if (isERC1155) { + return 'ERC1155'; + } + } catch (error) { + console.error('Error checking the ERC type:', error); + } + return '0'; + }; - // Fallback to ERC1155 transfer + const contractType = await checkContractType(); + + if (contractType === 'ERC721') { + // Try ERC721 transfer try { + // Encode the function data + const calldataERC721 = encodeFunctionData({ + abi: ERC721_ABI, + functionName: 'safeTransferFrom', + args: [accountAddress, pillarXAddress, selectedAsset.tokenId], + }); + + const txHash = await walletClient.sendTransaction({ + account: accountAddress as `0x${string}`, + to: selectedAsset.tokenAddress as `0x${string}`, + value: BigInt('0'), + data: calldataERC721, + }); + + return txHash; + } catch (errorERC721) { + console.warn(`ERC721 transfer failed: ${errorERC721}`); + } + } + + if (contractType === 'ERC1155') { + // Try ERC1155 transfer + try { + // Encode the function data + const calldataERC1155 = encodeFunctionData({ + abi: ERC1155_ABI, + functionName: 'safeTransferFrom', + args: [ + accountAddress, + pillarXAddress, + selectedAsset.tokenId, + '1', + '0x', + ], + }); + const txHash = await walletClient.sendTransaction({ account: accountAddress as `0x${string}`, to: selectedAsset.tokenAddress as `0x${string}`, From 5fde8edea61d6eaba55f7e8781957f7416406ad6 Mon Sep 17 00:00:00 2001 From: RanaBug Date: Mon, 13 Jan 2025 15:42:46 +0000 Subject: [PATCH 2/3] remove deposit for ERC1155 not supported for now --- .../components/SendAsset/SendAsset.tsx | 34 +++- src/apps/deposit/utils/blockchain.tsx | 165 +++++++++--------- 2 files changed, 112 insertions(+), 87 deletions(-) diff --git a/src/apps/deposit/components/SendAsset/SendAsset.tsx b/src/apps/deposit/components/SendAsset/SendAsset.tsx index 6f06f48a..85267b41 100644 --- a/src/apps/deposit/components/SendAsset/SendAsset.tsx +++ b/src/apps/deposit/components/SendAsset/SendAsset.tsx @@ -18,7 +18,11 @@ import { setDepositStep } from '../../reducer/depositSlice'; import { AddedAssets, BalanceInfo } from '../../types/types'; // utils -import { transferNft, transferTokens } from '../../utils/blockchain'; +import { + checkContractType, + transferNft, + transferTokens, +} from '../../utils/blockchain'; // components import Asset from '../Asset/Asset'; @@ -27,7 +31,8 @@ const SendAsset = () => { const { address } = useAppKitAccount(); const { chainId } = useAppKitNetworkCore(); const { walletProvider } = useAppKitProvider('eip155'); - const [amount, setAmount] = useState(''); + const [amount, setAmount] = useState(''); + const [nftType, setNftType] = useState(''); const walletAddress = useWalletAddress(); const dispatch = useAppDispatch(); const selectedAsset = useAppSelector( @@ -46,8 +51,17 @@ const SendAsset = () => { useEffect(() => { if (assetType === 'nft') { setAmount('1'); + const checkNftType = async () => { + const type = await checkContractType( + Number(chainId), + selectedAsset as AddedAssets + ); + setNftType(type); + }; + + checkNftType(); } - }, [assetType]); + }, [assetType, chainId, selectedAsset]); if (!selectedAsset || !address || !walletAddress) return null; @@ -145,9 +159,11 @@ const SendAsset = () => { />

- {assetType === 'token' - ? 'How much would you like to deposit in your PillarX Wallet?' - : 'Transfer the amount of 1 NFT'} + {assetType === 'token' && + 'How much would you like to deposit in your PillarX Wallet?'} + {assetType === 'nft' && + nftType === 'ERC721' && + 'Transfer the amount of 1 NFT'}

{assetType === 'token' && ( { /> )}
- {Number(amount) > 0 && ( + {Number(amount) > 0 && nftType !== 'ERC1155' ? ( + ) : ( +

+ We do not currently support ERC1155 deposit. +

)} )} diff --git a/src/apps/deposit/utils/blockchain.tsx b/src/apps/deposit/utils/blockchain.tsx index b0d9a5a9..4ff71952 100644 --- a/src/apps/deposit/utils/blockchain.tsx +++ b/src/apps/deposit/utils/blockchain.tsx @@ -382,13 +382,10 @@ export const transferTokens = async ( } }; -export const transferNft = async ( +export const checkContractType = async ( chainId: number, - walletProvider: Provider, - selectedAsset: BalanceInfo | AddedAssets, - accountAddress: string, - pillarXAddress: string -): Promise => { + selectedAsset: AddedAssets +) => { const chain = getNetworkViem(chainId); const chainUrl = chainMapping[chain.name.toLowerCase() as Network] || null; @@ -396,26 +393,63 @@ export const transferNft = async ( throw new Error(`Unsupported chain: ${chain.name}`); } - try { - const walletClient = createWalletClient({ - chain, - transport: custom(walletProvider), - }); + const ERC721_INTERFACE_ID = '0x80ac58cd'; + const ERC1155_INTERFACE_ID = '0xd9b67a26'; + const supportsInterfaceABI = [ + { + name: 'supportsInterface', + type: 'function', + stateMutability: 'view', + inputs: [{ name: 'interfaceId', type: 'bytes4' }], + outputs: [{ name: '', type: 'bool' }], + }, + ]; + + try { const publicClient = createPublicClient({ chain, transport: http(chainUrl), }); - const supportsInterfaceABI = [ - { - name: 'supportsInterface', - type: 'function', - stateMutability: 'view', - inputs: [{ name: 'interfaceId', type: 'bytes4' }], - outputs: [{ name: '', type: 'bool' }], - }, - ]; + const isERC721 = await publicClient.readContract({ + address: selectedAsset.tokenAddress as `0x${string}`, + abi: supportsInterfaceABI, + functionName: 'supportsInterface', + args: [ERC721_INTERFACE_ID], + }); + + const isERC1155 = await publicClient.readContract({ + address: selectedAsset.tokenAddress as `0x${string}`, + abi: supportsInterfaceABI, + functionName: 'supportsInterface', + args: [ERC1155_INTERFACE_ID], + }); + + if (isERC721) { + return 'ERC721'; + } + if (isERC1155) { + return 'ERC1155'; + } + } catch (error) { + console.error('Error checking the ERC type:', error); + } + return '0'; +}; + +export const transferNft = async ( + chainId: number, + walletProvider: Provider, + selectedAsset: BalanceInfo | AddedAssets, + accountAddress: string, + pillarXAddress: string +): Promise => { + try { + const walletClient = createWalletClient({ + chain: getNetworkViem(chainId), + transport: custom(walletProvider), + }); const isNft = !( (selectedAsset && 'name' in selectedAsset) || @@ -423,38 +457,7 @@ export const transferNft = async ( ); if (isNft) { - const checkContractType = async () => { - const ERC721_INTERFACE_ID = '0x80ac58cd'; - const ERC1155_INTERFACE_ID = '0xd9b67a26'; - - try { - const isERC721 = await publicClient.readContract({ - address: selectedAsset.tokenAddress as `0x${string}`, - abi: supportsInterfaceABI, - functionName: 'supportsInterface', - args: [ERC721_INTERFACE_ID], - }); - - const isERC1155 = await publicClient.readContract({ - address: selectedAsset.tokenAddress as `0x${string}`, - abi: supportsInterfaceABI, - functionName: 'supportsInterface', - args: [ERC1155_INTERFACE_ID], - }); - - if (isERC721) { - return 'ERC721'; - } - if (isERC1155) { - return 'ERC1155'; - } - } catch (error) { - console.error('Error checking the ERC type:', error); - } - return '0'; - }; - - const contractType = await checkContractType(); + const contractType = await checkContractType(chainId, selectedAsset); if (contractType === 'ERC721') { // Try ERC721 transfer @@ -462,7 +465,7 @@ export const transferNft = async ( // Encode the function data const calldataERC721 = encodeFunctionData({ abi: ERC721_ABI, - functionName: 'safeTransferFrom', + functionName: 'transferFrom', args: [accountAddress, pillarXAddress, selectedAsset.tokenId], }); @@ -480,33 +483,35 @@ export const transferNft = async ( } if (contractType === 'ERC1155') { - // Try ERC1155 transfer - try { - // Encode the function data - const calldataERC1155 = encodeFunctionData({ - abi: ERC1155_ABI, - functionName: 'safeTransferFrom', - args: [ - accountAddress, - pillarXAddress, - selectedAsset.tokenId, - '1', - '0x', - ], - }); - - const txHash = await walletClient.sendTransaction({ - account: accountAddress as `0x${string}`, - to: selectedAsset.tokenAddress as `0x${string}`, - value: BigInt('0'), - data: calldataERC1155, - }); - - return txHash; - } catch (errorERC1155) { - console.error(`ERC1155 transfer also failed: ${errorERC1155}`); - return 'Error transferring NFT: both ERC721 and ERC1155 failed.'; - } + return 'ERC1155 deposit not supported.'; + // // TODO when ERC1155 is supported + // // Try ERC1155 transfer + // try { + // // Encode the function data + // const calldataERC1155 = encodeFunctionData({ + // abi: ERC1155_ABI, + // functionName: 'safeTransferFrom', + // args: [ + // accountAddress, + // pillarXAddress, + // selectedAsset.tokenId, + // '1', + // '0x', + // ], + // }); + + // const txHash = await walletClient.sendTransaction({ + // account: accountAddress as `0x${string}`, + // to: selectedAsset.tokenAddress as `0x${string}`, + // value: BigInt('0'), + // data: calldataERC1155, + // }); + + // return txHash; + // } catch (errorERC1155) { + // console.error(`ERC1155 transfer also failed: ${errorERC1155}`); + // return 'Error transferring NFT: both ERC721 and ERC1155 failed.'; + // } } } return 'Selected asset is not an NFT. Transfer aborted.'; From 8609a7f59e77da5a67dc69d5f647cf0355e96e1d Mon Sep 17 00:00:00 2001 From: RanaBug Date: Mon, 13 Jan 2025 17:19:44 +0000 Subject: [PATCH 3/3] minor text dixes --- src/apps/deposit/components/SendAsset/SendAsset.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/apps/deposit/components/SendAsset/SendAsset.tsx b/src/apps/deposit/components/SendAsset/SendAsset.tsx index 85267b41..9ef5579c 100644 --- a/src/apps/deposit/components/SendAsset/SendAsset.tsx +++ b/src/apps/deposit/components/SendAsset/SendAsset.tsx @@ -163,7 +163,7 @@ const SendAsset = () => { 'How much would you like to deposit in your PillarX Wallet?'} {assetType === 'nft' && nftType === 'ERC721' && - 'Transfer the amount of 1 NFT'} + 'Transfer this NFT'}

{assetType === 'token' && ( { ) : (

- We do not currently support ERC1155 deposit. + Sorry, we do not currently support ERC1155 transfers. You can + manually transfer this NFT to your PillarX wallet address:{' '} + {walletAddress}

)}