-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
356 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"stackspulse": patch | ||
--- | ||
|
||
Add "Data" section in about page. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@stackspulse/server": minor | ||
--- | ||
|
||
Create new `/api/tokens/resolve` route. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@stackspulse/server": minor | ||
--- | ||
|
||
Create new `/api/tokens/markets` route. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"stackspulse": minor | ||
--- | ||
|
||
Create new token list page. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { env } from "~/env"; | ||
import { apiCacheConfig } from "~/lib/api"; | ||
|
||
type CoingeckoCoinsMarketsResponse = { | ||
id: string; | ||
symbol: string; | ||
name: string; | ||
image: string; | ||
current_price: number; | ||
market_cap: number; | ||
price_change_percentage_24h: number; | ||
}[]; | ||
|
||
type TokensMarketsRouteResponse = CoingeckoCoinsMarketsResponse; | ||
|
||
export default defineCachedEventHandler( | ||
async () => { | ||
const url = | ||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&category=stacks-ecosystem"; | ||
|
||
const data: CoingeckoCoinsMarketsResponse[] = await fetch(url, { | ||
method: "GET", | ||
headers: { | ||
accept: "application/json", | ||
"x-cg-demo-api-key": env.COINGECKO_API_KEY, | ||
}, | ||
}).then((res) => res.json()); | ||
|
||
return data; | ||
}, | ||
{ | ||
...apiCacheConfig, | ||
// Cache for 24 hours | ||
maxAge: 60 * 60 * 24, | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { z } from "zod"; | ||
import { env } from "~/env"; | ||
import { apiCacheConfig } from "~/lib/api"; | ||
import { getValidatedQueryZod } from "~/lib/nitro"; | ||
|
||
type CoingeckoCoinsIdResponse = { | ||
id: string; | ||
symbol: string; | ||
name: string; | ||
contract_address: string; | ||
}; | ||
|
||
type TokensResolveRouteResponse = CoingeckoCoinsIdResponse; | ||
|
||
const tokensResolveRouteSchema = z.object({ | ||
id: z.string(), | ||
}); | ||
|
||
/** | ||
* Resolves a coingecko token id to a deployed token contract address | ||
*/ | ||
export default defineCachedEventHandler( | ||
async (event) => { | ||
const query = await getValidatedQueryZod(event, tokensResolveRouteSchema); | ||
|
||
const url = `https://api.coingecko.com/api/v3/coins/${query.id}`; | ||
|
||
const data: CoingeckoCoinsIdResponse = await fetch(url, { | ||
method: "GET", | ||
headers: { | ||
accept: "application/json", | ||
"x-cg-demo-api-key": env.COINGECKO_API_KEY, | ||
}, | ||
}).then((res) => res.json()); | ||
|
||
return { | ||
id: data.id, | ||
symbol: data.symbol, | ||
name: data.name, | ||
contract_address: data.contract_address, | ||
}; | ||
}, | ||
{ | ||
...apiCacheConfig, | ||
// Cache for 3 days | ||
maxAge: 60 * 60 * 24 * 3, | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { env } from "@/env"; | ||
import type { TokensMarketsRouteResponse } from "@/lib/api"; | ||
import { Container, Link, Table, Text } from "@radix-ui/themes"; | ||
import type { Metadata } from "next"; | ||
import Image from "next/image"; | ||
import NextLink from "next/link"; | ||
|
||
export const dynamic = "force-dynamic"; | ||
|
||
export async function generateMetadata(): Promise<Metadata> { | ||
return { | ||
title: "stackspulse - tokens", | ||
description: "Explore Stacks tokens by market cap, volume, and price", | ||
alternates: { | ||
canonical: "/tokens", | ||
}, | ||
}; | ||
} | ||
|
||
export default async function ProtocolPage() { | ||
const data: TokensMarketsRouteResponse = await fetch( | ||
`${env.NEXT_PUBLIC_API_URL}/api/tokens/markets`, | ||
).then((res) => res.json()); | ||
|
||
return ( | ||
<Container size="2" className="px-4 pt-5"> | ||
<Table.Root> | ||
<Table.Header> | ||
<Table.Row> | ||
<Table.ColumnHeaderCell>Token</Table.ColumnHeaderCell> | ||
<Table.ColumnHeaderCell align="right">Price</Table.ColumnHeaderCell> | ||
<Table.ColumnHeaderCell align="right">24h</Table.ColumnHeaderCell> | ||
<Table.ColumnHeaderCell align="right"> | ||
Market Cap | ||
</Table.ColumnHeaderCell> | ||
</Table.Row> | ||
</Table.Header> | ||
|
||
<Table.Body> | ||
{data.map((market) => ( | ||
<Table.Row key={market.id}> | ||
<Table.Cell className="flex gap-2"> | ||
<Image | ||
className="rounded-full" | ||
src={market.image} | ||
alt={market.name} | ||
width={20} | ||
height={20} | ||
/> | ||
{market.id === "blockstack" ? ( | ||
<Text size="2">{market.name}</Text> | ||
) : ( | ||
<Link color="gray" highContrast size="2" asChild> | ||
<NextLink href={`/tokens/resolve/${market.id}`}> | ||
{market.name} | ||
</NextLink> | ||
</Link> | ||
)} | ||
</Table.Cell> | ||
<Table.Cell align="right"> | ||
$ | ||
{market.current_price.toLocaleString("en-US", { | ||
maximumFractionDigits: 12, | ||
})} | ||
</Table.Cell> | ||
<Table.Cell align="right"> | ||
<Text | ||
size="2" | ||
color={ | ||
market.price_change_percentage_24h >= 0 ? "green" : "red" | ||
} | ||
> | ||
{market.price_change_percentage_24h | ||
? `${market.price_change_percentage_24h.toLocaleString( | ||
"en-US", | ||
{ | ||
maximumFractionDigits: 2, | ||
}, | ||
)}%` | ||
: ""} | ||
</Text> | ||
</Table.Cell> | ||
<Table.Cell align="right"> | ||
${market.market_cap.toLocaleString("en-US")} | ||
</Table.Cell> | ||
</Table.Row> | ||
))} | ||
</Table.Body> | ||
</Table.Root> | ||
|
||
<div className="mt-5 flex justify-end"> | ||
<Text size="1" color="gray"> | ||
Data provided by{" "} | ||
<Link href="https://coingecko.com/" target="_blank"> | ||
CoinGecko | ||
</Link> | ||
. | ||
</Text> | ||
</div> | ||
</Container> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { env } from "@/env"; | ||
import type { TokensResolveRouteResponse } from "@/lib/api"; | ||
import { notFound, redirect } from "next/navigation"; | ||
|
||
export const dynamic = "force-dynamic"; | ||
|
||
interface PageProps { | ||
params: { token: string }; | ||
} | ||
|
||
export default async function ProtocolPage({ params }: PageProps) { | ||
const data: TokensResolveRouteResponse = await fetch( | ||
`${env.NEXT_PUBLIC_API_URL}/api/tokens/resolve?id=${params.token}`, | ||
).then((res) => res.json()); | ||
|
||
if (data.contract_address) { | ||
redirect(`/tokens/${data.contract_address}`); | ||
} | ||
|
||
notFound(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.