diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 59f6af2..7b723a2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,6 +22,7 @@ jobs: REACT_APP_SERVICE_URL: ${{ secrets.REACT_APP_SERVICE_URL }} REACT_APP_RPC_URL_1: ${{ secrets.REACT_APP_RPC_URL_1 }} REACT_APP_RPC_URL_4: ${{ secrets.REACT_APP_RPC_URL_4 }} + NODE_ENV: production run: SKIP_PREFLIGHT_CHECK=true yarn build - name: 💾 Create artifact diff --git a/package.json b/package.json index 3995437..7b97518 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fluuuid/nft-marketplace", - "version": "1.1.0", + "version": "2.0.0", "homepage": "https://nft.s2paganini.com", "dependencies": { "@ethersproject/constants": "^5.4.0", diff --git a/src/components/Gallery/Gallery.tsx b/src/components/Gallery/Gallery.tsx index d8116cd..d6dfc9a 100644 --- a/src/components/Gallery/Gallery.tsx +++ b/src/components/Gallery/Gallery.tsx @@ -1,5 +1,5 @@ import { BigNumber, utils } from 'ethers' -import { useEffect, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { Box, Button, Flex, Grid, Heading } from 'theme-ui' import { useAppState } from '../../state' import { Token } from '..' @@ -8,14 +8,16 @@ export type GalleryProps = {} type StateOrder = 'price' | 'alpha' const Gallery = () => { - const { user, tokensOnSale, updateTokensOnSale } = useAppState() + const { user, tokensOnSale } = useAppState() + const updateTokensOnSale = useAppState( + useCallback(({ updateTokensOnSale }) => updateTokensOnSale, []) + ) + const [order, setOrder] = useState('alpha') useEffect(() => { updateTokensOnSale() - }, [updateTokensOnSale, user?.ownedTokens]) - - console.log(user?.ownedTokens) + }, [updateTokensOnSale]) return ( diff --git a/src/components/Profile/Profile.stories.tsx b/src/components/Profile/Profile.stories.tsx deleted file mode 100644 index b40c3d1..0000000 --- a/src/components/Profile/Profile.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Story, Meta } from '@storybook/react/types-6-0' - -import { Profile, ProfileProps } from './Profile' - -export default { - title: 'Views/Profile', - component: Profile, - parameters: { - layout: 'padded', - }, -} as Meta - -const Template: Story = args => - -export const Default = Template.bind({}) -Default.args = {} as ProfileProps diff --git a/src/components/Profile/Profile.test.tsx b/src/components/Profile/Profile.test.tsx deleted file mode 100644 index 53db9df..0000000 --- a/src/components/Profile/Profile.test.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { render } from '@testing-library/react' -import { Profile } from './Profile' - -test(`Renders`, () => { - render() -}) diff --git a/src/components/Profile/Profile.tsx b/src/components/Profile/Profile.tsx deleted file mode 100644 index 5ac263b..0000000 --- a/src/components/Profile/Profile.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { utils } from 'ethers' -import { Text, Box, Heading, Grid, Divider } from 'theme-ui' -import { Token } from '..' -import { useAppState } from '../../state' - -export type ProfileProps = {} - -const Profile = () => { - const { user, tokensOnSale } = useAppState() - - if (!user) return null - - const { address, balance, ownedTokens } = user - - return ( - - My Profile - - - - Address - - {address} - - - - Balance - - Ξ {balance} - - - - - {ownedTokens && ownedTokens.length > 0 ? ( - - - My items{' '} - - ({ownedTokens.length} item) - - - - {ownedTokens.map((t, index) => ( - utils.formatUnits(a.id) === utils.formatUnits(t.id)) - } - onSale - onTransfer - token={t} - key={index} - /> - ))} - - - ) : ( - ownedTokens && ( - - You don't own any NFT tokens - - ) - )} - - - ) -} - -export { Profile } diff --git a/src/components/Profile/index.ts b/src/components/Profile/index.ts deleted file mode 100644 index ea36afc..0000000 --- a/src/components/Profile/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Profile' diff --git a/src/components/Token/Token.tsx b/src/components/Token/Token.tsx index aef320c..a5a7870 100644 --- a/src/components/Token/Token.tsx +++ b/src/components/Token/Token.tsx @@ -1,4 +1,4 @@ -import { FormEvent, MouseEvent, useState, useEffect } from 'react' +import { FormEvent, MouseEvent, useState } from 'react' import { utils, BigNumber, constants } from 'ethers' import { Spinner, @@ -15,9 +15,8 @@ import { } from 'theme-ui' import useSWR from 'swr' import { useAppState } from '../../state' -import { fetcherMetadata } from '../../utils/fetchers' -import { METADATA_API, toShort } from '../../utils' -import { useWeb3React } from '@web3-react/core' +import { fetcherMetadata, fetchOwner } from '../../utils/fetchers' +import { formatPriceEth, METADATA_API, toShort } from '../../utils' export type TokenProps = { id: string @@ -39,27 +38,13 @@ const Token = ({ token, isOnSale, onTransfer, onBuy, onSale }: TokenCompProps) = const [onSaleActive, setOnSale] = useState(false) const [address, setAddress] = useState('') const [price, setPrice] = useState('') - const [owner, setOwner] = useState('') - const { - user, - ethPrice, - contract, - updateTokensOnSale, - setUser, - transferToken, - buyToken, - setTokenSale, - } = useAppState() - const { library } = useWeb3React() + const { user, ethPrice, contractDetails, transferToken, buyToken, setTokenSale } = useAppState() const onTransferClick = async (e: FormEvent | MouseEvent) => { e.preventDefault() - try { - if (utils.isAddress(address) && onTransfer) { - await transferToken(token.id, address) - } - } catch (e) { - throw new Error(e) + if (onTransfer && utils.isAddress(address)) { + transferToken(token.id, address) + setTransfer(false) } } @@ -73,33 +58,16 @@ const Token = ({ token, isOnSale, onTransfer, onBuy, onSale }: TokenCompProps) = if (!onSale) return try { await setTokenSale(token.id, utils.parseEther(price), true) - await updateTokensOnSale() - await setUser(library) + setOnSale(false) } catch (e) { throw new Error(e) } } - useEffect(() => { - const loadOwner = async () => { - try { - const owner = await contract?.payload.ownerOf(token.id) - setOwner(owner) - } catch (e) { - // throw new Error(e) - console.error(e) - } - } - - loadOwner() - }, [contract, token.id]) - + const { data: owner } = useSWR(token.id, fetchOwner) const { data } = useSWR(`${METADATA_API}/token/${token.id}`, fetcherMetadata) - const tokenPriceEth = new Intl.NumberFormat('us-GB', { - style: 'currency', - currency: 'USD', - }).format(Number(utils.formatEther(token.price)) * Number(ethPrice)) + const tokenPriceEth = formatPriceEth(token.price, ethPrice) if (!data) return ( @@ -127,28 +95,30 @@ const Token = ({ token, isOnSale, onTransfer, onBuy, onSale }: TokenCompProps) = ({tokenPriceEth}) - - - Owner - - - {toShort(owner)} - - + {owner && !onTransfer && ( + + + Owner + + + {toShort(owner)} + + + )} View on Opensea.io diff --git a/src/components/TransactionProgress/TransactionProgress.tsx b/src/components/TransactionProgress/TransactionProgress.tsx index e6d001e..1301348 100644 --- a/src/components/TransactionProgress/TransactionProgress.tsx +++ b/src/components/TransactionProgress/TransactionProgress.tsx @@ -1,39 +1,58 @@ -import { useWeb3React } from '@web3-react/core' -import { useEffect } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { Card, Flex, Spinner } from 'theme-ui' import { useAppState } from '../../state' import { toShort } from '../../utils' const TransactionProgress = () => { - const { transaction, user, setTransaction, setUser, updateTokensOnSale } = useAppState() + const { setTransaction, setUser, updateTokensOnSale } = useAppState( + useCallback( + ({ setTransaction, setUser, updateTokensOnSale }) => ({ + setTransaction, + setUser, + updateTokensOnSale, + }), + [] + ) + ) + + const transactionRef = useRef(useAppState.getState().transaction) + const [loading, setLoading] = useState(false) - const { library } = useWeb3React() + const update = useCallback(async () => { + await setUser() + setTransaction(undefined) + updateTokensOnSale() + setLoading(false) + }, [setTransaction, setUser, updateTokensOnSale]) useEffect(() => { - const loadTransaction = async () => { - if (!user || !user.address || !transaction) return - - const receipt = await transaction.wait() - if (receipt.confirmations >= 1) { - await setUser(library) - setTransaction(undefined) - updateTokensOnSale() - } else { - throw new Error(receipt) + useAppState.subscribe(async ({ transaction }) => { + try { + transactionRef.current = transaction + if (!transaction) return + setLoading(true) + const receipt = await transaction.wait() + if (receipt.confirmations >= 1) { + update() + } + } catch (e) { + console.log('transaction', e) + setLoading(false) } - } + }) - loadTransaction() - }, [transaction, library, user, setTransaction, setUser, updateTokensOnSale]) - - console.log('asdasdasd', transaction) + return () => { + useAppState.destroy() + } + }, [update]) - if (!transaction) return null + if (!loading) return null return ( - Transaction: {toShort(transaction.hash)} + Transaction:{' '} + {toShort(transactionRef.current.hash)} ) diff --git a/src/components/index.ts b/src/components/index.ts index a87863d..7126346 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,6 +1,5 @@ export * from './Token' export * from './Header' -export * from './Profile' export * from './Gallery' export * from './ContractDetails' export * from './MetamaskLogin' diff --git a/src/index.tsx b/src/index.tsx index f2ff3b0..cc755ca 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,6 +10,7 @@ import theme from './theme' Sentry.init({ dsn: 'https://06951a956c7a4a6db2f776b1bc697efd@o72860.ingest.sentry.io/5842491', integrations: [new Integrations.BrowserTracing()], + enabled: process.env.NODE_ENV !== 'development', // Set tracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. diff --git a/src/layout/App.tsx b/src/layout/App.tsx deleted file mode 100644 index 4fb9b20..0000000 --- a/src/layout/App.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Container } from 'theme-ui' -import { useWeb3React } from '@web3-react/core' -import { Gallery, TransactionProgress, Login } from '../components' -import { useAppState } from '../state' - -const App = () => { - const { user } = useAppState() - const { active } = useWeb3React() - - return ( - - {!user && } - - {user && active && ( - <> - - - - )} - - ) -} - -export default App diff --git a/src/layout/Connect.tsx b/src/layout/Connect.tsx index a108c96..64c597b 100644 --- a/src/layout/Connect.tsx +++ b/src/layout/Connect.tsx @@ -6,7 +6,7 @@ import { import { UserRejectedRequestError as UserRejectedRequestErrorWalletConnect } from '@web3-react/walletconnect-connector' import { FC, useEffect } from 'react' -import { Text, Container, Heading } from 'theme-ui' +import { Text, Heading } from 'theme-ui' import useSWR from 'swr' import { useEagerConnect, useInactiveListener } from '../hooks/web3' import { ETHSCAN_API } from '../utils' @@ -32,14 +32,10 @@ function getErrorMessage(error: Error) { } const Connect: FC = ({ children }) => { - const { activatingConnector, setEthPrice, setContract, setUser } = useAppState() + const { activatingConnector, setContract, setUser } = useAppState() const { library, chainId, account, error } = useWeb3React() - const { data: ethPrice } = useSWR(ETHSCAN_API, fetcherETHUSD) - - useEffect(() => { - setEthPrice(ethPrice) - }, [ethPrice, setEthPrice]) + useSWR(ETHSCAN_API, fetcherETHUSD) useEffect(() => { if (!chainId || !account || !library) return @@ -47,7 +43,7 @@ const Connect: FC = ({ children }) => { const update = async () => { try { await setContract(library, chainId) - await setUser(library, account) + setUser(account) } catch (e) { console.log(e) } @@ -62,10 +58,10 @@ const Connect: FC = ({ children }) => { return ( <> {error ? ( - + <> ❌ Something is not right {getErrorMessage(error)} - + ) : ( children )} @@ -73,4 +69,4 @@ const Connect: FC = ({ children }) => { ) } -export default Connect +export { Connect } diff --git a/src/layout/Error.tsx b/src/layout/Error.tsx index 8c4e755..e751161 100644 --- a/src/layout/Error.tsx +++ b/src/layout/Error.tsx @@ -1,23 +1,21 @@ -import { Box, Flex, Image, Container, Text, Link, Heading } from 'theme-ui' +import { Box, Flex, Image, Text, Link, Heading } from 'theme-ui' const Error = () => { return ( - - - - - Metamask not installed - - Go to{' '} - - https://metamask.io - {' '} - to install it. - - - - + + + + Metamask not installed + + Go to{' '} + + https://metamask.io + {' '} + to install it. + + + ) } -export default Error +export { Error } diff --git a/src/layout/Marketplace.tsx b/src/layout/Marketplace.tsx new file mode 100644 index 0000000..ca5d76a --- /dev/null +++ b/src/layout/Marketplace.tsx @@ -0,0 +1,17 @@ +import { useWeb3React } from '@web3-react/core' +import { Gallery, Login } from '../components' +import { useAppState } from '../state' + +const Marketplace = () => { + const { user } = useAppState() + const { active } = useWeb3React() + + return ( + <> + {!user && } + {user && active && } + + ) +} + +export { Marketplace } diff --git a/src/layout/Profile.tsx b/src/layout/Profile.tsx index 44ce004..dc808fc 100644 --- a/src/layout/Profile.tsx +++ b/src/layout/Profile.tsx @@ -1,12 +1,68 @@ -import { Container } from 'theme-ui' -import { Profile } from '../components' +import { utils } from 'ethers' +import { Text, Box, Heading, Grid, Divider } from 'theme-ui' +import { Token } from '../components' +import { useAppState } from '../state' + +export type ProfileProps = {} + +const Profile = () => { + const { user, tokensOnSale } = useAppState() + + if (!user) return null + + const { address, balance, ownedTokens } = user -const ProfilePage = () => { return ( - - - + + My Profile + + + + Address + + {address} + + + + Balance + + Ξ {balance} + + + + + {ownedTokens && ownedTokens.length > 0 ? ( + + + My items{' '} + + ({ownedTokens.length} item) + + + + {ownedTokens.map((t, index) => ( + utils.formatUnits(a.id) === utils.formatUnits(t.id)) + } + onSale + onTransfer + token={t} + key={index} + /> + ))} + + + ) : ( + ownedTokens && ( + + You don't own any NFT tokens + + ) + )} + + ) } -export default ProfilePage +export { Profile } diff --git a/src/layout/Root.tsx b/src/layout/Root.tsx index 82d9cf6..5577f59 100644 --- a/src/layout/Root.tsx +++ b/src/layout/Root.tsx @@ -2,8 +2,9 @@ import { BrowserRouter as Router, Switch, Route } from 'react-router-dom' import { Web3ReactProvider } from '@web3-react/core' import { Web3Provider } from '@ethersproject/providers' -import { App, Profile, Connect } from './' -import { Header, PrivateRoute } from '../components' +import { Marketplace, Profile, Connect } from './' +import { Header, PrivateRoute, TransactionProgress } from '../components' +import { Container } from 'theme-ui' function getLibrary(provider: any): Web3Provider { const library = new Web3Provider(provider) @@ -17,14 +18,17 @@ const Root = () => {
- - - - + + + + + + + ) } -export default Root +export { Root } diff --git a/src/layout/index.ts b/src/layout/index.ts index 9f50453..eed1884 100644 --- a/src/layout/index.ts +++ b/src/layout/index.ts @@ -1,5 +1,5 @@ -export { default as App } from './App' -export { default as Error } from './Error' -export { default as Root } from './Root' -export { default as Profile } from './Profile' -export { default as Connect } from './Connect' +export * from './Marketplace' +export * from './Error' +export * from './Root' +export * from './Profile' +export * from './Connect' diff --git a/src/state/state.tsx b/src/state/state.tsx index 9ade8ba..22f40d0 100644 --- a/src/state/state.tsx +++ b/src/state/state.tsx @@ -1,18 +1,19 @@ import NFTT from '@fluuuid/nft-contracts/build/contracts/NFTT.json' import create from 'zustand' -import { BigNumber, Contract, utils } from 'ethers' +import { BigNumber, Contract, utils, Event } from 'ethers' import { TokenProps } from '../components/Token' -import { ContractProps, UserProps } from '../types' -import listTokensFrom from '../utils/listTokensFrom' +import { ContractPropsDetails, UserProps } from '../types' export interface StateContext { isAuthenticated: boolean - contract?: ContractProps + contract?: Contract + contractDetails?: ContractPropsDetails user?: UserProps tokensOnSale?: TokenProps[] ethPrice?: string activatingConnector?: any transaction?: any + library?: any setAuthenticated(authenticated: boolean): void setContract(library: any, chainId: number): void @@ -22,10 +23,11 @@ export interface StateContext { setTransaction(transaction: any): void // buyToken(id: string, price: BigNumber): void - setUser(library: any, address?: string): Promise + setUser(address?: string): void updateTokensOnSale(): Promise setTokenSale(id: string, price: BigNumber, onSale: boolean): Promise transferToken(id: string, to: string): void + getUserTokens(address?: string): Promise } const useAppState = create((set, get) => ({ @@ -64,38 +66,35 @@ const useAppState = create((set, get) => ({ const symbol = await contract.symbol() set({ - contract: { - payload: contract, - details: { name, symbol, address }, + library, + contract, + contractDetails: { + name, + symbol, + address, }, }) } catch (e) { console.log(e) } }, - setUser: async (library: any, address?: string) => { + setUser: async (address?: string) => { try { - const { contract, user } = get() + const { contract, user, library, getUserTokens } = get() + if (!library) throw new Error('No Web3 Found') if (!contract) throw new Error('No contract found') if (!user && !address) throw new Error('No user found') const balance = utils.formatEther(await library.getBalance(address || user?.address || '')) - const ownedTokens = await listTokensFrom(contract.payload, address || user?.address || '') + const ownedTokens = await getUserTokens(address || user?.address) set({ isAuthenticated: true, - user: { - address: address || user?.address || '', - balance, - ownedTokens, - }, + user: { address: address || user?.address || '', balance, ownedTokens }, }) - - return true } catch (e) { console.log(e) - return false } }, setTokensOnSale: (tokensOnSale: TokenProps[]) => set({ tokensOnSale: tokensOnSale }), @@ -104,14 +103,54 @@ const useAppState = create((set, get) => ({ set({ activatingConnector: activatingConnector }), setTransaction: (transaction: any) => set({ transaction: transaction }), + // + getUserTokens: async (address?: string): Promise => { + try { + const { contract, library, user } = get() + + if (!library) throw new Error('No Web3 Found') + if (!contract) throw new Error('No contract found') + if (!user?.address && !address) throw new Error('No user found') + + const userAddress = user?.address || address + + const ownedTokensEvents = contract.filters.Transfer(null, userAddress) + const results: Event[] = await contract.queryFilter(ownedTokensEvents, 0, 'latest') + + const ownedTokens: Map = new Map() + await Promise.all( + results.map(async current => { + const ownerToken = await contract.ownerOf(current.args?.tokenId) + + if (ownerToken === userAddress) { + const { id, name, price } = await contract.tokenMeta(current.args?.tokenId) + const uri = await contract.tokenURI(current.args?.tokenId) + + ownedTokens.set(uri, { + id, + name, + price, + uri, + }) + } + }) + ) + + return Array.from(ownedTokens).map(([_, token]) => token) + } catch (e) { + console.log(e) + return [] + } + }, + buyToken: async (id: string, price: BigNumber) => { try { const { setTransaction, contract } = get() if (!contract) throw new Error('No contract found') - const tx = await contract.payload.purchaseToken(id, { value: price }) + const tx = await contract.purchaseToken(id, { value: price }) setTransaction(tx) } catch (e) { - console.log(e) + console.log('on buy', e) } }, // @@ -120,16 +159,13 @@ const useAppState = create((set, get) => ({ const { contract, setTokensOnSale } = get() if (!contract) throw new Error('No contract found') - const tokensForSale = (await contract.payload.getAllOnSale()).reduce( - (acc: TokenProps[], b: any) => { - if (b.uri !== '') { - acc.push({ id: b.id, price: b.price, name: b.name, uri: b.uri }) - } + const tokensForSale = (await contract.getAllOnSale()).reduce((acc: TokenProps[], b: any) => { + if (b.uri !== '') { + acc.push({ id: b.id, price: b.price, name: b.name, uri: b.uri }) + } - return acc - }, - [] as TokenProps[] - ) + return acc + }, [] as TokenProps[]) setTokensOnSale(tokensForSale) return true } catch (e) { @@ -144,7 +180,7 @@ const useAppState = create((set, get) => ({ if (!contract) throw new Error('No contract found') if (!user) throw new Error('No user found') - const tx = await contract.payload.setTokenSale(id, onSale, price, { from: user.address }) + const tx = await contract.setTokenSale(id, onSale, price, { from: user.address }) setTransaction(tx) return true } catch (e) { @@ -159,16 +195,11 @@ const useAppState = create((set, get) => ({ if (!contract) throw new Error('No contract found') if (!user) throw new Error('No user found') - const tx = await contract.payload['safeTransferFrom(address,address,uint256)']( - user.address, - to, - id, - { - from: user.address, - } - ) + const tx = await contract['safeTransferFrom(address,address,uint256)'](user.address, to, id, { + from: user.address, + }) - console.log(tx) + // console.log(tx) setTransaction(tx) } catch (e) { console.log(e) diff --git a/src/types.d.ts b/src/types.d.ts index 3357b9e..0be1ec2 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,4 +1,3 @@ -import { Contract } from 'ethers' import { TokenProps } from './components/Token' declare global { @@ -15,11 +14,6 @@ export type ContractPropsDetails = { address?: string } -export type ContractProps = { - payload: Contract - details: ContractPropsDetails -} - export type UserProps = { address: string balance: string diff --git a/src/utils/fetchers.ts b/src/utils/fetchers.ts index 3cb5528..993a993 100644 --- a/src/utils/fetchers.ts +++ b/src/utils/fetchers.ts @@ -1,5 +1,17 @@ -export const fetcherETHUSD = (url: string) => - fetch(url).then(r => r.json().then(r => r.result.ethusd)) +import { useAppState } from '../state' + +export const fetcherETHUSD = async (url: string) => { + try { + const { setEthPrice } = useAppState.getState() + + const { + result: { ethusd }, + } = await (await fetch(url)).json() + setEthPrice(ethusd) + } catch (e) { + console.log(e) + } +} export const fetcherMetadata = async (url: string) => { try { @@ -8,3 +20,14 @@ export const fetcherMetadata = async (url: string) => { return { error: e.message } } } + +export const fetchOwner = async (id: string) => { + try { + const { contract } = useAppState.getState() + if (!contract) throw new Error('Contract not found') + + return await contract?.ownerOf(id) + } catch (e) { + return { error: e.message } + } +} diff --git a/src/utils/formatPriceEth.ts b/src/utils/formatPriceEth.ts new file mode 100644 index 0000000..462d5a9 --- /dev/null +++ b/src/utils/formatPriceEth.ts @@ -0,0 +1,9 @@ +import { BigNumberish, utils } from 'ethers' + +const formatPriceEth = (price: BigNumberish, ethPrice: string = '0') => + new Intl.NumberFormat('us-GB', { + style: 'currency', + currency: 'USD', + }).format(Number(utils.formatEther(price)) * Number(ethPrice)) + +export { formatPriceEth } diff --git a/src/utils/index.ts b/src/utils/index.ts index 5d28bae..d18de1a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,5 +3,5 @@ const { REACT_APP_SERVICE_URL } = process.env export const ETHSCAN_API = `${REACT_APP_SERVICE_URL}/ethusd` export const METADATA_API = REACT_APP_SERVICE_URL || '' -export { default as listTokensFrom } from './listTokensFrom' -export { default as toShort } from './toShort' +export * from './toShort' +export * from './formatPriceEth' diff --git a/src/utils/listTokensFrom.ts b/src/utils/listTokensFrom.ts deleted file mode 100644 index b679b0e..0000000 --- a/src/utils/listTokensFrom.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Contract, Event } from 'ethers' -import { TokenProps } from '../components/Token' - -const listTokensFrom = (contract: Contract, address: string) => - new Promise(async (resolve, reject) => { - if (!contract || !address) reject('Contract or address not found') - - try { - const ownedTokensEvents = contract.filters.Transfer(null, address) - const results: Event[] = await contract.queryFilter(ownedTokensEvents, 0, 'latest') - - const ownedTokens: Map = new Map() - await Promise.all( - results.map(async current => { - const ownerToken = await contract.ownerOf(current.args?.tokenId) - - if (ownerToken === address) { - const { id, name, price } = await contract.tokenMeta(current.args?.tokenId) - const uri = await contract.tokenURI(current.args?.tokenId) - - ownedTokens.set(uri, { - id, - name, - price, - uri, - }) - } - }) - ) - - resolve(Array.from(ownedTokens).map(([_, token]) => token)) - } catch (e) { - reject(e) - } - }) - -export default listTokensFrom diff --git a/src/utils/toShort.ts b/src/utils/toShort.ts index 1a05e95..d31508a 100644 --- a/src/utils/toShort.ts +++ b/src/utils/toShort.ts @@ -3,4 +3,4 @@ const toShort = (value: string, factor: number = 5) => { return `${value.substr(0, slice)}...${value.substr(value.length - slice, value.length)}` } -export default toShort +export { toShort }