Skip to content

Commit 6da8b13

Browse files
show fiat amount balance on homescreen
1 parent a5c0c81 commit 6da8b13

3 files changed

Lines changed: 56 additions & 7 deletions

File tree

src/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,6 @@ export const decodeBolt11 = (invoice: string) => {
121121
export const msatToSatoshi = (msat: number) => msat / 1000;
122122

123123
export const PLATFORM = Platform.OS;
124+
125+
export const coingeckoEndpoint =
126+
"https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd";

src/hooks/useMarketData.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { useQuery } from "@tanstack/react-query";
2+
import { coingeckoEndpoint } from "~/constants";
3+
4+
export const getBtcToUsdRate = async (): Promise<number> => {
5+
try {
6+
const response = await fetch(coingeckoEndpoint);
7+
if (!response.ok) {
8+
throw new Error("Network response was not ok");
9+
}
10+
const data = await response.json();
11+
if (data.bitcoin && data.bitcoin.usd) {
12+
return data.bitcoin.usd;
13+
}
14+
throw new Error("Invalid response from exchange rate API");
15+
} catch (error) {
16+
console.error("Failed to fetch BTC to USD rate:", error);
17+
throw new Error("Failed to fetch exchange rate");
18+
}
19+
};
20+
21+
export function useBtcToUsdRate() {
22+
return useQuery({
23+
queryKey: ["btcToUsdRate"],
24+
queryFn: getBtcToUsdRate,
25+
staleTime: 1000 * 60 * 5, // 5 minutes
26+
});
27+
}

src/screens/HomeScreen.tsx

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { AlertCircle, ChevronDown } from "lucide-react-native";
1010
import { useCallback, useState } from "react";
1111
import { COLORS } from "../lib/constants";
1212
import { useBalance } from "../hooks/useWallet";
13+
1314
import Animated, {
1415
FadeInDown,
1516
FadeOutDown,
@@ -19,10 +20,12 @@ import Animated, {
1920
import { NoahSafeAreaView } from "~/components/NoahSafeAreaView";
2021
import { useBottomTabBarHeight } from "react-native-bottom-tabs";
2122
import { PLATFORM } from "~/constants";
23+
import { useBtcToUsdRate } from "~/hooks/useMarketData";
2224

2325
const HomeScreen = () => {
2426
const navigation = useNavigation<NativeStackNavigationProp<HomeStackParamList>>();
2527
const { data: balance, isFetching, refetch, error } = useBalance();
28+
const { data: btcToUsdRate } = useBtcToUsdRate();
2629
const [isOpen, setIsOpen] = useState(false);
2730
const bottomTabBarHeight = useBottomTabBarHeight();
2831

@@ -31,6 +34,7 @@ const HomeScreen = () => {
3134
}, [refetch]);
3235

3336
const totalBalance = balance ? balance.onchain + balance.offchain : 0;
37+
const totalBalanceInUsd = btcToUsdRate ? (totalBalance / 100_000_000) * btcToUsdRate : 0;
3438
const errorMessage = error instanceof Error ? error.message : String(error);
3539

3640
const animatedRotation = useAnimatedStyle(() => {
@@ -77,13 +81,28 @@ const HomeScreen = () => {
7781
<Collapsible open={isOpen} onOpenChange={setIsOpen} className="items-center">
7882
<CollapsibleTrigger asChild>
7983
<Pressable>
80-
<View className="flex-row items-center space-x-2">
81-
<Text className="text-4xl font-bold">
82-
{totalBalance.toLocaleString()} sats
83-
</Text>
84-
<Animated.View style={animatedRotation}>
85-
<ChevronDown className="text-white" size={28} />
86-
</Animated.View>
84+
<View className="items-center">
85+
{btcToUsdRate ? (
86+
<Text className="text-2xl text-muted-foreground mb-2">
87+
$
88+
{totalBalanceInUsd.toLocaleString(undefined, {
89+
minimumFractionDigits: 2,
90+
maximumFractionDigits: 2,
91+
})}
92+
</Text>
93+
) : (
94+
<View className="h-[32px] mb-2 justify-center">
95+
<ActivityIndicator color={COLORS.BITCOIN_ORANGE} />
96+
</View>
97+
)}
98+
<View className="flex-row items-center space-x-2">
99+
<Text className="text-4xl font-bold">
100+
{totalBalance.toLocaleString()} sats
101+
</Text>
102+
<Animated.View style={animatedRotation}>
103+
<ChevronDown className="text-white" size={28} />
104+
</Animated.View>
105+
</View>
87106
</View>
88107
</Pressable>
89108
</CollapsibleTrigger>

0 commit comments

Comments
 (0)