mirror of
https://github.com/kremalicious/asi-calculator.git
synced 2024-12-22 17:33:18 +01:00
refactor to allow switching markets
This commit is contained in:
parent
1496238b4a
commit
c75354a54d
@ -1,9 +1,9 @@
|
||||
import styles from './page.module.css'
|
||||
import { Swap, Buy } from '@/components/Strategies'
|
||||
import { Swap, Buy } from '@/features/strategies'
|
||||
import { Content } from '@/components/Content'
|
||||
import { CalculationBase } from '@/components/CalculationBaseOutput'
|
||||
import { Header } from '@/components/Header'
|
||||
import { Footer } from '@/components/Footer'
|
||||
import { MarketData } from '@/features/prices'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
@ -16,7 +16,7 @@ export default function Home() {
|
||||
<Swap />
|
||||
<Buy />
|
||||
</div>
|
||||
<CalculationBase />
|
||||
<MarketData />
|
||||
</section>
|
||||
|
||||
<Content />
|
||||
|
@ -1 +0,0 @@
|
||||
export * from './CalculationBase'
|
@ -1,26 +0,0 @@
|
||||
import { InputAmount } from '@/components/FormAmount/Inputs/InputAmount'
|
||||
import { InputToken } from './Inputs/InputToken'
|
||||
import styles from './FormAmount.module.css'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { TokenSymbol } from '@/types'
|
||||
|
||||
export function FormAmount({
|
||||
amount,
|
||||
setAmount,
|
||||
token,
|
||||
setToken,
|
||||
isFiat
|
||||
}: {
|
||||
amount: number
|
||||
setAmount: Dispatch<SetStateAction<number>>
|
||||
token: TokenSymbol | string
|
||||
setToken?: Dispatch<SetStateAction<TokenSymbol>>
|
||||
isFiat?: boolean
|
||||
}) {
|
||||
return (
|
||||
<form className={styles.form}>
|
||||
<InputAmount amount={amount} setAmount={setAmount} />
|
||||
<InputToken token={token} setToken={setToken} isFiat={isFiat} />
|
||||
</form>
|
||||
)
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import styles from './InputToken.module.css'
|
||||
import { CaretDownIcon } from '@radix-ui/react-icons'
|
||||
import { TokenSymbol } from '@/types'
|
||||
import { useSWRConfig } from 'swr'
|
||||
|
||||
export function InputToken({
|
||||
token,
|
||||
setToken,
|
||||
isFiat
|
||||
}: {
|
||||
token: TokenSymbol | string
|
||||
isFiat?: boolean
|
||||
setToken?: Dispatch<SetStateAction<TokenSymbol>>
|
||||
}) {
|
||||
const { mutate } = useSWRConfig()
|
||||
|
||||
return (
|
||||
<span className={styles.selectWrapper}>
|
||||
<select
|
||||
className={styles.select}
|
||||
onChange={(e) => {
|
||||
if (!setToken) return
|
||||
|
||||
setToken(e.target.value as TokenSymbol)
|
||||
mutate('/api/quote')
|
||||
}}
|
||||
value={token}
|
||||
disabled={!setToken}
|
||||
style={setToken ? { paddingRight: '1.25rem' } : {}}
|
||||
>
|
||||
{isFiat ? (
|
||||
<option value="USD">USD</option>
|
||||
) : (
|
||||
<>
|
||||
<option value="OCEAN">OCEAN</option>
|
||||
<option value="FET">FET</option>
|
||||
<option value="AGIX">AGIX</option>
|
||||
</>
|
||||
)}
|
||||
</select>
|
||||
{setToken ? <CaretDownIcon className={styles.icon} /> : null}
|
||||
</span>
|
||||
)
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './ResultRow'
|
@ -1,3 +1,7 @@
|
||||
.selectWrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.select {
|
||||
display: inline-block;
|
||||
all: unset;
|
||||
@ -23,10 +27,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.selectWrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
right: 0.1rem;
|
22
components/Select/Select.tsx
Normal file
22
components/Select/Select.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { SelectHTMLAttributes } from 'react'
|
||||
import styles from './Select.module.css'
|
||||
import { CaretDownIcon } from '@radix-ui/react-icons'
|
||||
|
||||
type Props = SelectHTMLAttributes<HTMLSelectElement> & {
|
||||
options: { value: string; label: string }[]
|
||||
}
|
||||
|
||||
export function Select({ options, ...rest }: Props) {
|
||||
return (
|
||||
<span className={styles.selectWrapper}>
|
||||
<select className={styles.select} {...rest}>
|
||||
{options.map((option) => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{options.length > 1 ? <CaretDownIcon className={styles.icon} /> : null}
|
||||
</span>
|
||||
)
|
||||
}
|
1
components/Select/index.tsx
Normal file
1
components/Select/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from './Select'
|
@ -1,66 +0,0 @@
|
||||
import { Result } from '@/components/ResultRow'
|
||||
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
|
||||
import { usePrices } from '@/hooks'
|
||||
import { getTokenBySymbol } from '@/lib/utils'
|
||||
import { TokenSymbol } from '@/types'
|
||||
import { useQuote } from '@/hooks'
|
||||
|
||||
export function SwapResults({
|
||||
tokenSymbol,
|
||||
amount
|
||||
}: {
|
||||
tokenSymbol: TokenSymbol
|
||||
amount: number
|
||||
}) {
|
||||
const {
|
||||
prices,
|
||||
isValidating: isValidatingPrices,
|
||||
isLoading: isLoadingPrices
|
||||
} = usePrices()
|
||||
|
||||
const {
|
||||
amountToOcean,
|
||||
amountToAgix,
|
||||
amountToFet,
|
||||
isValidatingToAgix,
|
||||
isLoadingToAgix,
|
||||
isValidatingToFet,
|
||||
isLoadingToFet,
|
||||
isValidatingToOcean,
|
||||
isLoadingToOcean
|
||||
} = useQuote(tokenSymbol, amount)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Result
|
||||
token={getTokenBySymbol('OCEAN')}
|
||||
amount={amountToOcean}
|
||||
amountAsi={amountToOcean * ratioOceanToAsi}
|
||||
amountFiat={amountToOcean * ratioOceanToAsi * prices.asi}
|
||||
amountOriginalFiat={amountToOcean * prices.ocean}
|
||||
isValidating={isValidatingToOcean || isValidatingPrices}
|
||||
isLoading={isLoadingToOcean || isLoadingPrices}
|
||||
/>
|
||||
|
||||
<Result
|
||||
token={getTokenBySymbol('AGIX')}
|
||||
amount={amountToAgix}
|
||||
amountAsi={amountToAgix * ratioAgixToAsi}
|
||||
amountFiat={amountToAgix * ratioAgixToAsi * prices.asi}
|
||||
amountOriginalFiat={amountToAgix * prices.agix}
|
||||
isValidating={isValidatingToAgix || isValidatingPrices}
|
||||
isLoading={isLoadingToAgix || isLoadingPrices}
|
||||
/>
|
||||
|
||||
<Result
|
||||
token={getTokenBySymbol('FET')}
|
||||
amount={amountToFet}
|
||||
amountAsi={amountToFet * ratioFetToAsi}
|
||||
amountFiat={amountToFet * prices.asi}
|
||||
amountOriginalFiat={amountToFet * prices.asi}
|
||||
isValidating={isValidatingToFet || isValidatingPrices}
|
||||
isLoading={isLoadingToFet || isLoadingPrices}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
export * from './Buy'
|
||||
export * from './Swap/Swap'
|
@ -1,4 +1,4 @@
|
||||
.calculationBase {
|
||||
.marketData {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(235px, 1fr));
|
||||
justify-content: center;
|
||||
@ -9,14 +9,14 @@
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.calculationBase li {
|
||||
.marketData li {
|
||||
border-bottom: 1px solid rgba(var(--foreground-rgb), 0.2);
|
||||
border-right: 1px solid rgba(var(--foreground-rgb), 0.2);
|
||||
padding: 1rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.calculationBase p {
|
||||
.marketData p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
'use client'
|
||||
|
||||
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
|
||||
import styles from './CalculationBase.module.css'
|
||||
import { usePrices } from '@/hooks'
|
||||
import styles from './MarketData.module.css'
|
||||
import { usePrices } from '@/features/prices/hooks'
|
||||
import { Label } from '@/components/Label'
|
||||
|
||||
export function CalculationBase() {
|
||||
export function MarketData() {
|
||||
const { prices, isValidating, isLoading } = usePrices()
|
||||
|
||||
const feedbackClasses = isLoading
|
||||
@ -15,7 +15,7 @@ export function CalculationBase() {
|
||||
: ''
|
||||
|
||||
return (
|
||||
<ul className={styles.calculationBase}>
|
||||
<ul className={styles.marketData}>
|
||||
<li>
|
||||
<p>1 ASI</p>
|
||||
<p>
|
1
features/prices/components/MarketData/index.tsx
Normal file
1
features/prices/components/MarketData/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from './MarketData'
|
@ -1,2 +1 @@
|
||||
export * from './use-prices'
|
||||
export * from './use-quote'
|
@ -4,6 +4,13 @@ import useSWR from 'swr'
|
||||
|
||||
const tokenAddresses = tokens.map((token) => token.address).toString()
|
||||
|
||||
export type Prices = {
|
||||
ocean: number
|
||||
fet: number
|
||||
agix: number
|
||||
asi: number
|
||||
}
|
||||
|
||||
export function usePrices(): {
|
||||
prices: { ocean: number; fet: number; agix: number; asi: number }
|
||||
isValidating: boolean
|
2
features/prices/index.tsx
Normal file
2
features/prices/index.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './components/MarketData'
|
||||
export * from './hooks'
|
@ -1,13 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
|
||||
import { Result } from '@/components/ResultRow'
|
||||
import { useState } from 'react'
|
||||
import { useDebounce } from 'use-debounce'
|
||||
import stylesShared from './styles.module.css'
|
||||
import { usePrices } from '@/hooks'
|
||||
import { FormAmount } from '@/components/FormAmount'
|
||||
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
|
||||
import { usePrices } from '@/features/prices'
|
||||
import { getTokenBySymbol } from '@/lib/utils'
|
||||
import { FormAmount, Result } from '@/features/strategies/components'
|
||||
import stylesShared from '@/features/strategies/styles/shared.module.css'
|
||||
|
||||
export function Buy() {
|
||||
const { prices, isValidating, isLoading } = usePrices()
|
46
features/strategies/components/FormAmount/FormAmount.tsx
Normal file
46
features/strategies/components/FormAmount/FormAmount.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { InputAmount } from './Inputs/InputAmount'
|
||||
import styles from './FormAmount.module.css'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { TokenSymbol } from '@/types'
|
||||
import { Select } from '@/components/Select'
|
||||
|
||||
export function FormAmount({
|
||||
amount,
|
||||
setAmount,
|
||||
token,
|
||||
setToken,
|
||||
isFiat
|
||||
}: {
|
||||
amount: number
|
||||
setAmount: Dispatch<SetStateAction<number>>
|
||||
token: TokenSymbol | string
|
||||
setToken?: Dispatch<SetStateAction<TokenSymbol>>
|
||||
isFiat?: boolean
|
||||
}) {
|
||||
function handleTokenChange(e: React.ChangeEvent<HTMLSelectElement>) {
|
||||
if (!setToken) return
|
||||
setToken(e.target.value as TokenSymbol)
|
||||
}
|
||||
|
||||
const options = isFiat
|
||||
? [{ value: 'USD', label: 'USD' }]
|
||||
: [
|
||||
{ value: 'OCEAN', label: 'OCEAN' },
|
||||
{ value: 'FET', label: 'FET' },
|
||||
{ value: 'AGIX', label: 'AGIX' }
|
||||
]
|
||||
|
||||
return (
|
||||
<form className={styles.form}>
|
||||
<InputAmount amount={amount} setAmount={setAmount} />
|
||||
|
||||
<Select
|
||||
options={options}
|
||||
value={token}
|
||||
onChange={handleTokenChange}
|
||||
disabled={!setToken}
|
||||
style={setToken ? { paddingRight: '1.25rem' } : {}}
|
||||
/>
|
||||
</form>
|
||||
)
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
'use client'
|
||||
|
||||
import { Dispatch, SetStateAction, useRef, useState } from 'react'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import styles from './InputAmount.module.css'
|
||||
|
||||
export function InputAmount({
|
@ -0,0 +1,8 @@
|
||||
.form {
|
||||
display: inline-flex;
|
||||
border: 1px solid rgba(var(--foreground-rgb), 0.15);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
margin: -0.15em 0.25rem 0 0.25rem;
|
||||
font-size: 0.9em;
|
||||
}
|
27
features/strategies/components/FormMarket/FormMarket.tsx
Normal file
27
features/strategies/components/FormMarket/FormMarket.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import styles from './FormMarket.module.css'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { Select } from '@/components/Select'
|
||||
import { type Market } from '@/features/strategies'
|
||||
|
||||
export function FormMarket({
|
||||
market,
|
||||
setMarket
|
||||
}: {
|
||||
market: Market
|
||||
setMarket: Dispatch<SetStateAction<Market>>
|
||||
}) {
|
||||
const options = [
|
||||
{ value: 'market', label: 'All Markets' },
|
||||
{ value: 'uniswap-v3', label: 'Uniswap v3' }
|
||||
]
|
||||
return (
|
||||
<form className={styles.form}>
|
||||
<Select
|
||||
options={options}
|
||||
value={market}
|
||||
onChange={(e) => setMarket(e.target.value as Market)}
|
||||
style={{ paddingRight: '1.25rem' }}
|
||||
/>
|
||||
</form>
|
||||
)
|
||||
}
|
1
features/strategies/components/FormMarket/index.tsx
Normal file
1
features/strategies/components/FormMarket/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from './FormMarket'
|
@ -1,7 +1,7 @@
|
||||
import styles from './ResultRow.module.css'
|
||||
import styles from './Result.module.css'
|
||||
import { formatNumber } from '@/lib/utils'
|
||||
import { ArrowRightIcon } from '@radix-ui/react-icons'
|
||||
import { TokenLogo } from '../TokenLogo/TokenLogo'
|
||||
import { TokenLogo } from '../../../../components/TokenLogo/TokenLogo'
|
||||
import { Token } from '@/types'
|
||||
|
||||
type Props = {
|
1
features/strategies/components/Result/index.tsx
Normal file
1
features/strategies/components/Result/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from './Result'
|
81
features/strategies/components/Swap/Results.tsx
Normal file
81
features/strategies/components/Swap/Results.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
|
||||
import { usePrices, type Prices } from '@/features/prices'
|
||||
import { getTokenBySymbol } from '@/lib/utils'
|
||||
import { TokenSymbol } from '@/types'
|
||||
import { useQuote, type Market } from '@/features/strategies'
|
||||
import { Result } from '../Result'
|
||||
|
||||
export function SwapResults({
|
||||
tokenSymbol,
|
||||
amount,
|
||||
market
|
||||
}: {
|
||||
tokenSymbol: TokenSymbol
|
||||
amount: number
|
||||
market: Market
|
||||
}) {
|
||||
const isUniswap = market === 'uniswap-v3'
|
||||
|
||||
const {
|
||||
prices,
|
||||
isValidating: isValidatingPrices,
|
||||
isLoading: isLoadingPrices
|
||||
} = usePrices()
|
||||
|
||||
const {
|
||||
amountToOcean: amountToOceanUniswap,
|
||||
amountToAgix: amountToAgixUniswap,
|
||||
amountToFet: amountToFetUniswap,
|
||||
isValidatingToAgix,
|
||||
isLoadingToAgix,
|
||||
isValidatingToFet,
|
||||
isLoadingToFet,
|
||||
isValidatingToOcean,
|
||||
isLoadingToOcean
|
||||
} = useQuote(tokenSymbol, amount, isUniswap)
|
||||
|
||||
const amountInUsd = amount * prices[tokenSymbol.toLowerCase() as keyof Prices]
|
||||
const amountToOcean = amountInUsd / prices.ocean
|
||||
const amountToAgix = amountInUsd / prices.agix
|
||||
const amountToFet = amountInUsd / prices.fet
|
||||
|
||||
return (
|
||||
<>
|
||||
<Result
|
||||
token={getTokenBySymbol('OCEAN')}
|
||||
amount={amountToOceanUniswap || amountToOcean}
|
||||
amountAsi={(amountToOceanUniswap || amountToOcean) * ratioOceanToAsi}
|
||||
amountFiat={
|
||||
(amountToOceanUniswap || amountToOcean) * ratioOceanToAsi * prices.asi
|
||||
}
|
||||
amountOriginalFiat={
|
||||
(amountToOceanUniswap || amountToOcean) * prices.ocean
|
||||
}
|
||||
isValidating={isValidatingToOcean || isValidatingPrices}
|
||||
isLoading={isLoadingToOcean || isLoadingPrices}
|
||||
/>
|
||||
|
||||
<Result
|
||||
token={getTokenBySymbol('AGIX')}
|
||||
amount={amountToAgixUniswap || amountToAgix}
|
||||
amountAsi={(amountToAgixUniswap || amountToAgix) * ratioAgixToAsi}
|
||||
amountFiat={
|
||||
(amountToAgixUniswap || amountToAgix) * ratioAgixToAsi * prices.asi
|
||||
}
|
||||
amountOriginalFiat={(amountToAgixUniswap || amountToAgix) * prices.agix}
|
||||
isValidating={isValidatingToAgix || isValidatingPrices}
|
||||
isLoading={isLoadingToAgix || isLoadingPrices}
|
||||
/>
|
||||
|
||||
<Result
|
||||
token={getTokenBySymbol('FET')}
|
||||
amount={amountToFetUniswap || amountToFet}
|
||||
amountAsi={(amountToFetUniswap || amountToFet) * ratioFetToAsi}
|
||||
amountFiat={(amountToFetUniswap || amountToFet) * prices.asi}
|
||||
amountOriginalFiat={(amountToFetUniswap || amountToFet) * prices.asi}
|
||||
isValidating={isValidatingToFet || isValidatingPrices}
|
||||
isLoading={isLoadingToFet || isLoadingPrices}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,16 +1,18 @@
|
||||
'use client'
|
||||
|
||||
import stylesShared from '../styles.module.css'
|
||||
import { useState } from 'react'
|
||||
import { useDebounce } from 'use-debounce'
|
||||
import { FormAmount } from '@/components/FormAmount'
|
||||
import { SwapResults } from './Results'
|
||||
import { TokenSymbol } from '@/types'
|
||||
import { FormAmount, FormMarket } from '@/features/strategies/components'
|
||||
import stylesShared from '@/features/strategies/styles/shared.module.css'
|
||||
import { type Market } from '@/features/strategies'
|
||||
|
||||
export function Swap() {
|
||||
const [amount, setAmount] = useState(100)
|
||||
const [debouncedAmount] = useDebounce(amount, 500)
|
||||
const [tokenSymbol, setTokenSymbol] = useState<TokenSymbol>('OCEAN')
|
||||
const [market, setMarket] = useState<Market>('all')
|
||||
|
||||
return (
|
||||
<div className={stylesShared.results}>
|
||||
@ -22,10 +24,15 @@ export function Swap() {
|
||||
setAmount={setAmount}
|
||||
setToken={setTokenSymbol}
|
||||
/>{' '}
|
||||
on Uniswap right now gets you:
|
||||
on <FormMarket market={market} setMarket={setMarket} /> right now gets
|
||||
you:
|
||||
</h3>
|
||||
|
||||
<SwapResults tokenSymbol={tokenSymbol} amount={debouncedAmount} />
|
||||
<SwapResults
|
||||
tokenSymbol={tokenSymbol}
|
||||
amount={debouncedAmount}
|
||||
market={market}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
3
features/strategies/components/index.tsx
Normal file
3
features/strategies/components/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './FormAmount'
|
||||
export * from './FormMarket'
|
||||
export * from './Result'
|
1
features/strategies/hooks/index.tsx
Normal file
1
features/strategies/hooks/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from './use-quote'
|
89
features/strategies/hooks/use-quote.ts
Normal file
89
features/strategies/hooks/use-quote.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { TokenSymbol } from '@/types'
|
||||
import { getTokenAddressBySymbol, fetcher } from '@/lib/utils'
|
||||
import useSWR from 'swr'
|
||||
|
||||
const options = {
|
||||
keepPreviousData: true // so loading UI can kick in properly
|
||||
}
|
||||
|
||||
export function useQuote(
|
||||
tokenSymbol: TokenSymbol,
|
||||
amount: number,
|
||||
shouldFetch: boolean
|
||||
) {
|
||||
// -> AGIX
|
||||
const {
|
||||
data: dataSwapToAgix,
|
||||
isValidating: isValidatingToAgix,
|
||||
isLoading: isLoadingToAgix
|
||||
} = useSWR(
|
||||
shouldFetch
|
||||
? `/api/quote/?tokenIn=${getTokenAddressBySymbol(
|
||||
tokenSymbol
|
||||
)}&tokenOut=${getTokenAddressBySymbol('AGIX')}&amountIn=${amount}`
|
||||
: null,
|
||||
fetcher,
|
||||
options
|
||||
)
|
||||
|
||||
// -> FET
|
||||
const {
|
||||
data: dataSwapToFet,
|
||||
isValidating: isValidatingToFet,
|
||||
isLoading: isLoadingToFet
|
||||
} = useSWR(
|
||||
shouldFetch
|
||||
? `/api/quote/?tokenIn=${getTokenAddressBySymbol(
|
||||
tokenSymbol
|
||||
)}&tokenOut=${getTokenAddressBySymbol('FET')}&amountIn=${amount}`
|
||||
: null,
|
||||
fetcher,
|
||||
options
|
||||
)
|
||||
|
||||
// -> OCEAN
|
||||
const {
|
||||
data: dataSwapToOcean,
|
||||
isValidating: isValidatingToOcean,
|
||||
isLoading: isLoadingToOcean
|
||||
} = useSWR(
|
||||
shouldFetch
|
||||
? `/api/quote/?tokenIn=${getTokenAddressBySymbol(
|
||||
tokenSymbol
|
||||
)}&tokenOut=${getTokenAddressBySymbol('OCEAN')}&amountIn=${amount}`
|
||||
: null,
|
||||
fetcher,
|
||||
options
|
||||
)
|
||||
|
||||
const amountToOcean =
|
||||
dataSwapToOcean?.amountOut / Number(`1e${dataSwapToOcean?.decimals}`)
|
||||
const amountToAgix =
|
||||
dataSwapToAgix?.amountOut / Number(`1e${dataSwapToAgix?.decimals}`)
|
||||
const amountToFet =
|
||||
dataSwapToFet?.amountOut / Number(`1e${dataSwapToFet?.decimals}`)
|
||||
|
||||
return shouldFetch
|
||||
? {
|
||||
amountToOcean,
|
||||
amountToAgix,
|
||||
amountToFet,
|
||||
isValidatingToAgix,
|
||||
isLoadingToAgix,
|
||||
isValidatingToFet,
|
||||
isLoadingToFet,
|
||||
isValidatingToOcean,
|
||||
isLoadingToOcean
|
||||
}
|
||||
: {
|
||||
amountToOcean: undefined,
|
||||
amountToAgix: undefined,
|
||||
amountToFet: undefined,
|
||||
isValidatingToAgix: false,
|
||||
isLoadingToAgix: false,
|
||||
isValidatingToFet: false,
|
||||
isLoadingToFet: false,
|
||||
isValidatingToOcean: false,
|
||||
isLoadingToOcean: false
|
||||
}
|
||||
}
|
4
features/strategies/index.tsx
Normal file
4
features/strategies/index.tsx
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './components/Buy'
|
||||
export * from './components/Swap/Swap'
|
||||
export * from './hooks'
|
||||
export * from './types'
|
@ -9,4 +9,5 @@
|
||||
font-size: 1.2rem;
|
||||
color: rgb(var(--foreground-rgb-highlight));
|
||||
min-height: 58px;
|
||||
line-height: 1.5;
|
||||
}
|
1
features/strategies/types.ts
Normal file
1
features/strategies/types.ts
Normal file
@ -0,0 +1 @@
|
||||
export type Market = 'all' | 'uniswap-v3'
|
@ -1,67 +0,0 @@
|
||||
import { TokenSymbol } from '@/types'
|
||||
import { getTokenAddressBySymbol, fetcher } from '@/lib/utils'
|
||||
import useSWR from 'swr'
|
||||
|
||||
const options = {
|
||||
keepPreviousData: true // so loading UI can kick in properly
|
||||
}
|
||||
|
||||
export function useQuote(tokenSymbol: TokenSymbol, amount: number) {
|
||||
// -> AGIX
|
||||
const {
|
||||
data: dataSwapToAgix,
|
||||
isValidating: isValidatingToAgix,
|
||||
isLoading: isLoadingToAgix
|
||||
} = useSWR(
|
||||
`/api/quote/?tokenIn=${getTokenAddressBySymbol(
|
||||
tokenSymbol
|
||||
)}&tokenOut=${getTokenAddressBySymbol('AGIX')}&amountIn=${amount}`,
|
||||
fetcher,
|
||||
options
|
||||
)
|
||||
|
||||
// -> FET
|
||||
const {
|
||||
data: dataSwapToFet,
|
||||
isValidating: isValidatingToFet,
|
||||
isLoading: isLoadingToFet
|
||||
} = useSWR(
|
||||
`/api/quote/?tokenIn=${getTokenAddressBySymbol(
|
||||
tokenSymbol
|
||||
)}&tokenOut=${getTokenAddressBySymbol('FET')}&amountIn=${amount}`,
|
||||
fetcher,
|
||||
options
|
||||
)
|
||||
|
||||
// -> OCEAN
|
||||
const {
|
||||
data: dataSwapToOcean,
|
||||
isValidating: isValidatingToOcean,
|
||||
isLoading: isLoadingToOcean
|
||||
} = useSWR(
|
||||
`/api/quote/?tokenIn=${getTokenAddressBySymbol(
|
||||
tokenSymbol
|
||||
)}&tokenOut=${getTokenAddressBySymbol('OCEAN')}&amountIn=${amount}`,
|
||||
fetcher,
|
||||
options
|
||||
)
|
||||
|
||||
const amountToOcean =
|
||||
dataSwapToOcean?.amountOut / Number(`1e${dataSwapToOcean?.decimals}`)
|
||||
const amountToAgix =
|
||||
dataSwapToAgix?.amountOut / Number(`1e${dataSwapToAgix?.decimals}`)
|
||||
const amountToFet =
|
||||
dataSwapToFet?.amountOut / Number(`1e${dataSwapToFet?.decimals}`)
|
||||
|
||||
return {
|
||||
amountToOcean,
|
||||
amountToAgix,
|
||||
amountToFet,
|
||||
isValidatingToAgix,
|
||||
isLoadingToAgix,
|
||||
isValidatingToFet,
|
||||
isLoadingToFet,
|
||||
isValidatingToOcean,
|
||||
isLoadingToOcean
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user