Skip to content

Commit

Permalink
feat: add copy address
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseRFelix committed Dec 15, 2024
1 parent 2d6ba74 commit ac8d911
Show file tree
Hide file tree
Showing 11 changed files with 438 additions and 391 deletions.
435 changes: 44 additions & 391 deletions packages/mobile/app/(tabs)/index.tsx

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as SplashScreen from "expo-splash-screen";
import { StatusBar } from "expo-status-bar";
import { useEffect, useState } from "react";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { Toaster } from "sonner-native";

import { DefaultTheme } from "~/constants/themes";
import { getMobileAssetListAndChains } from "~/utils/asset-lists";
Expand Down Expand Up @@ -135,6 +136,7 @@ export default function RootLayout() {
<ThemeProvider value={DefaultTheme}>
<GestureHandlerRootView>
<BottomSheetModalProvider>
<Toaster />
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
Expand Down
32 changes: 32 additions & 0 deletions packages/mobile/components/icons/copy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import { StyleProp, ViewStyle } from "react-native";
import Svg, { Path, Rect } from "react-native-svg";

import { Colors } from "~/constants/theme-colors";

export const CopyIcon = ({
width = 16,
height = 16,
stroke = Colors.osmoverse[500],
style,
}: {
width?: number;
height?: number;
stroke?: string;
style?: StyleProp<ViewStyle>;
}) => (
<Svg
width={width}
height={height}
viewBox="0 0 24 24"
fill="none"
stroke={stroke}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
style={style}
>
<Rect x={8} y={8} width={14} height={14} rx={2} ry={2} />
<Path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
</Svg>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import { Dec } from "@osmosis-labs/unit";
import { formatPretty } from "@osmosis-labs/utils";
import { FlashList } from "@shopify/flash-list";
import { Link } from "expo-router";
import { useMemo, useState } from "react";
import {
ActivityIndicator,
Image,
StyleSheet,
TouchableOpacity,
View,
} from "react-native";
import { SvgUri } from "react-native-svg";

import { SubscriptDecimal } from "~/components/subscript-decimal";
import { Text } from "~/components/ui/text";
import { Colors } from "~/constants/theme-colors";
import { useCosmosWallet } from "~/hooks/use-cosmos-wallet";
import { getChangeColor } from "~/utils/price";
import { api, RouterOutputs } from "~/utils/trpc";

const itemSize = 70;

export const PortfolioAssetBalancesTable = () => {
const { address } = useCosmosWallet();
const [searchQuery, setSearchQuery] = useState("");

const {
data: assetPagesData,
isLoading,
isRefetching,
refetch,
isFetchingNextPage,
fetchNextPage,
} = api.local.assets.getUserBridgeAssets.useInfiniteQuery(
{
userOsmoAddress: address!,
limit: 50,
...(searchQuery && { search: { query: searchQuery } }),
},
{
enabled: Boolean(address),
getNextPageParam: (lastPage) => lastPage.nextCursor,
initialCursor: 0,
keepPreviousData: true,
trpc: {
context: {
skipBatch: true,
},
},
}
);

const assetsData = useMemo(
() => assetPagesData?.pages.flatMap((page) => page?.items) ?? [],
[assetPagesData]
);

return (
<View style={styles.contentContainer}>
{isLoading ? (
<View style={{ paddingHorizontal: 24 }}>
<ActivityIndicator />
</View>
) : (
<FlashList
data={assetsData}
renderItem={({ item }) => <AssetItem asset={item} />}
keyExtractor={(item) => item.coinMinimalDenom}
estimatedItemSize={itemSize}
refreshing={isRefetching}
onRefresh={() => {
refetch();
}}
onEndReached={fetchNextPage}
/>
)}
{isFetchingNextPage && (
<View style={{ paddingHorizontal: 24 }}>
<ActivityIndicator />
</View>
)}
</View>
);
};

const AssetItem = ({
asset,
}: {
asset: RouterOutputs["local"]["assets"]["getUserBridgeAssets"]["items"][number];
}) => {
return (
<Link
href={{
pathname: "/asset/[coinMinimalDenom]",
params: {
coinMinimalDenom: asset.coinMinimalDenom,
coinDenom: asset.coinDenom,
coinImageUrl: asset.coinImageUrl,
},
}}
asChild
push
>
<TouchableOpacity style={styles.assetItem}>
<View style={styles.assetLeft}>
{asset.coinImageUrl?.endsWith(".svg") ? (
<SvgUri
uri={asset.coinImageUrl}
width={40}
height={40}
style={styles.assetIcon}
/>
) : (
<Image
source={{ uri: asset.coinImageUrl }}
style={styles.assetIcon}
/>
)}
<View>
<Text style={styles.assetName}>{asset.coinName}</Text>
{asset.amount && (
<Text type="caption" style={{ color: Colors.osmoverse[400] }}>
{formatPretty(asset.amount, { maxDecimals: 8 })}
</Text>
)}
</View>
</View>
<View style={styles.assetRight}>
<Text style={styles.price}>
{asset.usdValue ? (
<>
{asset.usdValue.symbol}
<SubscriptDecimal decimal={asset.usdValue.toDec()} />
</>
) : (
""
)}
</Text>
<Text
style={[
styles.percentage,
{
color: getChangeColor(
asset.priceChange24h?.toDec() || new Dec(0)
),
},
]}
>
{asset.priceChange24h?.toString()}
</Text>
</View>
</TouchableOpacity>
</Link>
);
};

const styles = StyleSheet.create({
contentContainer: {
backgroundColor: Colors.osmoverse[900],
flex: 1,
borderTopEndRadius: 32,
borderTopStartRadius: 32,
},
assetItem: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingVertical: 12,
paddingHorizontal: 24,
},
assetLeft: {
flexDirection: "row",
alignItems: "center",
},
assetIcon: {
width: 40,
height: 40,
borderRadius: 20,
marginRight: 12,
},
assetName: {
fontSize: 16,
fontWeight: "500",
},
assetRight: {
alignItems: "flex-end",
},
price: {
fontSize: 16,
fontWeight: "500",
},
percentage: {
fontSize: 14,
},
});
99 changes: 99 additions & 0 deletions packages/mobile/components/portfolio/portfolio-value.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { calculatePortfolioPerformance } from "@osmosis-labs/server";
import { timeToLocal } from "@osmosis-labs/utils";
import dayjs from "dayjs";
import { useState } from "react";
import { View } from "react-native";

import { Skeleton } from "~/components/ui/skeleton";
import { Text } from "~/components/ui/text";
import { useCosmosWallet } from "~/hooks/use-cosmos-wallet";
import { getChangeColor } from "~/utils/price";
import { api, RouterInputs, RouterOutputs } from "~/utils/trpc";

export const PortfolioValue = ({
allocation,
isLoadingAllocation,
}: {
allocation:
| RouterOutputs["local"]["portfolio"]["getPortfolioAssets"]
| undefined;
isLoadingAllocation: boolean;
}) => {
const { address } = useCosmosWallet();
const [range, setRange] =
useState<
RouterInputs["local"]["portfolio"]["getPortfolioOverTime"]["range"]
>("1d");
const [dataPoint, setDataPoint] = useState<{
time: number;
value: number | undefined;
}>({
time: dayjs().unix(),
value: undefined,
});

const {
data: portfolioOverTimeData,
isFetched: isPortfolioOverTimeDataIsFetched,
} = api.local.portfolio.getPortfolioOverTime.useQuery(
{
address: address!,
range,
},
{
enabled: Boolean(address),
onSuccess: (data) => {
if (data && data.length > 0) {
const lastDataPoint = data[data.length - 1];
setDataPoint({
time: timeToLocal(lastDataPoint.time),
value: lastDataPoint.value,
});
}
},
}
);

const { selectedPercentageRatePretty } = calculatePortfolioPerformance(
portfolioOverTimeData,
dataPoint
);

return (
<View
style={{
paddingHorizontal: 24,
flexDirection: "row",
alignItems: "center",
gap: 8,
}}
>
<Skeleton
style={isLoadingAllocation ? { width: 100, height: 48 } : undefined}
isLoaded={!isLoadingAllocation}
>
<Text type="title">{allocation?.totalCap?.toString()}</Text>
</Skeleton>
<Skeleton
style={
!isPortfolioOverTimeDataIsFetched
? { width: 60, height: 24 }
: undefined
}
isLoaded={isPortfolioOverTimeDataIsFetched}
>
<Text
type="subtitle"
style={{
color: getChangeColor(selectedPercentageRatePretty.toDec()),
}}
>
{selectedPercentageRatePretty
.maxDecimals(1)
.inequalitySymbol(false)
.toString()}
</Text>
</Skeleton>
</View>
);
};
2 changes: 2 additions & 0 deletions packages/mobile/components/route-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const styles = StyleSheet.create({
position: "absolute",
left: 0,
top: 0,
width: 44,
height: 44,
},
assetDenom: {
fontSize: 20,
Expand Down
Loading

0 comments on commit ac8d911

Please sign in to comment.