Skip to content

Commit

Permalink
feat: whale tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
emidev98 committed Feb 16, 2024
1 parent 239eb63 commit 887efda
Show file tree
Hide file tree
Showing 15 changed files with 295 additions and 201 deletions.
106 changes: 70 additions & 36 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,88 @@ import Card from "../components/Card";
import Kpi from "../components/Kpi";
import Table from "../components/Table";
import { DEFAULT_CHAIN, SUPPORTED_CHAINS } from "../const/chains";
import { QueryAlliances } from "../lib/AllianceQuery";
import { AllianceAsset } from "@terra-money/feather.js/dist/client/lcd/api/AllianceAPI";
import { QueryAlliances } from "../lib/QueryAlliances";
import Link from "next/link";
import { useSearchParams, useRouter } from "next/navigation";
import { Suspense, useEffect, useState } from "react";
import { mergePrices, Prices, TerraPriceServerResponse } from "../models/Prices";
import { Prices, QueryAndMergePrices } from "../models/Prices";
import { Kpis } from "../const/kpis";
import { LCD } from "../models/LCDConfig";
import TableState from "../models/TableState";
import { GetInflationEndpoint, ParseInflation } from "../lib/QueryInflation";
import { QueryLP } from "../lib/QueryLP";
import { Chain } from "../models/Chain";

export default function Home() {
const [prices, setPrices] = useState<Prices>({});
const [data, setData] = useState<AllianceAsset[] | undefined>(undefined);
const params = useSearchParams();
let selectedChain = SUPPORTED_CHAINS[params.get("selected") ?? DEFAULT_CHAIN];
const router = useRouter();

if (selectedChain === undefined) {
selectedChain = SUPPORTED_CHAINS[DEFAULT_CHAIN];
router.push(`?selected=${SUPPORTED_CHAINS[DEFAULT_CHAIN].id}`)
}
const [tableState, setTableState] = useState<TableState | null>(null);
const [selectedChain, setSelectedChain] = useState<Chain | undefined>(undefined);
const [prices, setPrices] = useState<Prices>({});
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
setData(undefined);
(async () => {
// If prices are not loaded, load them from the API(s)
// Otherwise, use the cached prices
if (Object.keys(prices).length === 0) {
const res = await Promise.all([
fetch("https://price.api.tfm.com/tokens/?limit=1500"),
fetch("https://pisco-price-server.terra.dev/latest")
]);
const [tfmPrices, terraOraclePrices]: [Prices, TerraPriceServerResponse] = await Promise.all([res[0].json(), res[1].json()]);
let prices = mergePrices(tfmPrices, terraOraclePrices);
const selectedParamIsSupported = SUPPORTED_CHAINS[params.get("selected") as any];
if (selectedParamIsSupported) {
setSelectedChain(SUPPORTED_CHAINS[params.get("selected") as string]);
} else {
setSelectedChain(SUPPORTED_CHAINS[DEFAULT_CHAIN])
router.push(`?selected=${SUPPORTED_CHAINS[DEFAULT_CHAIN].id}`);
}
}, [params])

useEffect(() => {
if (selectedChain) {
setIsLoading(true);
(async () => {
// Load the prices only the first time a user lands on
// the page, then use the prices from the state.
//
// NOTE: the variable is not being shadowed because otherwise
// the first load will result on 0 prices.
const _prices = Object.keys(prices).length === 0 ? await QueryAndMergePrices() : prices;
setPrices(_prices);

// Query selectedChain alliances info
const _allianceAssetRes = await QueryAlliances(selectedChain).catch(() => []);

setPrices(prices);
}
// Query chain info on parallel to speed up the loading time
let chainInfoRes = await Promise.all([
LCD.alliance.params(selectedChain.id),
LCD.bank.supplyByDenom(selectedChain.id, selectedChain.bondDenom),
GetInflationEndpoint(selectedChain.id),
]).catch((e) => {
console.error(e)
return []
});

const res = await QueryAlliances(selectedChain).catch(() => []);
// Query this info in parallel to speed up the loading time
// because the requested data is independent from each other
const [inflation, allianceCoins] = await Promise.all([
ParseInflation(selectedChain.id, chainInfoRes[2]),
QueryLP(selectedChain.allianceCoins)
])

setData(res);
})();
}, [params]);
selectedChain.allianceCoins = allianceCoins;

// If no error occured, set the data
// otherwise, keep the default data
if (chainInfoRes != undefined) {
let tableState = new TableState(
selectedChain,
_allianceAssetRes,
_prices,
chainInfoRes[0].params,
chainInfoRes[1],
inflation,
);
setTableState(tableState)
}
setIsLoading(false);
})();
}
}, [selectedChain]);

return (
<section className="w-full flex-col">
Expand All @@ -72,7 +113,7 @@ export default function Home() {
{" "}Alliance assets on Terra
</h3>
</div>
<div className="flex flex-col pt-3 pb-3 mt-12 overflow-auto">
<div className="flex flex-col pt-3 mt-12 overflow-auto">
<div className="flex gap-3">
{Kpis.map((kpi) => <Kpi key={kpi.id} kpi={kpi} data={prices[kpi.token]} />)}
</div>
Expand All @@ -81,17 +122,10 @@ export default function Home() {
<div className="w-full lg:w-6/6">
<Card name="Assets">
<Suspense fallback={<CSSLoader />}>
<Table prices={prices} allianceAssets={data} selectedChain={selectedChain} />
<Table tableState={tableState} isLoading={isLoading} />
</Suspense>
</Card>
</div>
{/* <div className="w-full lg:w-2/6">
<Card name="Overview" className="flex flex-col items-center overflow-auto">
<Suspense fallback={<CSSLoader />}>
<Graph values={data} />
</Suspense>
</Card>
</div> */}
</div>
</section>
);
Expand Down
13 changes: 11 additions & 2 deletions components/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
"use client";

import { useState } from "react";
import { useEffect, useState } from "react";
import styles from "../styles/Dropdown.module.css";
import { useRouter, useSearchParams } from "next/navigation";
import { DEFAULT_CHAIN, SUPPORTED_CHAINS } from "../const/chains";

export default function Dropdown() {
const params = useSearchParams();
const [show, setShow] = useState<boolean>(false);
const [selected, setSelected] = useState<any>(SUPPORTED_CHAINS[params.get("selected") ?? DEFAULT_CHAIN]);
const [selected, setSelected] = useState<any>();
const router = useRouter();

useEffect(() => {
if (SUPPORTED_CHAINS[params.get("selected") as any]) {
setSelected(SUPPORTED_CHAINS[params.get("selected") as string]);
}
else {
setSelected(SUPPORTED_CHAINS[DEFAULT_CHAIN]);
}
}, [])

return (
<div
className={styles.select}
Expand Down
56 changes: 11 additions & 45 deletions components/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,18 @@
"use client";
import { useEffect, useState } from "react";
import { Tooltip } from "@nextui-org/react";
import { getAdditionalYield, getTakeRate, toLocaleString } from "../models/AllianceFunctions";
import LoadingComponent from "./LoadingComponent";
import { AllianceAsset } from "@terra-money/feather.js/dist/client/lcd/api/AllianceAPI";
import { LCD } from "../models/LCDConfig";
import { TableIcon } from "../components/TableIcon";
import TableState from "../models/TableState";
import { Prices } from "../models/Prices";
import { Chain } from "../models/Chain";
import TableState, {toLocalString} from "../models/TableState";
import { headers } from "../const/table";

interface TableProps {
allianceAssets: AllianceAsset[] | undefined;
prices: Prices
selectedChain: Chain;
tableState: TableState | null;
isLoading: boolean;
}

export default function Table({ selectedChain, allianceAssets, prices }: TableProps) {
const [tableState, setTableState] = useState<TableState>(TableState.default(selectedChain));

useEffect(() => {
(async () => {
// Query the data on paralel to speed up the loading time
const res = await Promise.all([
LCD.alliance.params(selectedChain.id),
LCD.bank.supplyByDenom(selectedChain.id, selectedChain.bondDenom),
LCD.mint.inflation(selectedChain.id),
]).catch((e) => { console.error(e) });

// If no error occured, set the data
// otherwise, keep the default data
if (res != undefined) {
let tableState = new TableState(
selectedChain,
allianceAssets,
prices,
res[0].params,
res[1],
res[2],
);
setTableState(tableState)
}
})();
}, [allianceAssets, selectedChain]);

export default function Table({ tableState, isLoading}: TableProps) {
return (
<LoadingComponent isLoading={tableState.allianceAssets === undefined} values={tableState.allianceAssets}>
<LoadingComponent isLoading={isLoading} values={tableState?.allianceAssets}>
<table className="w-full h-full border-collapse mb-3">
<thead>
<tr className="table_row">
Expand All @@ -56,7 +22,7 @@ export default function Table({ selectedChain, allianceAssets, prices }: TablePr
<div className="justify-start lg:justify-center flex items-center gap-1">
{v.title}
{v.tooltip ? (
<Tooltip content={v.tooltip(tableState.selectedChain.id)}>
<Tooltip content={v.tooltip(tableState?.selectedChain.id)}>
<img src="/images/info.svg" alt="Info" width={20} height={20} />
</Tooltip>
) : null}
Expand All @@ -70,11 +36,11 @@ export default function Table({ selectedChain, allianceAssets, prices }: TablePr
<tr key={row.denom}>
<td className="flex justify-start lg:justify-center pt-4"><TableIcon row={row} chain={tableState.selectedChain} /></td>
<td className="text-center lg:text-center pt-4">{tableState.getAllianceAssetName(row.denom)}</td>
<td className="text-center lg:text-center pt-4">{toLocaleString(tableState.getTotalTokens(row.denom))}</td>
<td className="text-center lg:text-center pt-4">${toLocaleString(tableState.getTotalValueStaked(row.denom))}</td>
<td className="text-center lg:text-center pt-4">{toLocaleString(tableState.getTakeRate(row.denom))}%</td>
<td className="text-center lg:text-center pt-4">{toLocaleString(parseFloat(row.reward_weight) * 100)}%</td>
<td className="text-center lg:text-center pt-4">{toLocaleString(tableState.getAdditionalYield(row.denom))}%</td>
<td className="text-center lg:text-center pt-4">{toLocalString(tableState.getTotalTokens(row.denom))}</td>
<td className="text-center lg:text-center pt-4">${toLocalString(tableState.getTotalValueStaked(row.denom))}</td>
<td className="text-center lg:text-center pt-4">{toLocalString(tableState.getTakeRate(row.denom))}%</td>
<td className="text-center lg:text-center pt-4">{toLocalString(parseFloat(row.reward_weight) * 100)}%</td>
<td className="text-center lg:text-center pt-4">{toLocalString(tableState.getAdditionalYield(row.denom))}%</td>
</tr>
))}
</tbody>
Expand Down
44 changes: 29 additions & 15 deletions const/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@ export const SUPPORTED_CHAINS: { [key: string]: Chain } = {
name: "ampLuna",
priceKey: "terra1ecgazyd0waaj3g7l9cmy5gulhxkps2gmxu9ghducvuypjq68mq2s5lvsct",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/ampLuna.svg",
color: "#324ab2",
},
"ibc/FBEE20115530F474F8BBE1460DA85437C3FBBFAF4A5DEBD71CA6B9C40559A161": {
name: "stLuna",
priceKey: "ibc/08095CEDEA29977C9DD0CE9A48329FDA622C183359D5F90CF04CC4FF80CBE431",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/stLUNA.svg",
color: "#fb0174",
},
},
}),
Expand All @@ -41,34 +39,45 @@ export const SUPPORTED_CHAINS: { [key: string]: Chain } = {
name: "ampLuna",
priceKey: "terra1ecgazyd0waaj3g7l9cmy5gulhxkps2gmxu9ghducvuypjq68mq2s5lvsct",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/ampLuna.svg",
color: "#324ab2",
},
"ibc/40C29143BF4153B365089E40E437B7AA819672646C45BB0A5F1E10915A0B6708": {
name: "bLuna",
priceKey: "terra17aj4ty4sz4yhgm08na8drc0v03v2jwr3waxcqrwhajj729zhl7zqnpc0ml",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/bLuna.png",
color: "#ff7500",
},
"factory/migaloo1axtz4y7jyvdkkrflknv9dcut94xr5k8m6wete4rdrw4fuptk896su44x2z/uLP": {
name: "WHALE/wBTC",
lpInfo: {
contractAddr: "migaloo1axtz4y7jyvdkkrflknv9dcut94xr5k8m6wete4rdrw4fuptk896su44x2z",
tokensPriceKey: ["WHALE", "WBTC"],
tokensDecimals: [6, 8],
},
icon: [
"https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/Whale.svg",
"https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/wbtc.svg",
],
},
"factory/migaloo1xv4ql6t6r8zawlqn2tyxqsrvjpmjfm6kvdfvytaueqe3qvcwyr7shtx0hj/uLP": {
name: "USDC-WHALE-LP",
priceKey: "factory/migaloo1xv4ql6t6r8zawlqn2tyxqsrvjpmjfm6kvdfvytaueqe3qvcwyr7shtx0hj/uLP",
name: "WHALE/USDC",
lpInfo: {
contractAddr: "migaloo1xv4ql6t6r8zawlqn2tyxqsrvjpmjfm6kvdfvytaueqe3qvcwyr7shtx0hj",
tokensPriceKey: ["WHALE","USDC"],
tokensDecimals: [6, 6]
},
icon: [
"https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/USDC.svg",
"https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/Whale.svg",
"https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/USDC.svg",
],
color: "#3b74c5"
},
"factory/migaloo1erul6xyq0gk6ws98ncj7lnq9l4jn4gnnu9we73gdz78yyl2lr7qqrvcgup/ash": {
name: "ASH",
priceKey: "factory/migaloo1erul6xyq0gk6ws98ncj7lnq9l4jn4gnnu9we73gdz78yyl2lr7qqrvcgup/ash",
priceKey: "ASH",
icon: "images/ash.svg",
color: "#3CCD64"
},
"migaloo10nucfm2zqgzqmy7y7ls398t58pjt9cwjsvpy88y2nvamtl34rgmqt5em2v": {
name: "mUSDC",
priceKey: "migaloo10nucfm2zqgzqmy7y7ls398t58pjt9cwjsvpy88y2nvamtl34rgmqt5em2v",
priceKey: "USDC",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/USDC.svg",
color: "#3b74c5"
},
},
}),
Expand All @@ -88,20 +97,25 @@ export const SUPPORTED_CHAINS: { [key: string]: Chain } = {
name: "rSWTH",
priceKey: "rSWTH",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/rSWTH.svg",
color: "#324ab2",
},
"ibc/B3F639855EE7478750CC8F82072307ED6E131A8EFF20345E1D136B50C4E5EC36": {
name: "ampWhale",
priceKey: "ibc/B3F639855EE7478750CC8F82072307ED6E131A8EFF20345E1D136B50C4E5EC36",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/ampWHALE.svg",
color: "#324ab2",
},
"ibc/517E13F14A1245D4DE8CF467ADD4DA0058974CDCC880FA6AE536DBCA1D16D84E": {
name: "bWhale",
priceKey: "ibc/517E13F14A1245D4DE8CF467ADD4DA0058974CDCC880FA6AE536DBCA1D16D84E",
icon: "https://raw.githubusercontent.com/terra-money/station-assets/main/img/coins/bWHALE.png",
color: "#fb0174",
},
},
}),
};


export interface CarbonInflationRes {
numberOfWeeks: string;
inflationRate: string;
last7DaysInflationRate: string;
last14DaysInflationRate: string;
}
2 changes: 1 addition & 1 deletion const/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const headers = [
},
{
title: "Reward Weight",
tooltip: (chainId: string | null) => (
tooltip: (chainId?: string) => (
<>
<p>The proportion of total staking rewards on this chain to be directed to stakers of this asset.</p>
{chainId == "phoenix-1" && (
Expand Down
File renamed without changes.
Loading

0 comments on commit 887efda

Please sign in to comment.