1
0
Fork 0

move selected token to nanostore

This commit is contained in:
Matthias Kretschmann 2023-10-29 22:51:31 +00:00
parent 7c82ec79be
commit 039757c671
Signed by: m
GPG Key ID: 606EEEF3C479A91F
6 changed files with 53 additions and 58 deletions

View File

@ -1,33 +1,28 @@
import { useEffect, type ReactElement, useState } from 'react'
import styles from './Conversion.module.css'
import type { GetToken } from '../../hooks/useTokens'
import { $selectedToken } from '../../stores/selectedToken'
import { useStore } from '@nanostores/react'
export function Conversion({ amount }: { amount: string }): ReactElement {
const selectedToken = useStore($selectedToken)
export function Conversion({
amount,
token
}: {
amount: string
token: GetToken | undefined
}): ReactElement {
const [dollar, setDollar] = useState('0.00')
const [euro, setEuro] = useState('0.00')
useEffect(() => {
if (!token?.price || !amount) {
if (!selectedToken?.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'
const { eur, usd } = selectedToken.price
const dollar = usd ? (Number(amount) * usd).toFixed(2) : '0.00'
const euro = eur ? (Number(amount) * eur).toFixed(2) : '0.00'
setDollar(dollar)
setEuro(euro)
}, [token?.price, amount])
}, [selectedToken?.price, amount])
return (
<div className={styles.conversion}>

View File

@ -6,19 +6,17 @@ import Alert from '../Alert/Alert'
import { InputGroup } from '../Input'
import styles from './index.module.css'
import { SendNative, SendErc20 } from '../Send'
import type { GetToken } from '../../hooks/useTokens'
import { useSend } from '@features/Web3/hooks/useSend'
import { useSend } from '../../hooks/useSend'
import type { SendFormData } from './types'
import { $selectedToken } from '../../stores/selectedToken'
import { useStore } from '@nanostores/react'
export default function Web3Form(): ReactElement {
const { address: account } = useAccount()
const selectedToken = useStore($selectedToken)
const [amount, setAmount] = useState('')
const [debouncedAmount] = useDebounce(amount, 500)
const [tokenSelected, setTokenSelected] = useState<GetToken>({
address: '0x0'
} as any)
const [sendFormData, setSendFormData] = useState<SendFormData>()
const { data, send } = sendFormData || {}
@ -31,7 +29,7 @@ export default function Web3Form(): ReactElement {
className={styles.web3}
onSubmit={async (e) => {
e.preventDefault()
if (!send || amount === '' || amount === '0') return
if (!send || debouncedAmount === '' || debouncedAmount === '0') return
await send()
}}
>
@ -42,24 +40,18 @@ export default function Web3Form(): ReactElement {
) : (
<InputGroup
amount={amount}
token={tokenSelected}
setAmount={setAmount}
setTokenSelected={setTokenSelected}
isDisabled={isDisabled}
/>
)}
{tokenSelected?.address === '0x0' ? (
{selectedToken?.address === '0x0' ? (
<SendNative
amount={debouncedAmount}
setSendFormData={setSendFormData}
/>
) : (
<SendErc20
amount={debouncedAmount}
tokenAddress={tokenSelected?.address}
setSendFormData={setSendFormData}
/>
<SendErc20 amount={debouncedAmount} setSendFormData={setSendFormData} />
)}
</form>
)

View File

@ -4,29 +4,21 @@ import { Conversion } from '../Conversion'
import styles from './InputGroup.module.css'
import { TokenSelect } from '../TokenSelect'
import config from '@config/blog.config'
import type { GetToken } from '../../hooks/useTokens'
export function InputGroup({
amount,
token,
isDisabled,
setAmount,
setTokenSelected
setAmount
}: {
amount: string
token: GetToken | undefined
isDisabled: boolean
setAmount: React.Dispatch<React.SetStateAction<string>>
setTokenSelected: React.Dispatch<React.SetStateAction<GetToken>>
}): ReactElement {
return (
<>
<div className={styles.inputGroup}>
<div className={styles.token}>
<TokenSelect
selectedToken={token}
setTokenSelected={setTokenSelected}
/>
<TokenSelect />
</div>
<Input
type="text"
@ -45,7 +37,7 @@ export function InputGroup({
Make it rain
</button>
</div>
<Conversion amount={amount} token={token} />
<Conversion amount={amount} />
<div className={styles.disclaimer}>
This form sends tokens to my account <code>{config.author.ether}</code>
</div>

View File

@ -1,23 +1,28 @@
import { parseEther } from 'viem'
import { parseUnits } from 'viem'
import { useContractWrite, usePrepareContractWrite } from 'wagmi'
import siteConfig from '@config/blog.config'
import { abiErc20Transfer } from './abiErc20Transfer'
import { useEffect } from 'react'
import { useStore } from '@nanostores/react'
import { $selectedToken } from '@features/Web3/stores/selectedToken'
export function SendErc20({
amount,
tokenAddress,
setSendFormData
}: {
amount: string
tokenAddress: `0x${string}` | undefined
setSendFormData: any
}) {
const selectedToken = useStore($selectedToken)
const { config } = usePrepareContractWrite({
address: tokenAddress,
address: selectedToken.address,
abi: abiErc20Transfer,
functionName: 'transfer',
args: [siteConfig.author.ether, parseEther(amount)]
args: [
siteConfig.author.ether,
parseUnits(amount, selectedToken?.decimals || 18)
]
})
const {

View File

@ -4,17 +4,14 @@ import { Token } from './Token'
import { ChevronDown, ChevronsDown, ChevronsUp } from '@images/components/react'
import { TokenLoading } from './TokenLoading'
import { useEffect } from 'react'
import { useTokens, type GetToken } from '../../hooks/useTokens'
import { useTokens } from '../../hooks/useTokens'
import { useAccount, useNetwork } from 'wagmi'
import { $selectedToken, $setSelectedToken } from '../../stores/selectedToken'
import { useStore } from '@nanostores/react'
export function TokenSelect({
selectedToken,
setTokenSelected
}: {
selectedToken: GetToken | undefined
setTokenSelected: React.Dispatch<React.SetStateAction<GetToken>>
}) {
export function TokenSelect() {
const { data: tokens, isLoading } = useTokens()
const selectedToken = useStore($selectedToken)
const { chain } = useNetwork()
const { address } = useAccount()
@ -25,21 +22,22 @@ export function TokenSelect({
function handleValueChange(value: `0x${string}`) {
const token = tokens?.find((token) => token.address === value)
if (!token) return
setTokenSelected(token)
$setSelectedToken(token)
}
// Set default token data to native token
useEffect(() => {
if (!chain?.id || !address || !tokens) return
handleValueChange('0x0')
}, [chain?.id, address, tokens])
if (!selectedToken || !selectedToken?.address) handleValueChange('0x0')
}, [chain?.id, address, tokens, selectedToken])
return (
<Select.Root
defaultValue={selectedToken?.address}
onValueChange={(value: `0x${string}`) => handleValueChange(value)}
disabled={!tokens || isLoading}
value={selectedToken?.address}
>
<Select.Trigger
className="SelectTrigger"

View File

@ -0,0 +1,13 @@
import { action, map } from 'nanostores'
import type { GetToken } from '../hooks/useTokens'
export const $selectedToken = map<GetToken>()
export const $setSelectedToken = action(
$selectedToken,
'setSelectedToken',
(store, token: GetToken) => {
store.set(token)
return store.get()
}
)