mirror of
https://github.com/kremalicious/blog.git
synced 2025-02-14 21:10:25 +01:00
move selected token to nanostore
This commit is contained in:
parent
7c82ec79be
commit
039757c671
@ -1,33 +1,28 @@
|
|||||||
import { useEffect, type ReactElement, useState } from 'react'
|
import { useEffect, type ReactElement, useState } from 'react'
|
||||||
import styles from './Conversion.module.css'
|
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 [dollar, setDollar] = useState('0.00')
|
||||||
const [euro, setEuro] = useState('0.00')
|
const [euro, setEuro] = useState('0.00')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!token?.price || !amount) {
|
if (!selectedToken?.price || !amount) {
|
||||||
setDollar('0.00')
|
setDollar('0.00')
|
||||||
setEuro('0.00')
|
setEuro('0.00')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const dollar = token?.price?.usd
|
const { eur, usd } = selectedToken.price
|
||||||
? (Number(amount) * token?.price?.usd).toFixed(2)
|
|
||||||
: '0.00'
|
const dollar = usd ? (Number(amount) * usd).toFixed(2) : '0.00'
|
||||||
const euro = token?.price?.eur
|
const euro = eur ? (Number(amount) * eur).toFixed(2) : '0.00'
|
||||||
? (Number(amount) * token?.price?.eur).toFixed(2)
|
|
||||||
: '0.00'
|
|
||||||
setDollar(dollar)
|
setDollar(dollar)
|
||||||
setEuro(euro)
|
setEuro(euro)
|
||||||
}, [token?.price, amount])
|
}, [selectedToken?.price, amount])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.conversion}>
|
<div className={styles.conversion}>
|
||||||
|
@ -6,19 +6,17 @@ import Alert from '../Alert/Alert'
|
|||||||
import { InputGroup } from '../Input'
|
import { InputGroup } from '../Input'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import { SendNative, SendErc20 } from '../Send'
|
import { SendNative, SendErc20 } from '../Send'
|
||||||
import type { GetToken } from '../../hooks/useTokens'
|
import { useSend } from '../../hooks/useSend'
|
||||||
import { useSend } from '@features/Web3/hooks/useSend'
|
|
||||||
import type { SendFormData } from './types'
|
import type { SendFormData } from './types'
|
||||||
|
import { $selectedToken } from '../../stores/selectedToken'
|
||||||
|
import { useStore } from '@nanostores/react'
|
||||||
|
|
||||||
export default function Web3Form(): ReactElement {
|
export default function Web3Form(): ReactElement {
|
||||||
const { address: account } = useAccount()
|
const { address: account } = useAccount()
|
||||||
|
const selectedToken = useStore($selectedToken)
|
||||||
|
|
||||||
const [amount, setAmount] = useState('')
|
const [amount, setAmount] = useState('')
|
||||||
const [debouncedAmount] = useDebounce(amount, 500)
|
const [debouncedAmount] = useDebounce(amount, 500)
|
||||||
const [tokenSelected, setTokenSelected] = useState<GetToken>({
|
|
||||||
address: '0x0'
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
const [sendFormData, setSendFormData] = useState<SendFormData>()
|
const [sendFormData, setSendFormData] = useState<SendFormData>()
|
||||||
|
|
||||||
const { data, send } = sendFormData || {}
|
const { data, send } = sendFormData || {}
|
||||||
@ -31,7 +29,7 @@ export default function Web3Form(): ReactElement {
|
|||||||
className={styles.web3}
|
className={styles.web3}
|
||||||
onSubmit={async (e) => {
|
onSubmit={async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (!send || amount === '' || amount === '0') return
|
if (!send || debouncedAmount === '' || debouncedAmount === '0') return
|
||||||
await send()
|
await send()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -42,24 +40,18 @@ export default function Web3Form(): ReactElement {
|
|||||||
) : (
|
) : (
|
||||||
<InputGroup
|
<InputGroup
|
||||||
amount={amount}
|
amount={amount}
|
||||||
token={tokenSelected}
|
|
||||||
setAmount={setAmount}
|
setAmount={setAmount}
|
||||||
setTokenSelected={setTokenSelected}
|
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{tokenSelected?.address === '0x0' ? (
|
{selectedToken?.address === '0x0' ? (
|
||||||
<SendNative
|
<SendNative
|
||||||
amount={debouncedAmount}
|
amount={debouncedAmount}
|
||||||
setSendFormData={setSendFormData}
|
setSendFormData={setSendFormData}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SendErc20
|
<SendErc20 amount={debouncedAmount} setSendFormData={setSendFormData} />
|
||||||
amount={debouncedAmount}
|
|
||||||
tokenAddress={tokenSelected?.address}
|
|
||||||
setSendFormData={setSendFormData}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
|
@ -4,29 +4,21 @@ import { Conversion } from '../Conversion'
|
|||||||
import styles from './InputGroup.module.css'
|
import styles from './InputGroup.module.css'
|
||||||
import { TokenSelect } from '../TokenSelect'
|
import { TokenSelect } from '../TokenSelect'
|
||||||
import config from '@config/blog.config'
|
import config from '@config/blog.config'
|
||||||
import type { GetToken } from '../../hooks/useTokens'
|
|
||||||
|
|
||||||
export function InputGroup({
|
export function InputGroup({
|
||||||
amount,
|
amount,
|
||||||
token,
|
|
||||||
isDisabled,
|
isDisabled,
|
||||||
setAmount,
|
setAmount
|
||||||
setTokenSelected
|
|
||||||
}: {
|
}: {
|
||||||
amount: string
|
amount: string
|
||||||
token: GetToken | undefined
|
|
||||||
isDisabled: boolean
|
isDisabled: boolean
|
||||||
setAmount: React.Dispatch<React.SetStateAction<string>>
|
setAmount: React.Dispatch<React.SetStateAction<string>>
|
||||||
setTokenSelected: React.Dispatch<React.SetStateAction<GetToken>>
|
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.inputGroup}>
|
<div className={styles.inputGroup}>
|
||||||
<div className={styles.token}>
|
<div className={styles.token}>
|
||||||
<TokenSelect
|
<TokenSelect />
|
||||||
selectedToken={token}
|
|
||||||
setTokenSelected={setTokenSelected}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
@ -45,7 +37,7 @@ export function InputGroup({
|
|||||||
Make it rain
|
Make it rain
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<Conversion amount={amount} token={token} />
|
<Conversion amount={amount} />
|
||||||
<div className={styles.disclaimer}>
|
<div className={styles.disclaimer}>
|
||||||
This form sends tokens to my account <code>{config.author.ether}</code>
|
This form sends tokens to my account <code>{config.author.ether}</code>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,23 +1,28 @@
|
|||||||
import { parseEther } from 'viem'
|
import { parseUnits } from 'viem'
|
||||||
import { useContractWrite, usePrepareContractWrite } from 'wagmi'
|
import { useContractWrite, usePrepareContractWrite } from 'wagmi'
|
||||||
import siteConfig from '@config/blog.config'
|
import siteConfig from '@config/blog.config'
|
||||||
import { abiErc20Transfer } from './abiErc20Transfer'
|
import { abiErc20Transfer } from './abiErc20Transfer'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
import { useStore } from '@nanostores/react'
|
||||||
|
import { $selectedToken } from '@features/Web3/stores/selectedToken'
|
||||||
|
|
||||||
export function SendErc20({
|
export function SendErc20({
|
||||||
amount,
|
amount,
|
||||||
tokenAddress,
|
|
||||||
setSendFormData
|
setSendFormData
|
||||||
}: {
|
}: {
|
||||||
amount: string
|
amount: string
|
||||||
tokenAddress: `0x${string}` | undefined
|
|
||||||
setSendFormData: any
|
setSendFormData: any
|
||||||
}) {
|
}) {
|
||||||
|
const selectedToken = useStore($selectedToken)
|
||||||
|
|
||||||
const { config } = usePrepareContractWrite({
|
const { config } = usePrepareContractWrite({
|
||||||
address: tokenAddress,
|
address: selectedToken.address,
|
||||||
abi: abiErc20Transfer,
|
abi: abiErc20Transfer,
|
||||||
functionName: 'transfer',
|
functionName: 'transfer',
|
||||||
args: [siteConfig.author.ether, parseEther(amount)]
|
args: [
|
||||||
|
siteConfig.author.ether,
|
||||||
|
parseUnits(amount, selectedToken?.decimals || 18)
|
||||||
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -4,17 +4,14 @@ import { Token } from './Token'
|
|||||||
import { ChevronDown, ChevronsDown, ChevronsUp } from '@images/components/react'
|
import { ChevronDown, ChevronsDown, ChevronsUp } from '@images/components/react'
|
||||||
import { TokenLoading } from './TokenLoading'
|
import { TokenLoading } from './TokenLoading'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useTokens, type GetToken } from '../../hooks/useTokens'
|
import { useTokens } from '../../hooks/useTokens'
|
||||||
import { useAccount, useNetwork } from 'wagmi'
|
import { useAccount, useNetwork } from 'wagmi'
|
||||||
|
import { $selectedToken, $setSelectedToken } from '../../stores/selectedToken'
|
||||||
|
import { useStore } from '@nanostores/react'
|
||||||
|
|
||||||
export function TokenSelect({
|
export function TokenSelect() {
|
||||||
selectedToken,
|
|
||||||
setTokenSelected
|
|
||||||
}: {
|
|
||||||
selectedToken: GetToken | undefined
|
|
||||||
setTokenSelected: React.Dispatch<React.SetStateAction<GetToken>>
|
|
||||||
}) {
|
|
||||||
const { data: tokens, isLoading } = useTokens()
|
const { data: tokens, isLoading } = useTokens()
|
||||||
|
const selectedToken = useStore($selectedToken)
|
||||||
const { chain } = useNetwork()
|
const { chain } = useNetwork()
|
||||||
const { address } = useAccount()
|
const { address } = useAccount()
|
||||||
|
|
||||||
@ -25,21 +22,22 @@ export function TokenSelect({
|
|||||||
function handleValueChange(value: `0x${string}`) {
|
function handleValueChange(value: `0x${string}`) {
|
||||||
const token = tokens?.find((token) => token.address === value)
|
const token = tokens?.find((token) => token.address === value)
|
||||||
if (!token) return
|
if (!token) return
|
||||||
setTokenSelected(token)
|
$setSelectedToken(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set default token data to native token
|
// Set default token data to native token
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!chain?.id || !address || !tokens) return
|
if (!chain?.id || !address || !tokens) return
|
||||||
|
|
||||||
handleValueChange('0x0')
|
if (!selectedToken || !selectedToken?.address) handleValueChange('0x0')
|
||||||
}, [chain?.id, address, tokens])
|
}, [chain?.id, address, tokens, selectedToken])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select.Root
|
<Select.Root
|
||||||
defaultValue={selectedToken?.address}
|
defaultValue={selectedToken?.address}
|
||||||
onValueChange={(value: `0x${string}`) => handleValueChange(value)}
|
onValueChange={(value: `0x${string}`) => handleValueChange(value)}
|
||||||
disabled={!tokens || isLoading}
|
disabled={!tokens || isLoading}
|
||||||
|
value={selectedToken?.address}
|
||||||
>
|
>
|
||||||
<Select.Trigger
|
<Select.Trigger
|
||||||
className="SelectTrigger"
|
className="SelectTrigger"
|
||||||
|
13
src/features/Web3/stores/selectedToken.ts
Normal file
13
src/features/Web3/stores/selectedToken.ts
Normal 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()
|
||||||
|
}
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user