more data

This commit is contained in:
Matthias Kretschmann 2024-03-29 18:54:14 +00:00
parent b2f3c3a5ec
commit bc75e64f82
Signed by: m
GPG Key ID: 606EEEF3C479A91F
12 changed files with 216 additions and 98 deletions

1
.env.example Normal file
View File

@ -0,0 +1 @@
ONEINCH_API_KEY=""

41
app/api/quote/route.ts Normal file
View 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)
}

View File

@ -36,6 +36,7 @@ body {
)
rgb(var(--background-start-rgb));
line-height: 1.5;
min-height: 100vh;
}
a {

View File

@ -1,6 +1,6 @@
.main {
.main,
.footer {
padding: 2rem;
min-height: 100vh;
max-width: var(--max-width);
margin: auto;
}
@ -8,3 +8,8 @@
.title {
margin-bottom: 2rem;
}
.footer {
margin-top: 2rem;
font-size: 0.8rem;
}

View File

@ -3,9 +3,12 @@ import styles from './page.module.css'
export default function Home() {
return (
<main className={styles.main}>
<h1 className={styles.title}>Should I Buy OCEAN or AGIX or FET?</h1>
<Prices />
</main>
<>
<main className={styles.main}>
<h1 className={styles.title}>Should I Buy OCEAN or AGIX or FET?</h1>
<Prices />
</main>
<footer className={styles.footer}>Send to krema.eth</footer>
</>
)
}

11
constants.ts Normal file
View 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

View File

@ -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>
</>
)
}

View File

@ -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>
)
}

View File

@ -13,6 +13,6 @@
.results p span {
margin-left: -100px;
min-width: 100px;
min-width: 90px;
display: inline-block;
}

View 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>
</>
)
}

View 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>
)
}

View File

@ -1 +1 @@
export * from './Prices'
export * from './components/Prices'