Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion metro.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const { getDefaultConfig } = require('expo/metro-config');
const path = require('path');

module.exports = (() => {
const config = getDefaultConfig(__dirname);
Expand Down
11,135 changes: 7,950 additions & 3,185 deletions package-lock.json

Large diffs are not rendered by default.

52 changes: 2 additions & 50 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,13 @@
"test:coverage": "jest --coverage"
},
"dependencies": {
"@buildonspark/spark-frost-bare-addon": "0.0.5",
"@craftzdog/react-native-buffer": "6.1.1",
"@expo/vector-icons": "15.0.3",
"@gorhom/bottom-sheet": "5.2.8",
"@react-native-async-storage/async-storage": "2.2.0",
"@react-navigation/bottom-tabs": "7.9.0",
"@react-navigation/elements": "2.9.3",
"@react-navigation/native": "7.1.26",
"@reduxjs/toolkit": "2.11.2",
"@tetherto/wdk-pricing-bitfinex-http": "^1.0.0-beta.1",
"@tetherto/wdk-pricing-provider": "^1.0.0-beta.1",
"@tetherto/wdk-react-native-core": "github:tetherto/wdk-react-native-core#0b2be6eb5eed5b039cb1083441c3ae0e653fd02d",
"@tetherto/wdk-react-native-core": "github:nampc1/wdk-react-native-core-fork#nampc/dev",
"@tetherto/wdk-uikit-react-native": "^1.0.0-beta.2",
"b4a": "1.7.3",
"bare-crypto": "1.13.0",
"bare-dns": "2.1.4",
"bare-net": "2.2.0",
"bare-node-runtime": "1.1.4",
"bare-performance": "1.3.0",
"bare-pipe": "4.1.2",
"bare-signals": "4.2.0",
"bare-tcp": "2.2.2",
"bare-tls": "2.1.6",
"bare-zlib": "1.3.1",
"bip39": "3.1.0",
"browserify-zlib": "0.2.0",
"bufferutil": "4.1.0",
"decimal.js": "10.6.0",
"events": "3.3.0",
"expo": "54.0.31",
"expo-build-properties": "1.0.10",
"expo-camera": "17.0.10",
Expand All @@ -67,44 +45,18 @@
"expo-symbols": "1.0.8",
"expo-system-ui": "6.0.9",
"expo-web-browser": "15.0.10",
"http2-wrapper": "2.2.1",
"https-browserify": "1.0.0",
"jssha": "3.3.1",
"lucide-react-native": "0.544.0",
"multicoin-address-validator": "0.5.26",
"nice-grpc-web": "3.3.9",
"path-browserify": "1.0.1",
"process": "0.11.10",
"querystring-es3": "0.2.1",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.4",
"react-native-b4a": "0.0.4",
"react-native-chart-kit": "6.12.0",
"react-native-crypto": "2.2.1",
"react-native-device-info": "14.1.1",
"react-native-fast-pbkdf2": "0.3.1",
"react-native-gesture-handler": "2.28.0",
"react-native-get-random-values": "1.11.0",
"react-native-keychain": "10.0.0",
"react-native-nitro-modules": "0.32.1",
"react-native-qr-svg": "1.5.0",
"react-native-quick-crypto": "1.0.6",
"react-native-randombytes": "3.6.2",
"react-native-reanimated": "4.1.6",
"react-native-safe-area-context": "5.6.2",
"react-native-screens": "4.16.0",
"react-native-svg": "15.15.1",
"react-native-tcp-socket": "6.3.1",
"react-native-url-polyfill": "2.0.0",
"react-native-web": "0.21.2",
"react-native-worklets": "0.5.1",
"react-redux": "9.2.0",
"sodium-javascript": "0.8.0",
"sodium-universal": "5.0.1",
"sonner-native": "0.21.2",
"stream-browserify": "3.0.0",
"stream-http": "3.2.0"
"sonner-native": "0.21.2"
},
"devDependencies": {
"@types/b4a": "1.6.5",
Expand Down
36 changes: 8 additions & 28 deletions src/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
// Crypto polyfill - MUST be first import before anything else
import 'react-native-get-random-values';

import { Buffer } from '@craftzdog/react-native-buffer';
// @ts-ignore
global.Buffer = Buffer as unknown as BufferConstructor;

import { DarkTheme, ThemeProvider as NavigationThemeProvider } from '@react-navigation/native';
import { WdkAppProvider } from '@tetherto/wdk-react-native-core';
import { ThemeProvider } from '@tetherto/wdk-uikit-react-native';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { StatusBar } from 'expo-status-bar';
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
import { View } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import 'react-native-reanimated';
import getChainsConfig, { SparkNetworkMode } from '@/config/get-chains-config';
import getTokenConfigs from '@/config/get-token-configs';
import { Toaster } from 'sonner-native';
import { colors } from '@/constants/colors';
import { getNetworkMode, NetworkMode } from '@/services/network-mode-service';
import { useNetworkMode } from '@/hooks/use-network-mode';

SplashScreen.preventAutoHideAsync();

Expand All @@ -33,23 +24,15 @@ const CustomDarkTheme = {
};

export default function RootLayout() {
const [sparkNetwork, setSparkNetwork] = useState<SparkNetworkMode>('MAINNET');
const [networkMode, setNetworkMode] = useState<NetworkMode>('mainnet');
const [isReady, setIsReady] = useState(false);
const { workletChainConfigs, tokens, isLoaded } = useNetworkMode();

useEffect(() => {
const init = async () => {
const mode = await getNetworkMode();
setNetworkMode(mode);
// Use REGTEST for testnet mode, MAINNET for mainnet
setSparkNetwork(mode === 'testnet' ? 'REGTEST' : 'MAINNET');
setIsReady(true);
if (isLoaded) {
SplashScreen.hideAsync();
};
init();
}, []);
}
}, [isLoaded]);

if (!isReady) {
if (!isLoaded) {
return null;
}

Expand All @@ -61,10 +44,7 @@ export default function RootLayout() {
primaryColor: colors.primary,
}}
>
<WdkAppProvider
networkConfigs={getChainsConfig(sparkNetwork)}
tokenConfigs={getTokenConfigs(networkMode)}
>
<WdkAppProvider networkConfigs={workletChainConfigs} tokenConfigs={tokens}>
<NavigationThemeProvider value={CustomDarkTheme}>
<View style={{ flex: 1, backgroundColor: colors.background }}>
<Stack
Expand Down
36 changes: 14 additions & 22 deletions src/app/assets.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { FiatCurrency, pricingService } from '@/services/pricing-service';
import { useWallet, useWalletManager, useBalancesForWallet } from '@tetherto/wdk-react-native-core';
import { useDebouncedNavigation } from '@/hooks/use-debounced-navigation';
import { useFocusEffect } from 'expo-router';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Asset, AssetTicker, assetConfig } from '../config/assets';
import getTokenConfigs from '../config/get-token-configs';
import { Asset, TOKEN_UI_CONFIGS, getTokenConfigs } from '@/config/token';
import formatAmount from '@/utils/format-amount';
import getDisplaySymbol from '@/utils/get-display-symbol';
import formatTokenAmount from '@/utils/format-token-amount';
import Header from '@/components/header';
import { colors } from '@/constants/colors';
import { getNetworkMode, filterNetworksByMode, NetworkMode } from '@/services/network-mode-service';
import { filterNetworksByMode } from '@/services/network-mode-service';
import { useNetworkMode } from '@/hooks/use-network-mode';

export default function AssetsScreen() {
const insets = useSafeAreaInsets();
Expand All @@ -21,18 +20,7 @@ export default function AssetsScreen() {
const currentWalletId = activeWalletId || wallets[0]?.identifier;
const { isInitialized } = useWallet({ walletId: currentWalletId });
const [assets, setAssets] = useState<Asset[]>([]);
const [networkMode, setNetworkMode] = useState<NetworkMode>('mainnet');
const [networkModeLoaded, setNetworkModeLoaded] = useState(false);

// Load network mode on focus to pick up changes from settings
useFocusEffect(
useCallback(() => {
getNetworkMode().then((mode) => {
setNetworkMode(mode);
setNetworkModeLoaded(true);
});
}, [])
);
const { mode: networkMode, isLoaded: networkModeLoaded } = useNetworkMode();

const tokenConfigs = useMemo(() => {
if (!networkModeLoaded) return {};
Expand All @@ -59,7 +47,9 @@ export default function AssetsScreen() {
if (tokenAddress === null) {
denomination = networkTokens.native.symbol.toLowerCase();
} else {
const token = networkTokens.tokens.find((t) => t.address?.toLowerCase() === tokenAddress?.toLowerCase());
const token = networkTokens.tokens.find(
(t) => t.address?.toLowerCase() === tokenAddress?.toLowerCase()
);
if (token) {
denomination = token.symbol.toLowerCase();
}
Expand All @@ -72,7 +62,9 @@ export default function AssetsScreen() {
10,
tokenAddress === null
? networkTokens?.native.decimals || 18
: networkTokens?.tokens.find((t) => t.address?.toLowerCase() === tokenAddress?.toLowerCase())?.decimals || 6
: networkTokens?.tokens.find(
(t) => t.address?.toLowerCase() === tokenAddress?.toLowerCase()
)?.decimals || 6
);

const current = balanceMap.get(denomination) || { totalBalance: 0 };
Expand All @@ -83,7 +75,7 @@ export default function AssetsScreen() {

const promises = Array.from(balanceMap.entries()).map(
async ([denomination, { totalBalance }]) => {
const config = assetConfig[denomination];
const config = TOKEN_UI_CONFIGS[denomination];
if (!config) return null;

const availableNetworks = filterNetworksByMode(config.supportedNetworks, networkMode);
Expand All @@ -93,15 +85,15 @@ export default function AssetsScreen() {

const fiatValue = await pricingService.getFiatValue(
totalBalance,
denomination as AssetTicker,
denomination,
FiatCurrency.USD
);

return {
id: denomination,
name: config.name,
symbol,
amount: formatTokenAmount(totalBalance, denomination as AssetTicker, false),
amount: formatTokenAmount(totalBalance, denomination, false),
fiatValue: fiatValue,
fiatCurrency: FiatCurrency.USD,
icon: config.icon,
Expand Down
4 changes: 2 additions & 2 deletions src/app/authorize.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useWalletManager } from '@tetherto/wdk-react-native-core';
import { useDebouncedNavigation } from '@/hooks/use-debounced-navigation';
import { Fingerprint, Shield, Trash2 } from 'lucide-react-native';
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import { ActivityIndicator, Alert, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { colors } from '@/constants/colors';
Expand All @@ -10,7 +10,7 @@ import getErrorMessage from '@/utils/get-error-message';
export default function AuthorizeScreen() {
const insets = useSafeAreaInsets();
const router = useDebouncedNavigation();
const { hasWallet, initializeWallet, deleteWallet, wallets } = useWalletManager();
const { initializeWallet, deleteWallet, wallets } = useWalletManager();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

Expand Down
2 changes: 1 addition & 1 deletion src/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function Index() {
);
}

const walletExists = wallets.some(w => w.exists);
const walletExists = wallets.some((w) => w.exists);

if (!walletExists) {
return <Redirect href="/onboarding" />;
Expand Down
8 changes: 4 additions & 4 deletions src/app/receive/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { useLocalSearchParams } from 'expo-router';
import { useDebouncedNavigation } from '@/hooks/use-debounced-navigation';
import * as Clipboard from 'expo-clipboard';
import { ArrowLeft, Copy, Share, X } from 'lucide-react-native';
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import { Share as RNShare, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { toast } from 'sonner-native';
import { colors } from '@/constants/colors';
import { networkConfigs, NetworkType } from '@/config/networks';
import { getAddressType, NetworkId } from '@/config/chain';

export default function ReceiveQRCodeScreen() {
const insets = useSafeAreaInsets();
Expand All @@ -23,8 +23,8 @@ export default function ReceiveQRCodeScreen() {
};

const getAddressTypeLabel = (): string | null => {
const config = networkConfigs[networkId as NetworkType];
if (config?.accountType === 'Safe') {
const addressType = getAddressType(networkId as NetworkId);
if (addressType === 'Safe') {
return 'Safe Account Address';
}
return null; // No special label for native addresses
Expand Down
Loading