diff --git a/explorer/src/components/account/TokenAccountSection.tsx b/explorer/src/components/account/TokenAccountSection.tsx
index 551851678a..9313c644c1 100644
--- a/explorer/src/components/account/TokenAccountSection.tsx
+++ b/explorer/src/components/account/TokenAccountSection.tsx
@@ -17,6 +17,8 @@ import { reportError } from "utils/sentry";
import { useTokenRegistry } from "providers/mints/token-registry";
import { BigNumber } from "bignumber.js";
import { Copyable } from "components/common/Copyable";
+import { CoingeckoStatus, useCoinGecko } from "utils/coingecko";
+import { displayTimestampWithoutDate } from "utils/date";
const getEthAddress = (link?: string) => {
let address = "";
@@ -76,7 +78,6 @@ function MintAccountCard({
const mintAddress = account.pubkey.toBase58();
const fetchInfo = useFetchAccountInfo();
const refresh = () => fetchInfo(account.pubkey);
-
const tokenInfo = tokenRegistry.get(mintAddress);
const bridgeContractAddress = getEthAddress(
@@ -86,6 +87,13 @@ function MintAccountCard({
tokenInfo?.extensions?.assetContract
);
+ const coinInfo = useCoinGecko(tokenInfo?.extensions?.coingeckoId);
+
+ let tokenPriceInfo;
+ if (coinInfo?.status === CoingeckoStatus.Success) {
+ tokenPriceInfo = coinInfo.coinInfo;
+ }
+
return (
@@ -115,6 +123,17 @@ function MintAccountCard({
)}
+ {tokenPriceInfo?.price && (
+
+ Current Price |
+
+ $
+ {tokenPriceInfo.price.toLocaleString("en-US", {
+ minimumFractionDigits: 2,
+ })}
+ |
+
+ )}
{tokenInfo?.extensions?.website && (
Website |
@@ -189,6 +208,12 @@ function MintAccountCard({
)}
+ {tokenPriceInfo && (
+
+ Price updated at{" "}
+ {displayTimestampWithoutDate(tokenPriceInfo.last_updated.getTime())}
+
+ )}
);
}
diff --git a/explorer/src/pages/ClusterStatsPage.tsx b/explorer/src/pages/ClusterStatsPage.tsx
index c19744cd7e..fb823027b2 100644
--- a/explorer/src/pages/ClusterStatsPage.tsx
+++ b/explorer/src/pages/ClusterStatsPage.tsx
@@ -15,18 +15,9 @@ import { Status, useFetchSupply, useSupply } from "providers/supply";
import { ErrorCard } from "components/common/ErrorCard";
import { LoadingCard } from "components/common/LoadingCard";
import { useVoteAccounts } from "providers/accounts/vote-accounts";
-// @ts-ignore
-import * as CoinGecko from "coingecko-api";
-
-enum CoingeckoStatus {
- Success,
- FetchFailed,
-}
-
-const CoinGeckoClient = new CoinGecko();
+import { CoingeckoStatus, useCoinGecko } from "utils/coingecko";
const CLUSTER_STATS_TIMEOUT = 5000;
-const PRICE_REFRESH = 10000;
export function ClusterStatsPage() {
return (
@@ -332,77 +323,3 @@ export function StatsNotReady({ error }: { error: boolean }) {
);
}
-
-interface CoinInfo {
- price: number;
- volume_24: number;
- market_cap: number;
- price_change_percentage_24h: number;
- market_cap_rank: number;
- last_updated: Date;
-}
-
-interface CoinInfoResult {
- data: {
- market_data: {
- current_price: {
- usd: number;
- };
- total_volume: {
- usd: number;
- };
- market_cap: {
- usd: number;
- };
- price_change_percentage_24h: number;
- market_cap_rank: number;
- };
- last_updated: string;
- };
-}
-
-type CoinGeckoResult = {
- coinInfo?: CoinInfo;
- status: CoingeckoStatus;
-};
-
-function useCoinGecko(coinId: string): CoinGeckoResult | undefined {
- const [coinInfo, setCoinInfo] = React.useState