diff --git a/src/components/Sponsor/Web3Donation/components/Conversion/Conversion.tsx b/src/components/Sponsor/Web3Donation/components/Conversion/Conversion.tsx index 5b948192..a0bc7a07 100644 --- a/src/components/Sponsor/Web3Donation/components/Conversion/Conversion.tsx +++ b/src/components/Sponsor/Web3Donation/components/Conversion/Conversion.tsx @@ -1,6 +1,6 @@ -import { type ReactElement } from 'react' +import { useEffect, type ReactElement, useState } from 'react' import styles from './Conversion.module.css' -import type { GetToken } from '../../api/getTokens' +import type { GetToken } from '../../hooks/useTokens' export function Conversion({ amount, @@ -9,12 +9,25 @@ export function Conversion({ amount: string token: GetToken | undefined }): ReactElement { - const dollar = token?.price?.usd - ? (Number(amount) * token?.price?.usd).toFixed(2) - : '0.00' - const euro = token?.price?.eur - ? (Number(amount) * token?.price?.eur).toFixed(2) - : '0.00' + const [dollar, setDollar] = useState('0.00') + const [euro, setEuro] = useState('0.00') + + useEffect(() => { + if (!token?.price || !amount) { + setDollar('0.00') + setEuro('0.00') + return + } + + const dollar = token?.price?.usd + ? (Number(amount) * token?.price?.usd).toFixed(2) + : '0.00' + const euro = token?.price?.eur + ? (Number(amount) * token?.price?.eur).toFixed(2) + : '0.00' + setDollar(dollar) + setEuro(euro) + }, [token?.price, amount]) return (
diff --git a/src/components/Sponsor/Web3Donation/components/Input/InputGroup.tsx b/src/components/Sponsor/Web3Donation/components/Input/InputGroup.tsx index df706729..d264382e 100644 --- a/src/components/Sponsor/Web3Donation/components/Input/InputGroup.tsx +++ b/src/components/Sponsor/Web3Donation/components/Input/InputGroup.tsx @@ -4,7 +4,7 @@ import { Conversion } from '../Conversion' import styles from './InputGroup.module.css' import { TokenSelect } from '../Tokens' import config from '@config/blog.config' -import type { GetToken } from '../../api/getTokens' +import type { GetToken } from '../../hooks/useTokens' export function InputGroup({ amount, @@ -23,7 +23,10 @@ export function InputGroup({ <>
- +
{ token: GetToken | undefined diff --git a/src/components/Sponsor/Web3Donation/components/Tokens/TokenSelect.tsx b/src/components/Sponsor/Web3Donation/components/Tokens/TokenSelect.tsx index aff0c99f..0074c898 100644 --- a/src/components/Sponsor/Web3Donation/components/Tokens/TokenSelect.tsx +++ b/src/components/Sponsor/Web3Donation/components/Tokens/TokenSelect.tsx @@ -2,17 +2,22 @@ import * as Select from '@radix-ui/react-select' import './TokenSelect.css' import { Token } from './Token' import { ChevronDown, ChevronsDown, ChevronsUp } from '@images/components/react' -import { useTokens } from '../../hooks/useTokens' +import { useTokens } from '../../hooks/useTokens/useTokens' import { TokenLoading } from './TokenLoading' -import type { GetToken } from '../../api/getTokens' import { useEffect } from 'react' +import type { GetToken } from '../../hooks/useTokens' +import { useAccount, useNetwork } from 'wagmi' export function TokenSelect({ + selectedToken, setTokenSelected }: { + selectedToken: GetToken | undefined setTokenSelected: React.Dispatch> }) { const { data: tokens, isLoading } = useTokens() + const { chain } = useNetwork() + const { address } = useAccount() const items = tokens?.map((token) => ( @@ -24,12 +29,16 @@ export function TokenSelect({ setTokenSelected(token) } - // set default token data - useEffect(() => handleValueChange('0x0'), []) + // Set default token data to native token + useEffect(() => { + if (!chain?.id || !address || !tokens) return - return tokens ? ( + handleValueChange('0x0') + }, [chain?.id, address, tokens]) + + return ( handleValueChange(value)} disabled={!tokens || isLoading} > @@ -63,5 +72,5 @@ export function TokenSelect({ - ) : null + ) } diff --git a/src/components/Sponsor/Web3Donation/api/getTokens.ts b/src/components/Sponsor/Web3Donation/hooks/useTokens/getTokens.ts similarity index 57% rename from src/components/Sponsor/Web3Donation/api/getTokens.ts rename to src/components/Sponsor/Web3Donation/hooks/useTokens/getTokens.ts index b48a5982..24e79ef3 100644 --- a/src/components/Sponsor/Web3Donation/api/getTokens.ts +++ b/src/components/Sponsor/Web3Donation/hooks/useTokens/getTokens.ts @@ -1,26 +1,15 @@ -export type GetToken = { - address: `0x${string}` - balance: number | undefined - chainId: number - name: string | null - symbol: string | null - decimals: number | null - logo: string | null - price: { - usd: number | null - eur: number | null - } -} +import type { GetToken } from './types' export async function getTokens( address: `0x${string}`, - chainId: number + chainId: number, + signal?: AbortSignal ): Promise { if (!address || !chainId) return [] // const url = `http://localhost:3000/api/balance?address=${address}&chainId=${chainId}` const url = `https://web3.kremalicious.com/api/balance?address=${address}&chainId=${chainId}` - const response = await fetch(url) + const response = await fetch(url, { signal }) const json: GetToken[] = await response.json() if (!json) console.error(response.statusText) diff --git a/src/components/Sponsor/Web3Donation/hooks/useTokens/index.tsx b/src/components/Sponsor/Web3Donation/hooks/useTokens/index.tsx new file mode 100644 index 00000000..e1d38f28 --- /dev/null +++ b/src/components/Sponsor/Web3Donation/hooks/useTokens/index.tsx @@ -0,0 +1,2 @@ +export * from './useTokens' +export * from './types' diff --git a/src/components/Sponsor/Web3Donation/hooks/useTokens/types.ts b/src/components/Sponsor/Web3Donation/hooks/useTokens/types.ts new file mode 100644 index 00000000..6eec3674 --- /dev/null +++ b/src/components/Sponsor/Web3Donation/hooks/useTokens/types.ts @@ -0,0 +1,13 @@ +export type GetToken = { + address: `0x${string}` + balance: number | undefined + chainId: number + name: string | null + symbol: string | null + decimals: number | null + logo: string | null + price: { + usd: number | null + eur: number | null + } +} diff --git a/src/components/Sponsor/Web3Donation/hooks/useTokens.tsx b/src/components/Sponsor/Web3Donation/hooks/useTokens/useTokens.tsx similarity index 50% rename from src/components/Sponsor/Web3Donation/hooks/useTokens.tsx rename to src/components/Sponsor/Web3Donation/hooks/useTokens/useTokens.tsx index 79a64b30..616a0084 100644 --- a/src/components/Sponsor/Web3Donation/hooks/useTokens.tsx +++ b/src/components/Sponsor/Web3Donation/hooks/useTokens/useTokens.tsx @@ -1,6 +1,7 @@ import { useState, useEffect } from 'react' import { useAccount, useNetwork } from 'wagmi' -import { getTokens, type GetToken } from '../api/getTokens' +import { getTokens } from './getTokens' +import type { GetToken } from './types' export function useTokens() { const { address } = useAccount() @@ -11,23 +12,35 @@ export function useTokens() { const [isError, setIsError] = useState() useEffect(() => { + const abortController = new AbortController() + const { signal } = abortController + async function init() { - if (!address || !chain) return + if (!address || !chain?.id) return setIsLoading(true) try { - const tokens = await getTokens(address, chain.id) + const tokens = await getTokens(address, chain.id, signal) setData(tokens) setIsLoading(false) - } catch (error) { + } catch (error: any) { setIsError(true) setIsLoading(false) - console.error((error as Error).message) + if ((error as Error).name !== 'AbortError') { + console.error((error as Error).message) + } } } init() - }, [address, chain]) + + return () => { + abortController.abort() + setData(undefined) + setIsLoading(undefined) + setIsError(undefined) + } + }, [address, chain?.id]) return { data, isLoading, isError } } diff --git a/src/components/Sponsor/Web3Donation/index.tsx b/src/components/Sponsor/Web3Donation/index.tsx index 4f6c72a8..096a60a4 100644 --- a/src/components/Sponsor/Web3Donation/index.tsx +++ b/src/components/Sponsor/Web3Donation/index.tsx @@ -6,7 +6,7 @@ import Alert, { getTransactionMessage } from './components/Alert/Alert' import { InputGroup } from './components/Input' import styles from './index.module.css' import { SendNative, SendErc20 } from './components/Send' -import type { GetToken } from './api/getTokens' +import type { GetToken } from './hooks/useTokens' export default function Web3Donation(): ReactElement { const { address: account } = useAccount()