This commit is contained in:
Matthias Kretschmann 2024-03-31 15:48:31 +01:00
parent 1ffaab23f5
commit 6123e5d182
Signed by: m
GPG Key ID: 606EEEF3C479A91F
13 changed files with 116 additions and 59 deletions

View File

@ -3,7 +3,7 @@
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
import styles from './CalculationBase.module.css'
import { usePrices } from '@/hooks'
import { Label } from '../Label'
import { Label } from '@/components/Label'
export function CalculationBase() {
const { prices, isValidating } = usePrices()

View File

@ -2,7 +2,7 @@ import { InputAmount } from '@/components/FormAmount/Inputs/InputAmount'
import { InputToken } from './Inputs/InputToken'
import styles from './FormAmount.module.css'
import { Dispatch, SetStateAction } from 'react'
import { Token } from './types'
import { TokenSymbol } from '@/types'
export function FormAmount({
amount,
@ -13,8 +13,8 @@ export function FormAmount({
}: {
amount: number
setAmount: Dispatch<SetStateAction<number>>
token: Token | string
setToken?: Dispatch<SetStateAction<Token>>
token: TokenSymbol | string
setToken?: Dispatch<SetStateAction<TokenSymbol>>
isFiat?: boolean
}) {
return (

View File

@ -1,33 +1,35 @@
import { Dispatch, SetStateAction } from 'react'
import styles from './InputToken.module.css'
import { CaretDownIcon } from '@radix-ui/react-icons'
import { Token } from '../types'
import { TokenSymbol } from '@/types'
export function InputToken({
token,
setToken,
isFiat
}: {
token: Token | string
token: TokenSymbol | string
isFiat?: boolean
setToken?: Dispatch<SetStateAction<Token>>
setToken?: Dispatch<SetStateAction<TokenSymbol>>
}) {
return (
<span className={styles.selectWrapper}>
<select
className={styles.select}
onChange={(e) => (setToken ? setToken(e.target.value as Token) : null)}
onChange={(e) =>
setToken ? setToken(e.target.value as TokenSymbol) : null
}
value={token}
disabled={!setToken}
style={setToken ? { paddingRight: '1.25rem' } : {}}
>
{isFiat ? (
<option value="usd">USD</option>
<option value="USD">USD</option>
) : (
<>
<option value="ocean">OCEAN</option>
<option value="fet">FET</option>
<option value="agix">AGIX</option>
<option value="OCEAN">OCEAN</option>
<option value="FET">FET</option>
<option value="AGIX">AGIX</option>
</>
)}
</select>

View File

@ -1,2 +1 @@
export * from './FormAmount'
export * from './types'

View File

@ -1 +0,0 @@
export type Token = 'ocean' | 'fet' | 'agix' | undefined

View File

@ -1,58 +1,49 @@
'use client'
import { Result } from '@/components/ResultRow'
import {
ratioOceanToAsi,
ratioAgixToAsi,
ratioFetToAsi,
tokens
} from '@/constants'
import { fetcher } from '@/utils'
import { Result } from '@/components/ResultRow'
import stylesShared from './styles.module.css'
import { useState } from 'react'
import useSWR from 'swr'
import { useDebounce } from 'use-debounce'
import { usePrices } from '@/hooks'
import { FormAmount, type Token } from '@/components/FormAmount'
import { fetcher } from '@/utils'
import useSWR from 'swr'
import { TokenSymbol } from '@/types'
export function Swap() {
export function SwapResults({
token,
amount
}: {
token: TokenSymbol
amount: number
}) {
const { prices, isValidating: isValidatingPrices } = usePrices()
const [amount, setAmount] = useState(100)
const [debouncedAmount] = useDebounce(amount, 500)
const [token, setToken] = useState<Token>('ocean')
const { data: dataSwapOceanToAgix, isValidating: isValidatingOceanToAgix } =
useSWR(
`/api/quote/?tokenIn=${tokens[0]}&tokenOut=${tokens[2]}&amountIn=${debouncedAmount}`,
`/api/quote/?tokenIn=${tokens[0].address}&tokenOut=${tokens[2].address}&amountIn=${amount}`,
fetcher
)
const { data: dataSwapOceanToFet, isValidating: isValidatingOceanToFet } =
useSWR(
`/api/quote/?tokenIn=${tokens[0]}&tokenOut=${tokens[1]}&amountIn=${debouncedAmount}`,
`/api/quote/?tokenIn=${tokens[0].address}&tokenOut=${tokens[1].address}&amountIn=${amount}`,
fetcher
)
return (
<div className={stylesShared.results}>
<h3 className={stylesShared.title}>
Holding or swapping{' '}
<FormAmount
amount={amount}
token={token}
setAmount={setAmount}
// setToken={setToken}
/>{' '}
right now gets you:
</h3>
<>
<Result
tokenSymbol="OCEAN"
tokenAddress="0x967da4048cd07ab37855c090aaf366e4ce1b9f48"
amount={debouncedAmount}
amountAsi={debouncedAmount * ratioOceanToAsi}
amountFiat={debouncedAmount * ratioOceanToAsi * prices.asi}
amountOriginalFiat={token ? debouncedAmount * prices[token] : undefined}
amount={amount}
amountAsi={amount * ratioOceanToAsi}
amountFiat={amount * ratioOceanToAsi * prices.asi}
amountOriginalFiat={
token
? amount *
prices[token.toLowerCase() as 'ocean' | 'agix' | 'fet' | 'asi']
: undefined
}
isValidating={
isValidatingOceanToAgix ||
isValidatingOceanToFet ||
@ -105,6 +96,6 @@ export function Swap() {
}
isValidating={isValidatingOceanToFet || isValidatingPrices}
/>
</div>
</>
)
}

View File

@ -0,0 +1,31 @@
'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'
export function Swap() {
const [amount, setAmount] = useState(100)
const [debouncedAmount] = useDebounce(amount, 500)
const [token, setToken] = useState<TokenSymbol>('OCEAN')
return (
<div className={stylesShared.results}>
<h3 className={stylesShared.title}>
Holding or swapping{' '}
<FormAmount
amount={amount}
token={token}
setAmount={setAmount}
// setToken={setToken}
/>{' '}
right now gets you:
</h3>
<SwapResults token={token} amount={debouncedAmount} />
</div>
)
}

View File

@ -1,2 +1,2 @@
export * from './Buy'
export * from './Swap'
export * from './Swap/Swap'

View File

@ -1,9 +1,11 @@
import { Token } from '@/types'
export const ratioOceanToAsi = 0.433226
export const ratioAgixToAsi = 0.43335
export const ratioFetToAsi = 1
export const tokens: `0x${string}`[] = [
'0x967da4048cd07ab37855c090aaf366e4ce1b9f48', // OCEAN
'0xaea46a60368a7bd060eec7df8cba43b7ef41ad85', // FET
'0x5b7533812759b45c2b44c19e320ba2cd2681b542' // AGIX
export const tokens: Token[] = [
{ symbol: 'OCEAN', address: '0x967da4048cd07ab37855c090aaf366e4ce1b9f48' },
{ symbol: 'FET', address: '0xaea46a60368a7bd060eec7df8cba43b7ef41ad85' },
{ symbol: 'AGIX', address: '0x5b7533812759b45c2b44c19e320ba2cd2681b542' }
]

View File

@ -1,22 +1,33 @@
'use client'
import { tokens } from '@/constants'
import { fetcher } from '@/utils'
import { fetcher, getTokenAddressBySymbol } from '@/utils'
import useSWR from 'swr'
const tokenAddresses = tokens.map((token) => token.address).toString()
export function usePrices(): {
prices: { ocean: number; fet: number; agix: number; asi: number }
isValidating: boolean
isLoading: boolean
} {
const { data, isValidating, isLoading } = useSWR(
`/api/prices/?tokens=${tokens.toString()}`,
`/api/prices/?tokens=${tokenAddresses}`,
fetcher
)
const ocean = data?.[tokens[0]]?.usd || 0
const fet = data?.[tokens[1]]?.usd || 0
const agix = data?.[tokens[2]]?.usd || 0
const oceanAddress = getTokenAddressBySymbol('OCEAN')
const fetAddress = getTokenAddressBySymbol('FET')
const agixAddress = getTokenAddressBySymbol('AGIX')
if (!oceanAddress || !fetAddress || !agixAddress)
return {
prices: { ocean: 0, fet: 0, agix: 0, asi: 0 },
isValidating,
isLoading
}
const ocean = data?.[oceanAddress]?.usd || 0
const fet = data?.[fetAddress]?.usd || 0
const agix = data?.[agixAddress]?.usd || 0
const asi = fet
return { prices: { ocean, fet, agix, asi }, isValidating, isLoading }

7
types/Token.ts Normal file
View File

@ -0,0 +1,7 @@
export type TokenSymbol = 'OCEAN' | 'FET' | 'AGIX' | 'ASI'
export type TokenAddress = `0x${string}`
export type Token = {
symbol: TokenSymbol
address: `0x${string}`
}

1
types/index.ts Normal file
View File

@ -0,0 +1 @@
export * from './Token'

View File

@ -1,3 +1,5 @@
import { tokens } from '@/constants'
import type { TokenAddress, Token } from '@/types'
import { formatCurrency } from '@coingecko/cryptoformat'
export function formatNumber(price: number, currency: string) {
@ -12,3 +14,15 @@ export async function fetcher(url: string) {
if (!res.ok) throw new Error('Failed to fetch')
return await res.json()
}
export function getTokenBySymbol(symbol: string): Token | undefined {
const token = tokens.find((t) => t.symbol === symbol)
return token
}
export function getTokenAddressBySymbol(
symbol: string
): TokenAddress | undefined {
const token = getTokenBySymbol(symbol)
return token?.address
}