mirror of
https://github.com/kremalicious/asi-calculator.git
synced 2024-12-22 09:23:16 +01:00
more data
This commit is contained in:
parent
b2f3c3a5ec
commit
bc75e64f82
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
|||||||
|
ONEINCH_API_KEY=""
|
41
app/api/quote/route.ts
Normal file
41
app/api/quote/route.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { type NextRequest } from 'next/server'
|
||||||
|
|
||||||
|
export const runtime = 'edge'
|
||||||
|
|
||||||
|
const apiUrl = 'https://api.1inch.dev/swap/v6.0/1/quote'
|
||||||
|
|
||||||
|
const config: RequestInit = {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.ONEINCH_API_KEY}`,
|
||||||
|
accept: 'application/json',
|
||||||
|
'content-type': 'application/json'
|
||||||
|
},
|
||||||
|
method: 'GET',
|
||||||
|
next: { revalidate: 60 }
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
const searchParams = request?.nextUrl?.searchParams
|
||||||
|
const src = searchParams?.get('src')
|
||||||
|
const dst = searchParams?.get('dst')
|
||||||
|
const amount = searchParams?.get('amount')
|
||||||
|
|
||||||
|
if (!src || !dst || !amount) {
|
||||||
|
return Response.json(null, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
let data
|
||||||
|
const url = `${apiUrl}/?src=${src}&dst=${dst}&amount=${amount}&includeTokensInfo=true&includeProtocols=true`
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(url, config)
|
||||||
|
const json = await res.json()
|
||||||
|
|
||||||
|
data = json
|
||||||
|
} catch (error: unknown) {
|
||||||
|
console.error((error as Error).message)
|
||||||
|
data = null
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.json(data)
|
||||||
|
}
|
@ -36,6 +36,7 @@ body {
|
|||||||
)
|
)
|
||||||
rgb(var(--background-start-rgb));
|
rgb(var(--background-start-rgb));
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.main {
|
.main,
|
||||||
|
.footer {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
min-height: 100vh;
|
|
||||||
max-width: var(--max-width);
|
max-width: var(--max-width);
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
@ -8,3 +8,8 @@
|
|||||||
.title {
|
.title {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 2rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
11
app/page.tsx
11
app/page.tsx
@ -3,9 +3,12 @@ import styles from './page.module.css'
|
|||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<main className={styles.main}>
|
<>
|
||||||
<h1 className={styles.title}>Should I Buy OCEAN or AGIX or FET?</h1>
|
<main className={styles.main}>
|
||||||
<Prices />
|
<h1 className={styles.title}>Should I Buy OCEAN or AGIX or FET?</h1>
|
||||||
</main>
|
<Prices />
|
||||||
|
</main>
|
||||||
|
<footer className={styles.footer}>Send ❤️ to krema.eth</footer>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
11
constants.ts
Normal file
11
constants.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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 exampleBuyInUsd = 100
|
@ -1,63 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import useSWR from 'swr'
|
|
||||||
import styles from './Prices.module.css'
|
|
||||||
import { Result } from './Result'
|
|
||||||
|
|
||||||
const fetcher = (url: string) => fetch(url).then((res) => res.json())
|
|
||||||
const ratioOceanToAsi = 0.433226
|
|
||||||
const ratioAgixToAsi = 0.43335
|
|
||||||
const tokens: `0x${string}`[] = [
|
|
||||||
'0x967da4048cd07ab37855c090aaf366e4ce1b9f48', // OCEAN
|
|
||||||
'0xaea46a60368a7bd060eec7df8cba43b7ef41ad85', // FET
|
|
||||||
'0x5b7533812759b45c2b44c19e320ba2cd2681b542' // AGIX
|
|
||||||
]
|
|
||||||
const exampleBuyInUsd = 100
|
|
||||||
|
|
||||||
export function Prices() {
|
|
||||||
const { data, error, isLoading } = useSWR(
|
|
||||||
`https://web3.kremalicious.com/api/prices/?tokens=${tokens.toString()}`,
|
|
||||||
fetcher
|
|
||||||
)
|
|
||||||
|
|
||||||
const priceOcean = data?.[tokens[0]]?.usd.toFixed(2) || 0
|
|
||||||
const priceFet = data?.[tokens[1]]?.usd.toFixed(2) || 0
|
|
||||||
const priceAgix = data?.[tokens[2]]?.usd.toFixed(2) || 0
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>
|
|
||||||
1 OCEAN = ${priceOcean} = {ratioOceanToAsi} ASI
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
1 AGIX = ${priceAgix} = {ratioAgixToAsi} ASI
|
|
||||||
</p>
|
|
||||||
<p>1 Fet = ${priceFet} = 1 ASI</p>
|
|
||||||
|
|
||||||
<div className={styles.results}>
|
|
||||||
<h3>If you buy with ${exampleBuyInUsd} right now:</h3>
|
|
||||||
<Result
|
|
||||||
symbol="OCEAN"
|
|
||||||
price={priceOcean}
|
|
||||||
priceAsi={priceFet}
|
|
||||||
ratio={ratioOceanToAsi}
|
|
||||||
exampleBuyInUsd={exampleBuyInUsd}
|
|
||||||
/>
|
|
||||||
<Result
|
|
||||||
symbol="AGIX"
|
|
||||||
price={priceAgix}
|
|
||||||
priceAsi={priceFet}
|
|
||||||
ratio={ratioAgixToAsi}
|
|
||||||
exampleBuyInUsd={exampleBuyInUsd}
|
|
||||||
/>
|
|
||||||
<Result
|
|
||||||
symbol="FET"
|
|
||||||
price={priceFet}
|
|
||||||
priceAsi={priceFet}
|
|
||||||
ratio={1}
|
|
||||||
exampleBuyInUsd={exampleBuyInUsd}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
type Props = {
|
|
||||||
symbol: string
|
|
||||||
price: number
|
|
||||||
priceAsi: number
|
|
||||||
ratio: number
|
|
||||||
exampleBuyInUsd: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Result({
|
|
||||||
symbol,
|
|
||||||
price,
|
|
||||||
priceAsi,
|
|
||||||
ratio,
|
|
||||||
exampleBuyInUsd
|
|
||||||
}: Props) {
|
|
||||||
return (
|
|
||||||
<p>
|
|
||||||
<span>{symbol}</span> You will get {exampleBuyInUsd / price} {symbol},
|
|
||||||
convertible to <strong>{(exampleBuyInUsd / price) * ratio} ASI</strong>{' '}
|
|
||||||
currently worth{' '}
|
|
||||||
<strong>
|
|
||||||
${((exampleBuyInUsd / price) * ratio * priceAsi).toFixed(2)}
|
|
||||||
</strong>
|
|
||||||
.
|
|
||||||
</p>
|
|
||||||
)
|
|
||||||
}
|
|
@ -13,6 +13,6 @@
|
|||||||
|
|
||||||
.results p span {
|
.results p span {
|
||||||
margin-left: -100px;
|
margin-left: -100px;
|
||||||
min-width: 100px;
|
min-width: 90px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
130
features/Prices/components/Prices.tsx
Normal file
130
features/Prices/components/Prices.tsx
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import useSWR from 'swr'
|
||||||
|
import styles from './Prices.module.css'
|
||||||
|
import { Result } from './Result'
|
||||||
|
import {
|
||||||
|
tokens,
|
||||||
|
ratioOceanToAsi,
|
||||||
|
ratioAgixToAsi,
|
||||||
|
exampleBuyInUsd,
|
||||||
|
ratioFetToAsi
|
||||||
|
} from '@/constants'
|
||||||
|
|
||||||
|
const fetcher = async (url: string) => {
|
||||||
|
const res = await fetch(url)
|
||||||
|
if (!res.ok) throw new Error('Failed to fetch')
|
||||||
|
return await res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Prices() {
|
||||||
|
const { data: dataPrices } = useSWR(
|
||||||
|
`https://web3.kremalicious.com/api/prices/?tokens=${tokens.toString()}`,
|
||||||
|
fetcher
|
||||||
|
)
|
||||||
|
const { data: dataSwapOceanToAgix } = useSWR(
|
||||||
|
`/api/quote/?src=${tokens[0]}&dst=${tokens[2]}&amount=${
|
||||||
|
exampleBuyInUsd * 1e18
|
||||||
|
}`,
|
||||||
|
fetcher
|
||||||
|
)
|
||||||
|
|
||||||
|
const { data: dataSwapOceanToFet } = useSWR(
|
||||||
|
`/api/quote/?src=${tokens[0]}&dst=${tokens[1]}&amount=${
|
||||||
|
exampleBuyInUsd * 1e18
|
||||||
|
}`,
|
||||||
|
fetcher
|
||||||
|
)
|
||||||
|
|
||||||
|
const priceOcean = dataPrices?.[tokens[0]]?.usd || 0
|
||||||
|
const priceFet = dataPrices?.[tokens[1]]?.usd || 0
|
||||||
|
const priceAgix = dataPrices?.[tokens[2]]?.usd || 0
|
||||||
|
const priceAsi = priceFet
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
1 OCEAN = {ratioOceanToAsi} ASI (fixed) = ${priceOcean}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
1 AGIX = {ratioAgixToAsi} ASI (fixed) = ${priceAgix}
|
||||||
|
</p>
|
||||||
|
<p>1 Fet = 1 ASI (fixed) = ${priceAsi}</p>
|
||||||
|
|
||||||
|
<div className={styles.results}>
|
||||||
|
<h3>Buying with ${exampleBuyInUsd} right now gets you:</h3>
|
||||||
|
<Result
|
||||||
|
symbol="OCEAN"
|
||||||
|
amount={exampleBuyInUsd / priceOcean}
|
||||||
|
amountAsi={(exampleBuyInUsd / priceOcean) * ratioOceanToAsi}
|
||||||
|
amountFiat={
|
||||||
|
(exampleBuyInUsd / priceOcean) * ratioOceanToAsi * priceAsi
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Result
|
||||||
|
symbol="AGIX"
|
||||||
|
amount={exampleBuyInUsd / priceAgix}
|
||||||
|
amountAsi={(exampleBuyInUsd / priceAgix) * ratioAgixToAsi}
|
||||||
|
amountFiat={(exampleBuyInUsd / priceAgix) * ratioAgixToAsi * priceAsi}
|
||||||
|
/>
|
||||||
|
<Result
|
||||||
|
symbol="FET"
|
||||||
|
amount={exampleBuyInUsd / priceFet}
|
||||||
|
amountAsi={(exampleBuyInUsd / priceFet) * ratioFetToAsi}
|
||||||
|
amountFiat={(exampleBuyInUsd / priceFet) * ratioFetToAsi * priceAsi}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.results}>
|
||||||
|
<h3>
|
||||||
|
Swapping 100 OCEAN (${(100 * priceOcean).toFixed(2)}) right now gets
|
||||||
|
you:
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<Result
|
||||||
|
symbol="OCEAN"
|
||||||
|
amount={100}
|
||||||
|
amountAsi={100 * ratioOceanToAsi}
|
||||||
|
amountFiat={100 * ratioOceanToAsi * priceAsi}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Result
|
||||||
|
symbol="AGIX"
|
||||||
|
amount={
|
||||||
|
dataSwapOceanToAgix?.dstAmount /
|
||||||
|
Number(`1e${dataSwapOceanToAgix?.dstToken?.decimals}`) || 0
|
||||||
|
}
|
||||||
|
amountAsi={
|
||||||
|
(dataSwapOceanToAgix?.dstAmount /
|
||||||
|
Number(`1e${dataSwapOceanToAgix?.dstToken?.decimals}`) || 0) *
|
||||||
|
ratioAgixToAsi
|
||||||
|
}
|
||||||
|
amountFiat={
|
||||||
|
(dataSwapOceanToAgix?.dstAmount /
|
||||||
|
Number(`1e${dataSwapOceanToAgix?.dstToken?.decimals}`) || 0) *
|
||||||
|
ratioAgixToAsi *
|
||||||
|
priceAsi
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Result
|
||||||
|
symbol="FET"
|
||||||
|
amount={
|
||||||
|
dataSwapOceanToFet?.dstAmount /
|
||||||
|
Number(`1e${dataSwapOceanToFet?.dstToken?.decimals}`) || 0
|
||||||
|
}
|
||||||
|
amountAsi={
|
||||||
|
(dataSwapOceanToFet?.dstAmount /
|
||||||
|
Number(`1e${dataSwapOceanToFet?.dstToken?.decimals}`) || 0) *
|
||||||
|
ratioFetToAsi
|
||||||
|
}
|
||||||
|
amountFiat={
|
||||||
|
(dataSwapOceanToFet?.dstAmount /
|
||||||
|
Number(`1e${dataSwapOceanToFet?.dstToken?.decimals}`) || 0) *
|
||||||
|
priceAsi
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
16
features/Prices/components/Result.tsx
Normal file
16
features/Prices/components/Result.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
type Props = {
|
||||||
|
symbol: string
|
||||||
|
amount: number
|
||||||
|
amountAsi: number
|
||||||
|
amountFiat: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Result({ symbol, amount, amountAsi, amountFiat }: Props) {
|
||||||
|
return (
|
||||||
|
<p>
|
||||||
|
<span>{symbol}</span> {amount} {symbol}, convertible to{' '}
|
||||||
|
<strong>{amountAsi} ASI</strong> currently worth{' '}
|
||||||
|
<strong>${amountFiat.toFixed(2)}</strong>.
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
export * from './Prices'
|
export * from './components/Prices'
|
||||||
|
Loading…
Reference in New Issue
Block a user