mirror of
https://github.com/kremalicious/blog.git
synced 2024-11-26 11:49:04 +01:00
refactor
This commit is contained in:
parent
bad987d68d
commit
a6f01ed2aa
12
package-lock.json
generated
12
package-lock.json
generated
@ -35,7 +35,6 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"slugify": "^1.6.6",
|
"slugify": "^1.6.6",
|
||||||
"swr": "^2.2.4",
|
"swr": "^2.2.4",
|
||||||
"use-debounce": "^9.0.4",
|
|
||||||
"viem": "^1.18.2",
|
"viem": "^1.18.2",
|
||||||
"wagmi": "^1.4.5"
|
"wagmi": "^1.4.5"
|
||||||
},
|
},
|
||||||
@ -18987,17 +18986,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/use-debounce": {
|
|
||||||
"version": "9.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.4.tgz",
|
|
||||||
"integrity": "sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=16.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/use-sidecar": {
|
"node_modules/use-sidecar": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
|
||||||
|
@ -74,7 +74,6 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"slugify": "^1.6.6",
|
"slugify": "^1.6.6",
|
||||||
"swr": "^2.2.4",
|
"swr": "^2.2.4",
|
||||||
"use-debounce": "^9.0.4",
|
|
||||||
"viem": "^1.18.2",
|
"viem": "^1.18.2",
|
||||||
"wagmi": "^1.4.5"
|
"wagmi": "^1.4.5"
|
||||||
},
|
},
|
||||||
|
@ -2,9 +2,11 @@ import { useEffect, type ReactElement, useState } from 'react'
|
|||||||
import styles from './Conversion.module.css'
|
import styles from './Conversion.module.css'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { $selectedToken } from '@features/Web3/stores/selectedToken'
|
import { $selectedToken } from '@features/Web3/stores/selectedToken'
|
||||||
|
import { $amount } from '@features/Web3/stores'
|
||||||
|
|
||||||
export function Conversion({ amount }: { amount: string }): ReactElement {
|
export function Conversion(): ReactElement {
|
||||||
const selectedToken = useStore($selectedToken)
|
const selectedToken = useStore($selectedToken)
|
||||||
|
const amount = useStore($amount)
|
||||||
|
|
||||||
const [dollar, setDollar] = useState('0.00')
|
const [dollar, setDollar] = useState('0.00')
|
||||||
const [euro, setEuro] = useState('0.00')
|
const [euro, setEuro] = useState('0.00')
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { type ReactElement, useState, useEffect } from 'react'
|
import { type ReactElement, useEffect } from 'react'
|
||||||
import { useDebounce } from 'use-debounce'
|
|
||||||
import { useAccount } from 'wagmi'
|
import { useAccount } from 'wagmi'
|
||||||
import { ConnectButton } from '@rainbow-me/rainbowkit'
|
import { ConnectButton } from '@rainbow-me/rainbowkit'
|
||||||
import { InputGroup } from '../Input'
|
import { InputGroup } from '../Input'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { $selectedToken, $isInitSend } from '@features/Web3/stores'
|
import { $selectedToken, $isInitSend, $amount } from '@features/Web3/stores'
|
||||||
import siteConfig from '@config/blog.config'
|
import siteConfig from '@config/blog.config'
|
||||||
import { Send } from '../Send'
|
import { Send } from '../Send'
|
||||||
|
|
||||||
@ -13,42 +12,34 @@ export default function Web3Form(): ReactElement {
|
|||||||
const { address: account } = useAccount()
|
const { address: account } = useAccount()
|
||||||
const selectedToken = useStore($selectedToken)
|
const selectedToken = useStore($selectedToken)
|
||||||
const isInitSend = useStore($isInitSend)
|
const isInitSend = useStore($isInitSend)
|
||||||
|
const amount = useStore($amount)
|
||||||
const [amount, setAmount] = useState('')
|
|
||||||
const [debouncedAmount] = useDebounce(amount, 500)
|
|
||||||
|
|
||||||
const isDisabled = !account
|
const isDisabled = !account
|
||||||
|
|
||||||
// reset amount whenever token changes
|
// reset amount whenever token changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedToken) return
|
if (!selectedToken) return
|
||||||
setAmount('')
|
$amount.set('')
|
||||||
}, [selectedToken])
|
}, [selectedToken])
|
||||||
|
|
||||||
return isInitSend ? (
|
return isInitSend ? (
|
||||||
<Send amount={debouncedAmount} />
|
<Send />
|
||||||
) : (
|
) : (
|
||||||
<form
|
<form
|
||||||
className={styles.web3}
|
className={styles.web3}
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (debouncedAmount === '' || debouncedAmount === '0') return
|
if (amount === '' || amount === '0') return
|
||||||
$isInitSend.set(true)
|
$isInitSend.set(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<>
|
<div className={styles.rainbowkit}>
|
||||||
<div className={styles.rainbowkit}>
|
<ConnectButton chainStatus="full" showBalance={false} />
|
||||||
<ConnectButton chainStatus="full" showBalance={false} />
|
</div>
|
||||||
</div>
|
<InputGroup isDisabled={isDisabled} />
|
||||||
<InputGroup
|
<div className={styles.disclaimer}>
|
||||||
amount={amount}
|
Sends tokens to my account <code>{siteConfig.author.ether.ens}</code>
|
||||||
setAmount={setAmount}
|
</div>
|
||||||
isDisabled={isDisabled}
|
|
||||||
/>
|
|
||||||
<div className={styles.disclaimer}>
|
|
||||||
Sends tokens to my account <code>{siteConfig.author.ether.ens}</code>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,20 @@ import Input from '@components/Input'
|
|||||||
import { Conversion } from '../Conversion'
|
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 { $isInitSend } from '@features/Web3/stores'
|
import { $amount, $isInitSend } from '@features/Web3/stores'
|
||||||
|
import { useStore } from '@nanostores/react'
|
||||||
|
|
||||||
export function InputGroup({
|
export function InputGroup({
|
||||||
amount,
|
isDisabled
|
||||||
isDisabled,
|
|
||||||
setAmount
|
|
||||||
}: {
|
}: {
|
||||||
amount: string
|
|
||||||
isDisabled: boolean
|
isDisabled: boolean
|
||||||
setAmount: React.Dispatch<React.SetStateAction<string>>
|
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
|
const amount = useStore($amount)
|
||||||
|
|
||||||
|
function handleChange(newAmount: string) {
|
||||||
|
$amount.set(newAmount)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.inputGroup}>
|
<div className={styles.inputGroup}>
|
||||||
@ -27,7 +30,7 @@ export function InputGroup({
|
|||||||
pattern="[0-9.]*"
|
pattern="[0-9.]*"
|
||||||
value={amount}
|
value={amount}
|
||||||
placeholder="0.00"
|
placeholder="0.00"
|
||||||
onChange={(e) => setAmount(e.target.value)}
|
onChange={(e) => handleChange(e.target.value)}
|
||||||
className={styles.inputInput}
|
className={styles.inputInput}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -40,7 +43,7 @@ export function InputGroup({
|
|||||||
Preview
|
Preview
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<Conversion amount={amount} />
|
<Conversion />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
.amount,
|
|
||||||
.network,
|
|
||||||
.to {
|
|
||||||
/* font-weight: var(--font-weight-bold); */
|
|
||||||
}
|
|
||||||
|
|
||||||
.to,
|
.to,
|
||||||
.from {
|
.from {
|
||||||
display: block;
|
display: block;
|
||||||
@ -23,7 +17,7 @@
|
|||||||
margin-left: -14px;
|
margin-left: -14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.from .table {
|
.table {
|
||||||
/* max-width: 386px; */
|
/* max-width: 386px; */
|
||||||
margin-bottom: calc(var(--spacer) / 1.5);
|
margin-bottom: calc(var(--spacer) / 1.5);
|
||||||
}
|
}
|
@ -4,11 +4,11 @@ import type {
|
|||||||
SendTransactionArgs,
|
SendTransactionArgs,
|
||||||
WriteContractPreparedArgs
|
WriteContractPreparedArgs
|
||||||
} from 'wagmi/actions'
|
} from 'wagmi/actions'
|
||||||
import styles from './SendTable.module.css'
|
import styles from './Data.module.css'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { $selectedToken } from '@features/Web3/stores'
|
import { $selectedToken } from '@features/Web3/stores'
|
||||||
|
|
||||||
export function SendTable({
|
export function Data({
|
||||||
to,
|
to,
|
||||||
ensResolved,
|
ensResolved,
|
||||||
txConfig,
|
txConfig,
|
21
src/features/Web3/components/Preview/Preview.module.css
Normal file
21
src/features/Web3/components/Preview/Preview.module.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions button {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions button:first-child {
|
||||||
|
margin-right: var(--spacer);
|
||||||
|
width: 115px;
|
||||||
|
height: 50px;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
67
src/features/Web3/components/Preview/Preview.tsx
Normal file
67
src/features/Web3/components/Preview/Preview.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { Loader } from '@components/Loader'
|
||||||
|
import { usePrepareSend } from '@features/Web3/hooks/usePrepareSend'
|
||||||
|
import { useSend } from '@features/Web3/hooks/useSend'
|
||||||
|
import { $isInitSend } from '@features/Web3/stores'
|
||||||
|
import { useEnsAddress, useEnsName } from 'wagmi'
|
||||||
|
import { Data } from './Data'
|
||||||
|
import siteConfig from '@config/blog.config'
|
||||||
|
import styles from './Preview.module.css'
|
||||||
|
|
||||||
|
export function Preview() {
|
||||||
|
// Always resolve to address from ENS name and vice versa
|
||||||
|
// so nobody has to trust my config values.
|
||||||
|
const { ens } = siteConfig.author.ether
|
||||||
|
const { data: to } = useEnsAddress({ name: ens, chainId: 1 })
|
||||||
|
const { data: ensResolved } = useEnsName({
|
||||||
|
address: to as `0x${string}` | undefined,
|
||||||
|
chainId: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: txConfig,
|
||||||
|
error: prepareError,
|
||||||
|
isError: isPrepareError
|
||||||
|
} = usePrepareSend({ to })
|
||||||
|
const { handleSend, isLoading, error } = useSend({ txConfig })
|
||||||
|
|
||||||
|
// TODO: Cancel flow if chain changes in preview as this can mess with token selection
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!chain?.id || $isInitSend.get() === false) return
|
||||||
|
// $isInitSend.set(false)
|
||||||
|
// }, [chain?.id])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Data
|
||||||
|
to={to}
|
||||||
|
ensResolved={ensResolved}
|
||||||
|
txConfig={txConfig}
|
||||||
|
isDisabled={isLoading}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{error || prepareError ? (
|
||||||
|
<div className={styles.alert}>{error || prepareError}</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<footer className={styles.actions}>
|
||||||
|
<button
|
||||||
|
onClick={async (e) => {
|
||||||
|
e?.preventDefault()
|
||||||
|
await handleSend()
|
||||||
|
}}
|
||||||
|
className="btn btn-primary"
|
||||||
|
disabled={isLoading || !txConfig || isPrepareError}
|
||||||
|
>
|
||||||
|
{isLoading ? <Loader /> : 'Make it rain'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => $isInitSend.set(false)}
|
||||||
|
className="link"
|
||||||
|
disabled={isLoading}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</footer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
1
src/features/Web3/components/Preview/index.tsx
Normal file
1
src/features/Web3/components/Preview/index.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './Preview'
|
@ -1,29 +1,3 @@
|
|||||||
.send {
|
.send {
|
||||||
margin-top: calc(var(--spacer) / 2);
|
margin-top: calc(var(--spacer) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions button {
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions button:first-child {
|
|
||||||
margin-right: var(--spacer);
|
|
||||||
width: 115px;
|
|
||||||
height: 50px;
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert {
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
@ -1,71 +1,11 @@
|
|||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { useEnsAddress, useEnsName } from 'wagmi'
|
import { $txHash } from '@features/Web3/stores'
|
||||||
import { $isInitSend, $txHash } from '@features/Web3/stores'
|
|
||||||
import siteConfig from '@config/blog.config'
|
|
||||||
import styles from './Send.module.css'
|
import styles from './Send.module.css'
|
||||||
import { SendTable } from './SendTable'
|
import { Success } from '../Success'
|
||||||
import { Loader } from '@components/Loader'
|
import { Preview } from '../Preview'
|
||||||
import { usePrepareSend } from '@features/Web3/hooks/usePrepareSend'
|
|
||||||
import { useSend } from '@features/Web3/hooks/useSend'
|
|
||||||
|
|
||||||
export function Send({ amount }: { amount: string }) {
|
export function Send() {
|
||||||
const txHash = useStore($txHash)
|
const txHash = useStore($txHash)
|
||||||
|
|
||||||
// Always resolve to address from ENS name and vice versa
|
return <div className={styles.send}>{txHash ? <Success /> : <Preview />}</div>
|
||||||
// so nobody has to trust my config values.
|
|
||||||
const { ens } = siteConfig.author.ether
|
|
||||||
const { data: to } = useEnsAddress({ name: ens, chainId: 1 })
|
|
||||||
const { data: ensResolved } = useEnsName({
|
|
||||||
address: to as `0x${string}` | undefined,
|
|
||||||
chainId: 1
|
|
||||||
})
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: txConfig,
|
|
||||||
error: prepareError,
|
|
||||||
isError: isPrepareError
|
|
||||||
} = usePrepareSend({ amount, to })
|
|
||||||
const { handleSend, isLoading, error } = useSend({ txConfig })
|
|
||||||
|
|
||||||
// Cancel send flow if chain changes as this can mess with token selection
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (!chain?.id || $isInitSend.get() === false) return
|
|
||||||
// $isInitSend.set(false)
|
|
||||||
// }, [chain?.id])
|
|
||||||
|
|
||||||
console.log(txHash)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className={styles.send}>
|
|
||||||
{/* <h5 className={styles.title}>You are sending</h5> */}
|
|
||||||
|
|
||||||
<SendTable
|
|
||||||
to={to}
|
|
||||||
ensResolved={ensResolved}
|
|
||||||
txConfig={txConfig}
|
|
||||||
isDisabled={isLoading}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className={styles.alert}>{error || prepareError}</div>
|
|
||||||
|
|
||||||
<footer className={styles.actions}>
|
|
||||||
<button
|
|
||||||
onClick={(e) => handleSend(e)}
|
|
||||||
className="btn btn-primary"
|
|
||||||
disabled={isLoading || !txConfig || isPrepareError}
|
|
||||||
>
|
|
||||||
{isLoading ? <Loader /> : 'Make it rain'}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={() => $isInitSend.set(false)}
|
|
||||||
className="link"
|
|
||||||
disabled={isLoading}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
8
src/features/Web3/components/Success/Success.module.css
Normal file
8
src/features/Web3/components/Success/Success.module.css
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.success {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: var(--spacer);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: var(--font-size-h3);
|
||||||
|
}
|
37
src/features/Web3/components/Success/Success.tsx
Normal file
37
src/features/Web3/components/Success/Success.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { $txHash, $isInitSend } from '@features/Web3/stores'
|
||||||
|
import { useStore } from '@nanostores/react'
|
||||||
|
import styles from './Success.module.css'
|
||||||
|
|
||||||
|
export function Success() {
|
||||||
|
const txHash = useStore($txHash)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.success}>
|
||||||
|
<h5 className={styles.title}>You're amazing!</h5>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Your transaction has been sent. You can check the status on{' '}
|
||||||
|
<a
|
||||||
|
href={`https://etherscan.io/tx/${txHash}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Etherscan
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<code>0xxxx{txHash}</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<footer className={styles.actions}>
|
||||||
|
<button
|
||||||
|
onClick={() => $isInitSend.set(false)}
|
||||||
|
className="btn btn-primary"
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
1
src/features/Web3/components/Success/index.tsx
Normal file
1
src/features/Web3/components/Success/index.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './Success'
|
@ -6,14 +6,17 @@ import { Icon as ChevronsDown } from '@images/components/react/ChevronsDown'
|
|||||||
import { Icon as ChevronsUp } from '@images/components/react/ChevronsUp'
|
import { Icon as ChevronsUp } from '@images/components/react/ChevronsUp'
|
||||||
import { useFetchTokens } from '@features/Web3/hooks/useFetchTokens'
|
import { useFetchTokens } from '@features/Web3/hooks/useFetchTokens'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { $tokens } from '@features/Web3/stores/tokens'
|
import { $setTokens, $tokens } from '@features/Web3/stores'
|
||||||
import {
|
import {
|
||||||
$selectedToken,
|
$selectedToken,
|
||||||
$setSelectedToken
|
$setSelectedToken
|
||||||
} from '@features/Web3/stores/selectedToken'
|
} from '@features/Web3/stores/selectedToken'
|
||||||
import { Loader } from '@components/Loader'
|
import { Loader } from '@components/Loader'
|
||||||
|
import { useAccount } from 'wagmi'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
export function TokenSelect() {
|
export function TokenSelect() {
|
||||||
|
const { address } = useAccount()
|
||||||
const { isLoading } = useFetchTokens()
|
const { isLoading } = useFetchTokens()
|
||||||
const tokens = useStore($tokens)
|
const tokens = useStore($tokens)
|
||||||
const selectedToken = useStore($selectedToken)
|
const selectedToken = useStore($selectedToken)
|
||||||
@ -28,6 +31,13 @@ export function TokenSelect() {
|
|||||||
$setSelectedToken(token)
|
$setSelectedToken(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset when no account connected
|
||||||
|
useEffect(() => {
|
||||||
|
if (!address && tokens?.length) {
|
||||||
|
$setTokens(undefined)
|
||||||
|
}
|
||||||
|
}, [address])
|
||||||
|
|
||||||
return tokens && selectedToken ? (
|
return tokens && selectedToken ? (
|
||||||
<Select.Root
|
<Select.Root
|
||||||
defaultValue={selectedToken?.address}
|
defaultValue={selectedToken?.address}
|
||||||
@ -38,7 +48,6 @@ export function TokenSelect() {
|
|||||||
className="SelectTrigger"
|
className="SelectTrigger"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
aria-label="Token"
|
aria-label="Token"
|
||||||
placeholder="..."
|
|
||||||
>
|
>
|
||||||
<Select.Value />
|
<Select.Value />
|
||||||
<Select.Icon>
|
<Select.Icon>
|
||||||
|
@ -5,18 +5,17 @@ import type {
|
|||||||
SendTransactionArgs,
|
SendTransactionArgs,
|
||||||
WriteContractPreparedArgs
|
WriteContractPreparedArgs
|
||||||
} from 'wagmi/actions'
|
} from 'wagmi/actions'
|
||||||
import { $selectedToken } from '@features/Web3/stores'
|
import { $amount, $selectedToken } from '@features/Web3/stores'
|
||||||
import { prepare } from './prepare'
|
import { prepare } from './prepare'
|
||||||
|
|
||||||
export function usePrepareSend({
|
export function usePrepareSend({
|
||||||
amount,
|
|
||||||
to
|
to
|
||||||
}: {
|
}: {
|
||||||
amount: string
|
|
||||||
to: `0x${string}` | null | undefined
|
to: `0x${string}` | null | undefined
|
||||||
}) {
|
}) {
|
||||||
const { chain } = useNetwork()
|
|
||||||
const selectedToken = useStore($selectedToken)
|
const selectedToken = useStore($selectedToken)
|
||||||
|
const amount = useStore($amount)
|
||||||
|
const { chain } = useNetwork()
|
||||||
|
|
||||||
const [txConfig, setTxConfig] = useState<
|
const [txConfig, setTxConfig] = useState<
|
||||||
SendTransactionArgs | WriteContractPreparedArgs
|
SendTransactionArgs | WriteContractPreparedArgs
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { $txHash, $selectedToken } from '@features/Web3/stores'
|
import { $txHash, $selectedToken } from '@features/Web3/stores'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { useState, type FormEvent } from 'react'
|
import { useState } from 'react'
|
||||||
import type {
|
import type {
|
||||||
SendTransactionArgs,
|
SendTransactionArgs,
|
||||||
WriteContractPreparedArgs
|
WriteContractPreparedArgs
|
||||||
@ -18,9 +18,7 @@ export function useSend({
|
|||||||
const [isError, setIsError] = useState(false)
|
const [isError, setIsError] = useState(false)
|
||||||
const [error, setError] = useState<string | undefined>()
|
const [error, setError] = useState<string | undefined>()
|
||||||
|
|
||||||
async function handleSend(event: FormEvent<HTMLButtonElement>) {
|
async function handleSend() {
|
||||||
event?.preventDefault()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsError(false)
|
setIsError(false)
|
||||||
setError(undefined)
|
setError(undefined)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { atom } from 'nanostores'
|
import { atom } from 'nanostores'
|
||||||
|
|
||||||
export const $isInitSend = atom<boolean>(false)
|
export const $isInitSend = atom<boolean>(false)
|
||||||
|
export const $amount = atom<string>('')
|
||||||
export const $txHash = atom<string | undefined>()
|
export const $txHash = atom<string | undefined>()
|
||||||
|
@ -6,7 +6,7 @@ export const $tokens = atom<GetToken[] | undefined>()
|
|||||||
export const $setTokens = action(
|
export const $setTokens = action(
|
||||||
$tokens,
|
$tokens,
|
||||||
'setTokens',
|
'setTokens',
|
||||||
(store, tokens: GetToken[]) => {
|
(store, tokens: GetToken[] | undefined) => {
|
||||||
store.set(tokens)
|
store.set(tokens)
|
||||||
return store.get()
|
return store.get()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user