diff --git a/packages/mobile/app/settings/index.tsx b/packages/mobile/app/settings/index.tsx
index aa0f6e5550..94847fd198 100644
--- a/packages/mobile/app/settings/index.tsx
+++ b/packages/mobile/app/settings/index.tsx
@@ -1,13 +1,16 @@
import { Stack } from "expo-router";
import { router } from "expo-router";
import React from "react";
-import { ScrollView, View } from "react-native";
+import { ScrollView, Switch, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
+import { useShallow } from "zustand/react/shallow";
import { RouteHeader } from "~/components/route-header";
import { SettingsGroup } from "~/components/settings/settings-group";
import { SettingsItem } from "~/components/settings/settings-item";
import { Text } from "~/components/ui/text";
+import { Colors } from "~/constants/theme-colors";
+import { useSettingsStore } from "~/stores/settings";
export default function SettingsScreen() {
return (
@@ -82,6 +85,7 @@ export default function SettingsScreen() {
title="Face ID"
onPress={() => router.push("/settings/face-id")}
/>
+
{/* {}} />
{}} /> */}
@@ -89,3 +93,25 @@ export default function SettingsScreen() {
);
}
+
+const PreviewAssetsToggle: React.FC = () => {
+ const { showUnverifiedAssets, setShowUnverifiedAssets } = useSettingsStore(
+ useShallow((state) => ({
+ showUnverifiedAssets: state.showUnverifiedAssets,
+ setShowUnverifiedAssets: state.setShowUnverifiedAssets,
+ }))
+ );
+
+ return (
+
+ }
+ />
+ );
+};
diff --git a/packages/mobile/components/modals/unverified-asset-modal.tsx b/packages/mobile/components/modals/unverified-asset-modal.tsx
new file mode 100644
index 0000000000..d53ebe2096
--- /dev/null
+++ b/packages/mobile/components/modals/unverified-asset-modal.tsx
@@ -0,0 +1,108 @@
+import {
+ BottomSheetBackdrop,
+ BottomSheetBackdropProps,
+ BottomSheetModal,
+ BottomSheetView,
+} from "@gorhom/bottom-sheet";
+import { forwardRef, useCallback } from "react";
+import { StyleSheet } from "react-native";
+
+import { AssetImage } from "~/components/ui/asset-image";
+import { Button } from "~/components/ui/button";
+import { Text } from "~/components/ui/text";
+import { Colors } from "~/constants/theme-colors";
+
+interface UnverifiedAssetModalProps {
+ onActivate: () => void;
+ assetSymbol: string;
+ assetImageUrl?: string;
+}
+
+export const UnverifiedAssetModal = forwardRef<
+ BottomSheetModal,
+ UnverifiedAssetModalProps
+>(({ onActivate, assetSymbol, assetImageUrl }, ref) => {
+ return (
+ (
+
+ ),
+ []
+ )}
+ backgroundStyle={styles.bottomSheetBackground}
+ handleIndicatorStyle={styles.indicator}
+ >
+
+ {assetImageUrl && (
+
+ )}
+
+ Activate unverified assets
+
+
+ {assetSymbol} is an unverified token. Do you wish to activate it? Be
+ sure to research thoroughly before trading.
+
+
+ You can always deactivate this setting in the settings modal.
+
+
+
+
+ );
+});
+
+const styles = StyleSheet.create({
+ container: {
+ alignItems: "center",
+ paddingHorizontal: 24,
+ paddingTop: 5,
+ paddingBottom: 42,
+ flex: 1,
+ },
+ bottomSheetBackground: {
+ backgroundColor: Colors.osmoverse[900],
+ },
+ indicator: {
+ backgroundColor: Colors.osmoverse[400],
+ },
+ assetIcon: {
+ width: 48,
+ height: 48,
+ borderRadius: 24,
+ marginBottom: 16,
+ },
+ title: {
+ fontSize: 24,
+ marginBottom: 16,
+ textAlign: "center",
+ },
+ description: {
+ color: Colors.osmoverse[200],
+ textAlign: "center",
+ marginBottom: 12,
+ },
+ note: {
+ color: Colors.osmoverse[300],
+ textAlign: "center",
+ marginBottom: 24,
+ },
+ button: {
+ width: "100%",
+ paddingVertical: 16,
+ },
+});
diff --git a/packages/mobile/components/portfolio/portfolio-asset-balances-table.tsx b/packages/mobile/components/portfolio/portfolio-asset-balances-table.tsx
index 4129b5d2e6..3142d9e4ca 100644
--- a/packages/mobile/components/portfolio/portfolio-asset-balances-table.tsx
+++ b/packages/mobile/components/portfolio/portfolio-asset-balances-table.tsx
@@ -1,8 +1,9 @@
+import { BottomSheetModal } from "@gorhom/bottom-sheet";
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 { useMemo, useRef, useState } from "react";
import {
ActivityIndicator,
Image,
@@ -11,11 +12,15 @@ import {
View,
} from "react-native";
import { SvgUri } from "react-native-svg";
+import { useShallow } from "zustand/react/shallow";
+import { UnverifiedAssetModal } from "~/components/modals/unverified-asset-modal";
import { SubscriptDecimal } from "~/components/subscript-decimal";
+import { Button } from "~/components/ui/button";
import { Text } from "~/components/ui/text";
import { Colors } from "~/constants/theme-colors";
import { useCosmosWallet } from "~/hooks/use-cosmos-wallet";
+import { useSettingsStore } from "~/stores/settings";
import { getChangeColor } from "~/utils/price";
import { api, RouterOutputs } from "~/utils/trpc";
@@ -24,6 +29,11 @@ const itemSize = 70;
export const PortfolioAssetBalancesTable = () => {
const { address } = useCosmosWallet();
const [searchQuery, setSearchQuery] = useState("");
+ const { showUnverifiedAssets } = useSettingsStore(
+ useShallow((state) => ({
+ showUnverifiedAssets: state.showUnverifiedAssets,
+ }))
+ );
const {
data: assetPagesData,
@@ -37,6 +47,10 @@ export const PortfolioAssetBalancesTable = () => {
userOsmoAddress: address!,
limit: 50,
...(searchQuery && { search: { query: searchQuery } }),
+ sort: {
+ keyPath: "usdValue",
+ direction: "desc",
+ },
},
{
enabled: Boolean(address),
@@ -89,6 +103,62 @@ const AssetItem = ({
}: {
asset: RouterOutputs["local"]["assets"]["getUserBridgeAssets"]["items"][number];
}) => {
+ const unverifiedAssetModalRef = useRef(null);
+ const { showUnverifiedAssets, setShowUnverifiedAssets } = useSettingsStore(
+ useShallow((state) => ({
+ showUnverifiedAssets: state.showUnverifiedAssets,
+ setShowUnverifiedAssets: state.setShowUnverifiedAssets,
+ }))
+ );
+
+ const isUnverified = !asset.isVerified;
+
+ if (isUnverified && !showUnverifiedAssets) {
+ return (
+
+
+ {asset.coinImageUrl?.endsWith(".svg") ? (
+
+ ) : (
+
+ )}
+
+ {asset.coinName}
+ {asset.amount && (
+
+ {formatPretty(asset.amount, { maxDecimals: 8 })}
+
+ )}
+
+
+
+ );
+ }
+
return (
void;
+}
+
+export const useSettingsStore = create()(
+ persist(
+ (set) => ({
+ showUnverifiedAssets: false,
+ setShowUnverifiedAssets: (show) => set({ showUnverifiedAssets: show }),
+ }),
+ {
+ name: "settings-store",
+ storage: createJSONStorage(() => mmkvStorage),
+ }
+ )
+);
diff --git a/packages/trpc/src/assets.ts b/packages/trpc/src/assets.ts
index c7066865fa..5b4a209ebf 100644
--- a/packages/trpc/src/assets.ts
+++ b/packages/trpc/src/assets.ts
@@ -370,21 +370,22 @@ export const assetsRouter = createTRPCRouter({
),
getUserBridgeAssets: publicProcedure
.input(
- GetInfiniteAssetsInputSchema.merge(UserOsmoAddressSchema).merge(
- z.object({
- sort: createSortSchema([
- "currentPrice",
- "priceChange24h",
- "usdValue",
- ] as const).optional(),
- })
- )
+ GetInfiniteAssetsInputSchema.omit({ onlyVerified: true })
+ .merge(UserOsmoAddressSchema)
+ .merge(
+ z.object({
+ sort: createSortSchema([
+ "currentPrice",
+ "priceChange24h",
+ "usdValue",
+ ] as const).optional(),
+ })
+ )
)
.query(
({
input: {
search,
- onlyVerified,
userOsmoAddress,
sort: sortInput,
categories,
@@ -446,7 +447,6 @@ export const assetsRouter = createTRPCRouter({
},
cacheKey: JSON.stringify({
search,
- onlyVerified,
userOsmoAddress,
sort: sortInput,
categories,
diff --git a/packages/web/components/table/portfolio-asset-balances.tsx b/packages/web/components/table/portfolio-asset-balances.tsx
index 0cff1bcf43..535fd4570a 100644
--- a/packages/web/components/table/portfolio-asset-balances.tsx
+++ b/packages/web/components/table/portfolio-asset-balances.tsx
@@ -128,7 +128,6 @@ export const PortfolioAssetBalancesTable: FunctionComponent<{
userOsmoAddress: account?.address,
limit: 50,
search: searchQuery,
- onlyVerified: !searchQuery && showUnverifiedAssets === false,
includePreview: showPreviewAssets,
sort,
},