mirror of
https://github.com/kremalicious/asi-calculator.git
synced 2024-12-22 09:23:16 +01:00
refactor
This commit is contained in:
parent
1ffaab23f5
commit
6123e5d182
@ -3,7 +3,7 @@
|
|||||||
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
|
import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants'
|
||||||
import styles from './CalculationBase.module.css'
|
import styles from './CalculationBase.module.css'
|
||||||
import { usePrices } from '@/hooks'
|
import { usePrices } from '@/hooks'
|
||||||
import { Label } from '../Label'
|
import { Label } from '@/components/Label'
|
||||||
|
|
||||||
export function CalculationBase() {
|
export function CalculationBase() {
|
||||||
const { prices, isValidating } = usePrices()
|
const { prices, isValidating } = usePrices()
|
||||||
|
@ -2,7 +2,7 @@ import { InputAmount } from '@/components/FormAmount/Inputs/InputAmount'
|
|||||||
import { InputToken } from './Inputs/InputToken'
|
import { InputToken } from './Inputs/InputToken'
|
||||||
import styles from './FormAmount.module.css'
|
import styles from './FormAmount.module.css'
|
||||||
import { Dispatch, SetStateAction } from 'react'
|
import { Dispatch, SetStateAction } from 'react'
|
||||||
import { Token } from './types'
|
import { TokenSymbol } from '@/types'
|
||||||
|
|
||||||
export function FormAmount({
|
export function FormAmount({
|
||||||
amount,
|
amount,
|
||||||
@ -13,8 +13,8 @@ export function FormAmount({
|
|||||||
}: {
|
}: {
|
||||||
amount: number
|
amount: number
|
||||||
setAmount: Dispatch<SetStateAction<number>>
|
setAmount: Dispatch<SetStateAction<number>>
|
||||||
token: Token | string
|
token: TokenSymbol | string
|
||||||
setToken?: Dispatch<SetStateAction<Token>>
|
setToken?: Dispatch<SetStateAction<TokenSymbol>>
|
||||||
isFiat?: boolean
|
isFiat?: boolean
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
|
@ -1,33 +1,35 @@
|
|||||||
import { Dispatch, SetStateAction } from 'react'
|
import { Dispatch, SetStateAction } from 'react'
|
||||||
import styles from './InputToken.module.css'
|
import styles from './InputToken.module.css'
|
||||||
import { CaretDownIcon } from '@radix-ui/react-icons'
|
import { CaretDownIcon } from '@radix-ui/react-icons'
|
||||||
import { Token } from '../types'
|
import { TokenSymbol } from '@/types'
|
||||||
|
|
||||||
export function InputToken({
|
export function InputToken({
|
||||||
token,
|
token,
|
||||||
setToken,
|
setToken,
|
||||||
isFiat
|
isFiat
|
||||||
}: {
|
}: {
|
||||||
token: Token | string
|
token: TokenSymbol | string
|
||||||
isFiat?: boolean
|
isFiat?: boolean
|
||||||
setToken?: Dispatch<SetStateAction<Token>>
|
setToken?: Dispatch<SetStateAction<TokenSymbol>>
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<span className={styles.selectWrapper}>
|
<span className={styles.selectWrapper}>
|
||||||
<select
|
<select
|
||||||
className={styles.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}
|
value={token}
|
||||||
disabled={!setToken}
|
disabled={!setToken}
|
||||||
style={setToken ? { paddingRight: '1.25rem' } : {}}
|
style={setToken ? { paddingRight: '1.25rem' } : {}}
|
||||||
>
|
>
|
||||||
{isFiat ? (
|
{isFiat ? (
|
||||||
<option value="usd">USD</option>
|
<option value="USD">USD</option>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<option value="ocean">OCEAN</option>
|
<option value="OCEAN">OCEAN</option>
|
||||||
<option value="fet">FET</option>
|
<option value="FET">FET</option>
|
||||||
<option value="agix">AGIX</option>
|
<option value="AGIX">AGIX</option>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './FormAmount'
|
export * from './FormAmount'
|
||||||
export * from './types'
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export type Token = 'ocean' | 'fet' | 'agix' | undefined
|
|
@ -1,58 +1,49 @@
|
|||||||
'use client'
|
import { Result } from '@/components/ResultRow'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ratioOceanToAsi,
|
ratioOceanToAsi,
|
||||||
ratioAgixToAsi,
|
ratioAgixToAsi,
|
||||||
ratioFetToAsi,
|
ratioFetToAsi,
|
||||||
tokens
|
tokens
|
||||||
} from '@/constants'
|
} 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 { 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 { 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 } =
|
const { data: dataSwapOceanToAgix, isValidating: isValidatingOceanToAgix } =
|
||||||
useSWR(
|
useSWR(
|
||||||
`/api/quote/?tokenIn=${tokens[0]}&tokenOut=${tokens[2]}&amountIn=${debouncedAmount}`,
|
`/api/quote/?tokenIn=${tokens[0].address}&tokenOut=${tokens[2].address}&amountIn=${amount}`,
|
||||||
fetcher
|
fetcher
|
||||||
)
|
)
|
||||||
|
|
||||||
const { data: dataSwapOceanToFet, isValidating: isValidatingOceanToFet } =
|
const { data: dataSwapOceanToFet, isValidating: isValidatingOceanToFet } =
|
||||||
useSWR(
|
useSWR(
|
||||||
`/api/quote/?tokenIn=${tokens[0]}&tokenOut=${tokens[1]}&amountIn=${debouncedAmount}`,
|
`/api/quote/?tokenIn=${tokens[0].address}&tokenOut=${tokens[1].address}&amountIn=${amount}`,
|
||||||
fetcher
|
fetcher
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
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
|
<Result
|
||||||
tokenSymbol="OCEAN"
|
tokenSymbol="OCEAN"
|
||||||
tokenAddress="0x967da4048cd07ab37855c090aaf366e4ce1b9f48"
|
tokenAddress="0x967da4048cd07ab37855c090aaf366e4ce1b9f48"
|
||||||
amount={debouncedAmount}
|
amount={amount}
|
||||||
amountAsi={debouncedAmount * ratioOceanToAsi}
|
amountAsi={amount * ratioOceanToAsi}
|
||||||
amountFiat={debouncedAmount * ratioOceanToAsi * prices.asi}
|
amountFiat={amount * ratioOceanToAsi * prices.asi}
|
||||||
amountOriginalFiat={token ? debouncedAmount * prices[token] : undefined}
|
amountOriginalFiat={
|
||||||
|
token
|
||||||
|
? amount *
|
||||||
|
prices[token.toLowerCase() as 'ocean' | 'agix' | 'fet' | 'asi']
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
isValidating={
|
isValidating={
|
||||||
isValidatingOceanToAgix ||
|
isValidatingOceanToAgix ||
|
||||||
isValidatingOceanToFet ||
|
isValidatingOceanToFet ||
|
||||||
@ -105,6 +96,6 @@ export function Swap() {
|
|||||||
}
|
}
|
||||||
isValidating={isValidatingOceanToFet || isValidatingPrices}
|
isValidating={isValidatingOceanToFet || isValidatingPrices}
|
||||||
/>
|
/>
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
31
components/Strategies/Swap/Swap.tsx
Normal file
31
components/Strategies/Swap/Swap.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
@ -1,2 +1,2 @@
|
|||||||
export * from './Buy'
|
export * from './Buy'
|
||||||
export * from './Swap'
|
export * from './Swap/Swap'
|
||||||
|
10
constants.ts
10
constants.ts
@ -1,9 +1,11 @@
|
|||||||
|
import { Token } from '@/types'
|
||||||
|
|
||||||
export const ratioOceanToAsi = 0.433226
|
export const ratioOceanToAsi = 0.433226
|
||||||
export const ratioAgixToAsi = 0.43335
|
export const ratioAgixToAsi = 0.43335
|
||||||
export const ratioFetToAsi = 1
|
export const ratioFetToAsi = 1
|
||||||
|
|
||||||
export const tokens: `0x${string}`[] = [
|
export const tokens: Token[] = [
|
||||||
'0x967da4048cd07ab37855c090aaf366e4ce1b9f48', // OCEAN
|
{ symbol: 'OCEAN', address: '0x967da4048cd07ab37855c090aaf366e4ce1b9f48' },
|
||||||
'0xaea46a60368a7bd060eec7df8cba43b7ef41ad85', // FET
|
{ symbol: 'FET', address: '0xaea46a60368a7bd060eec7df8cba43b7ef41ad85' },
|
||||||
'0x5b7533812759b45c2b44c19e320ba2cd2681b542' // AGIX
|
{ symbol: 'AGIX', address: '0x5b7533812759b45c2b44c19e320ba2cd2681b542' }
|
||||||
]
|
]
|
||||||
|
@ -1,22 +1,33 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { tokens } from '@/constants'
|
import { tokens } from '@/constants'
|
||||||
import { fetcher } from '@/utils'
|
import { fetcher, getTokenAddressBySymbol } from '@/utils'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
|
||||||
|
const tokenAddresses = tokens.map((token) => token.address).toString()
|
||||||
|
|
||||||
export function usePrices(): {
|
export function usePrices(): {
|
||||||
prices: { ocean: number; fet: number; agix: number; asi: number }
|
prices: { ocean: number; fet: number; agix: number; asi: number }
|
||||||
isValidating: boolean
|
isValidating: boolean
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
} {
|
} {
|
||||||
const { data, isValidating, isLoading } = useSWR(
|
const { data, isValidating, isLoading } = useSWR(
|
||||||
`/api/prices/?tokens=${tokens.toString()}`,
|
`/api/prices/?tokens=${tokenAddresses}`,
|
||||||
fetcher
|
fetcher
|
||||||
)
|
)
|
||||||
|
|
||||||
const ocean = data?.[tokens[0]]?.usd || 0
|
const oceanAddress = getTokenAddressBySymbol('OCEAN')
|
||||||
const fet = data?.[tokens[1]]?.usd || 0
|
const fetAddress = getTokenAddressBySymbol('FET')
|
||||||
const agix = data?.[tokens[2]]?.usd || 0
|
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
|
const asi = fet
|
||||||
|
|
||||||
return { prices: { ocean, fet, agix, asi }, isValidating, isLoading }
|
return { prices: { ocean, fet, agix, asi }, isValidating, isLoading }
|
||||||
|
7
types/Token.ts
Normal file
7
types/Token.ts
Normal 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
1
types/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './Token'
|
@ -1,3 +1,5 @@
|
|||||||
|
import { tokens } from '@/constants'
|
||||||
|
import type { TokenAddress, Token } from '@/types'
|
||||||
import { formatCurrency } from '@coingecko/cryptoformat'
|
import { formatCurrency } from '@coingecko/cryptoformat'
|
||||||
|
|
||||||
export function formatNumber(price: number, currency: string) {
|
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')
|
if (!res.ok) throw new Error('Failed to fetch')
|
||||||
return await res.json()
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user