Skip to content

Commit

Permalink
issue #867 2. added usd value using coingecko api (#948)
Browse files Browse the repository at this point in the history
* issue #867 2. added usd value using coingecko api

* fix lockfile

* refactor: convert getPrice to support both hook and direct fetch function using react-query + takes in param to fetch any coins price

* fixed implementation of getPrice in BalanceCard.tsx

---------

Co-authored-by: Greg Nazario <[email protected]>
  • Loading branch information
sahil7886 and gregnazario authored Dec 11, 2024
1 parent 207bed0 commit fc0b65b
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 2 deletions.
61 changes: 61 additions & 0 deletions src/api/hooks/useGetPrice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {useQuery} from "@tanstack/react-query";

const COINGECKO_API_ENDPOINT = "https://api.coingecko.com/api/v3/simple/price";

/**
* Fetches the USD price for a cryptocurrency using its CoinGecko ID.
*
* Common CoinGecko IDs:
* - "aptos" : Aptos (APT)
* - "bitcoin": Bitcoin (BTC)
* - "ethereum": Ethereum (ETH)
* - "solana": Solana (SOL)
* - "binancecoin": Binance Coin (BNB)
* - "cardano": Cardano (ADA)
*
* Complete list of supported IDs:
* https://api.coingecko.com/api/v3/coins/list
*
* @param coinId - The CoinGecko ID of the cryptocurrency (defaults to "aptos")
* @returns The USD price of the cryptocurrency or null if the price fetch fails
*/
export async function getPrice(
coinId: string = "aptos",
): Promise<number | null> {
const query = {
ids: coinId,
vs_currencies: "usd",
};

const queryString = new URLSearchParams(query);
const url = `${COINGECKO_API_ENDPOINT}?${queryString}`;

try {
const response = await fetch(url, {
method: "GET",
});

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const data = await response.json();
return Number(data[coinId].usd);
} catch (error) {
console.error(`Error fetching ${coinId} price from CoinGecko:`, error);
return null;
}
}

/**
* Fetches the USD price for a cryptocurrency using its CoinGecko ID.
*
* @param coinId - The CoinGecko ID of the cryptocurrency (defaults to "aptos")
* @returns React Query result object containing the price data and query state
*/
export function useGetPrice(coinId: string = "aptos") {
return useQuery({
queryKey: ["price", coinId],
queryFn: () => getPrice(coinId),
});
}
39 changes: 37 additions & 2 deletions src/pages/Account/BalanceCard.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,65 @@
import React from "react";
import React, {useState, useEffect} from "react";
import {Stack, Typography} from "@mui/material";
import {getFormattedBalanceStr} from "../../components/IndividualPageContent/ContentValue/CurrencyValue";
import {Card} from "../../components/Card";
import {grey} from "../../themes/colors/aptosColorPalette";
import StyledTooltip from "../../components/StyledTooltip";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import {useGetAccountAPTBalance} from "../../api/hooks/useGetAccountAPTBalance";
import {getPrice} from "../../api/hooks/useGetPrice";
import {useGlobalState} from "../../global-config/GlobalConfig";

type BalanceCardProps = {
address: string;
};

export default function BalanceCard({address}: BalanceCardProps) {
const balance = useGetAccountAPTBalance(address);
const [globalState] = useGlobalState();
const [price, setPrice] = useState<number | null>(null);

useEffect(() => {
const fetchPrice = async () => {
try {
const fetchedPrice = await getPrice();
setPrice(fetchedPrice);
} catch (error) {
console.error("Error fetching APT price:", error);
setPrice(null);
}
};

fetchPrice();
}, []);

const balanceUSD =
balance.data && price !== null
? (Number(balance.data) * Number(price)) / 10e7
: null;

return balance.data ? (
<Card height="auto">
<Stack spacing={1.5} marginY={1}>
{/* APT balance */}
<Typography fontSize={17} fontWeight={700}>
{`${getFormattedBalanceStr(balance.data)} APT`}
</Typography>

{/* USD value */}
{globalState.network_name === "mainnet" && balanceUSD !== null && (
<Typography fontSize={14} color={grey[450]}>
${balanceUSD.toLocaleString(undefined, {maximumFractionDigits: 2})}{" "}
USD
</Typography>
)}

<Stack direction="row" spacing={1} alignItems="center">
<Typography fontSize={12} color={grey[450]}>
Balance
</Typography>
<StyledTooltip title="This balance reflects the amount of APT tokens held in your wallet.">
<StyledTooltip
title={`This balance reflects the amount of APT tokens held in your wallet${globalState.network_name === "mainnet" ? ` and their live value in USD at a rate of 1 APT = $${price?.toFixed(2)}` : ""}.`}
>
<InfoOutlinedIcon sx={{fontSize: 15, color: grey[450]}} />
</StyledTooltip>
</Stack>
Expand Down

0 comments on commit fc0b65b

Please sign in to comment.