diff --git a/scripts/list-outdated-dependencies/connect-dependencies.txt b/scripts/list-outdated-dependencies/connect-dependencies.txt
index 407d7632e35..dec6e2dc0b9 100644
--- a/scripts/list-outdated-dependencies/connect-dependencies.txt
+++ b/scripts/list-outdated-dependencies/connect-dependencies.txt
@@ -94,3 +94,4 @@ scroll-into-view-if-needed
@reown/walletkit
@walletconnect/core
@walletconnect/utils
+@walletconnect/react-native-compat
diff --git a/scripts/list-outdated-dependencies/mobile-dependencies.txt b/scripts/list-outdated-dependencies/mobile-dependencies.txt
index 9790db953fa..2a5984b204e 100644
--- a/scripts/list-outdated-dependencies/mobile-dependencies.txt
+++ b/scripts/list-outdated-dependencies/mobile-dependencies.txt
@@ -77,3 +77,8 @@ fantasticon
@whatwg-node/events
abortcontroller-polyfill
event-target-shim
+@react-native-async-storage/async-storage
+@types/fast-text-encoding
+@types/react-native-get-random-values
+fast-text-encoding
+react-native-get-random-values
\ No newline at end of file
diff --git a/suite-native/app/package.json b/suite-native/app/package.json
index 8587b3f44f7..00b0707d659 100644
--- a/suite-native/app/package.json
+++ b/suite-native/app/package.json
@@ -23,6 +23,7 @@
"dependencies": {
"@gorhom/bottom-sheet": "5.0.5",
"@mobily/ts-belt": "^3.13.1",
+ "@react-native-async-storage/async-storage": "^2.1.1",
"@react-native-community/netinfo": "^11.4.1",
"@react-native/metro-config": "^0.76.1",
"@react-navigation/bottom-tabs": "6.6.1",
@@ -42,6 +43,7 @@
"@suite-common/token-definitions": "workspace:*",
"@suite-common/wallet-core": "workspace:*",
"@suite-common/wallet-types": "workspace:*",
+ "@suite-common/walletconnect": "workspace:*",
"@suite-native/accounts": "workspace:*",
"@suite-native/alerts": "workspace:*",
"@suite-native/analytics": "workspace:*",
@@ -84,6 +86,7 @@
"@trezor/styles": "workspace:*",
"@trezor/theme": "workspace:*",
"@trezor/trezor-user-env-link": "workspace:*",
+ "@walletconnect/react-native-compat": "^2.18.0",
"@whatwg-node/events": "0.1.2",
"abortcontroller-polyfill": "1.7.6",
"buffer": "^6.0.3",
@@ -105,6 +108,7 @@
"expo-system-ui": "^4.0.2",
"expo-updates": "0.26.6",
"expo-video": "^2.0.1",
+ "fast-text-encoding": "^1.0.6",
"lottie-react-native": "^7.1.0",
"node-libs-browser": "^2.2.1",
"react": "18.2.0",
@@ -112,6 +116,7 @@
"react-native": "0.76.1",
"react-native-edge-to-edge": "^1.3.1",
"react-native-gesture-handler": "^2.21.0",
+ "react-native-get-random-values": "^1.11.0",
"react-native-keyboard-aware-scroll-view": "0.9.5",
"react-native-mmkv": "2.12.2",
"react-native-quick-crypto": "^0.7.6",
@@ -133,8 +138,10 @@
"@react-native/babel-preset": "^0.75.2",
"@suite-common/test-utils": "workspace:^",
"@trezor/connect-mobile": "workspace:^",
+ "@types/fast-text-encoding": "^1",
"@types/jest": "^29.5.12",
"@types/node": "22.10.1",
+ "@types/react-native-get-random-values": "^1",
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
"babel-plugin-transform-remove-console": "^6.9.4",
"detox": "^20.25.6",
diff --git a/suite-native/app/src/initActions.ts b/suite-native/app/src/initActions.ts
index 8fefd6c7920..fc016b9d784 100644
--- a/suite-native/app/src/initActions.ts
+++ b/suite-native/app/src/initActions.ts
@@ -9,7 +9,9 @@ import {
initStakeDataThunk,
periodicFetchFiatRatesThunk,
} from '@suite-common/wallet-core';
+import { walletConnectInitThunk } from '@suite-common/walletconnect';
import { initAnalyticsThunk } from '@suite-native/analytics';
+import { FeatureFlag, selectIsFeatureFlagEnabled } from '@suite-native/feature-flags';
import { selectFiatCurrencyCode } from '@suite-native/settings';
import { setIsAppReady, setIsConnectInitialized } from '@suite-native/state/src/appSlice';
@@ -49,6 +51,10 @@ export const applicationInit = createThunk(
// Create Portfolio Tracker device if it doesn't exist
dispatch(createImportedDeviceThunk());
+
+ if (selectIsFeatureFlagEnabled(getState(), FeatureFlag.IsWalletConnectEnabled)) {
+ dispatch(walletConnectInitThunk());
+ }
} catch (error) {
console.error(error);
} finally {
diff --git a/suite-native/app/src/navigation/RootStackNavigator.tsx b/suite-native/app/src/navigation/RootStackNavigator.tsx
index 8edb08655bf..7f821279798 100644
--- a/suite-native/app/src/navigation/RootStackNavigator.tsx
+++ b/suite-native/app/src/navigation/RootStackNavigator.tsx
@@ -11,7 +11,11 @@ import {
import { AddCoinAccountStackNavigator } from '@suite-native/module-add-accounts';
import { DeviceCompromisedModalScreen } from '@suite-native/module-authenticity-checks';
import { AuthorizeDeviceStackNavigator } from '@suite-native/module-authorize-device';
-import { ConnectPopupScreen } from '@suite-native/module-connect-popup';
+import {
+ ConnectPopupScreen,
+ WalletConnectPairScreen,
+ WalletConnectSessionPopupScreen,
+} from '@suite-native/module-connect-popup';
import { DevUtilsStackNavigator } from '@suite-native/module-dev-utils';
import { DeviceSettingsStackNavigator } from '@suite-native/module-device-settings';
import { OnboardingStackNavigator } from '@suite-native/module-onboarding';
@@ -81,6 +85,14 @@ export const RootStackNavigator = () => {
/>
+
+
{
isTradingEnabled: true,
isDeviceOnboardingEnabled: true,
IsFwRevisionCheckEnabled: true,
+ isWalletConnectEnabled: true,
});
});
@@ -56,6 +57,7 @@ describe('featureFlagsSlice', () => {
isTradingEnabled: false,
isDeviceOnboardingEnabled: false,
IsFwRevisionCheckEnabled: false,
+ isWalletConnectEnabled: false,
});
});
@@ -83,6 +85,7 @@ describe('featureFlagsSlice', () => {
isTradingEnabled: false,
isDeviceOnboardingEnabled: false,
IsFwRevisionCheckEnabled: false,
+ isWalletConnectEnabled: false,
});
});
});
diff --git a/suite-native/feature-flags/src/featureFlagsSlice.ts b/suite-native/feature-flags/src/featureFlagsSlice.ts
index b9da94ffe29..b54f152cfdb 100644
--- a/suite-native/feature-flags/src/featureFlagsSlice.ts
+++ b/suite-native/feature-flags/src/featureFlagsSlice.ts
@@ -12,6 +12,7 @@ export const FeatureFlag = {
IsDeviceOnboardingEnabled: 'isDeviceOnboardingEnabled',
IsTradingEnabled: 'isTradingEnabled',
IsFwRevisionCheckEnabled: 'IsFwRevisionCheckEnabled',
+ IsWalletConnectEnabled: 'isWalletConnectEnabled',
} as const;
export type FeatureFlag = (typeof FeatureFlag)[keyof typeof FeatureFlag];
@@ -31,6 +32,7 @@ export const featureFlagsInitialState: FeatureFlagsState = {
[FeatureFlag.IsDeviceOnboardingEnabled]: isDebugEnv() && !isDetoxTestBuild(),
[FeatureFlag.IsTradingEnabled]: isDebugEnv(),
[FeatureFlag.IsFwRevisionCheckEnabled]: isDevelopOrDebugEnv(),
+ [FeatureFlag.IsWalletConnectEnabled]: isDevelopOrDebugEnv(),
};
export const featureFlagsPersistedKeys: Array = [
@@ -42,6 +44,7 @@ export const featureFlagsPersistedKeys: Array = [
FeatureFlag.IsDeviceOnboardingEnabled,
FeatureFlag.IsTradingEnabled,
FeatureFlag.IsFwRevisionCheckEnabled,
+ FeatureFlag.IsWalletConnectEnabled,
];
export const featureFlagsSlice = createSlice({
diff --git a/suite-native/intl/src/en.ts b/suite-native/intl/src/en.ts
index 77f89aa07d9..09fd141fa53 100644
--- a/suite-native/intl/src/en.ts
+++ b/suite-native/intl/src/en.ts
@@ -288,6 +288,7 @@ export const en = {
title: 'Trezor Connect Mobile',
callback: 'Callback',
confirm: 'Confirm',
+ cancel: 'Cancel',
areYouSureMessage: 'Are you sure you want to continue?\nMake sure you trust the source.',
connectionStatus: {
loading: 'Loading...',
@@ -303,6 +304,29 @@ export const en = {
bottomSheets: {
confirmOnDeviceMessage: 'Go to your device and verify the details of the operation.',
},
+ walletConnect: {
+ title: 'WalletConnect',
+ message:
+ 'An external app is trying to connect to your Trezor Suite. Make sure you trust the source!',
+ connect: 'Connect',
+ pairingUrl: 'Enter pairing URL',
+ scanQR: 'Scan QR code',
+ activeConnections: 'Active connections',
+ noActiveConnections: 'No active connections',
+ disconnect: 'Disconnect',
+ serviceStatus: {
+ verified: 'Verified',
+ unknown: 'Unknown',
+ dangerous: 'Dangerous',
+ },
+ errors: {
+ requestExpired:
+ 'Request has expired. Please go back to the application and try again.',
+ isScam: 'The request was detected as a scam and was blocked automatically.',
+ unableToVerify:
+ 'We were unable to verify the request authenticity. Please make sure you trust the source.',
+ },
+ },
},
moduleDevice: {
incompatibleFirmwareModalAppendix: {
@@ -608,6 +632,10 @@ export const en = {
title: 'Device checks',
subtitle: 'Authenticity and security checks',
},
+ walletConnect: {
+ title: 'WalletConnect',
+ subtitle: 'Use external apps using the WalletConnect protocol',
+ },
},
support: {
title: 'Support',
diff --git a/suite-native/module-connect-popup/package.json b/suite-native/module-connect-popup/package.json
index 60b5d225703..eb94cb1abc2 100644
--- a/suite-native/module-connect-popup/package.json
+++ b/suite-native/module-connect-popup/package.json
@@ -14,6 +14,7 @@
"@reduxjs/toolkit": "1.9.5",
"@suite-common/suite-types": "workspace:*",
"@suite-common/wallet-core": "workspace:*",
+ "@suite-common/walletconnect": "workspace:*",
"@suite-native/atoms": "workspace:*",
"@suite-native/config": "workspace:*",
"@suite-native/device": "workspace:*",
diff --git a/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts b/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts
index b4d03a3a4f9..962762f295a 100644
--- a/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts
+++ b/suite-native/module-connect-popup/src/hooks/useConnectPopupNavigation.ts
@@ -5,6 +5,7 @@ import { useNavigation } from '@react-navigation/native';
import * as Linking from 'expo-linking';
import { connectPopupDeeplinkThunk, selectConnectPopupCall } from '@suite-common/connect-popup';
+import { selectPendingProposal, walletConnectPairThunk } from '@suite-common/walletconnect';
import { isDevelopOrDebugEnv } from '@suite-native/config';
import { FeatureFlag, useFeatureFlag } from '@suite-native/feature-flags';
import {
@@ -30,26 +31,38 @@ const isConnectPopupUrl = (url: string): boolean => {
return false;
};
+const isWalletConnectUrl = (url: string): boolean =>
+ url.startsWith('trezorsuitelite://walletconnect');
+
// TODO: will be necessary to handle if device is not connected/unlocked so we probably want to wait until user unlock device
// we already have some modals like biometrics or coin enabled which are waiting for device to be connected
export const useConnectPopupNavigation = () => {
const featureFlagEnabled = useFeatureFlag(FeatureFlag.IsConnectPopupEnabled);
+ const featureFlagWalletConnectEnabled = useFeatureFlag(FeatureFlag.IsWalletConnectEnabled);
const navigation = useNavigation();
const dispatch = useDispatch();
const connectPopupCall = useSelector(selectConnectPopupCall);
+ const walletConnectProposal = useSelector(selectPendingProposal);
// Handle deeplink
const url = Linking.useURL();
useEffect(() => {
- if (!featureFlagEnabled) return;
- if (!url || !isConnectPopupUrl(url)) return;
- dispatch(connectPopupDeeplinkThunk({ url }));
- }, [url, featureFlagEnabled, dispatch]);
+ if (!featureFlagEnabled || !url) return;
+
+ if (isConnectPopupUrl(url)) {
+ dispatch(connectPopupDeeplinkThunk({ url }));
+ } else if (featureFlagWalletConnectEnabled && isWalletConnectUrl(url)) {
+ dispatch(walletConnectPairThunk({ uri: url }));
+ }
+ }, [url, featureFlagEnabled, featureFlagWalletConnectEnabled, dispatch]);
useEffect(() => {
if (connectPopupCall) {
navigation.navigate(RootStackRoutes.ConnectPopup);
}
- }, [connectPopupCall, navigation]);
+ if (walletConnectProposal && !walletConnectProposal.expired) {
+ navigation.navigate(RootStackRoutes.WalletConnectSessionPopup);
+ }
+ }, [connectPopupCall, walletConnectProposal, navigation]);
};
diff --git a/suite-native/module-connect-popup/src/index.ts b/suite-native/module-connect-popup/src/index.ts
index ce81e7177e3..c0ee146b07f 100644
--- a/suite-native/module-connect-popup/src/index.ts
+++ b/suite-native/module-connect-popup/src/index.ts
@@ -1,3 +1,5 @@
export * from './screens/ConnectPopupScreen';
+export * from './screens/WalletConnectSessionPopupScreen';
+export * from './screens/WalletConnectPairScreen';
export * from './hooks/useConnectPopupNavigation';
export * from './hooks/useIsConnectPopupOpened';
diff --git a/suite-native/module-connect-popup/src/screens/WalletConnectPairScreen.tsx b/suite-native/module-connect-popup/src/screens/WalletConnectPairScreen.tsx
new file mode 100644
index 00000000000..9f3fc7d64d7
--- /dev/null
+++ b/suite-native/module-connect-popup/src/screens/WalletConnectPairScreen.tsx
@@ -0,0 +1,107 @@
+import { useState } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+
+import {
+ selectSessions,
+ walletConnectDisconnectThunk,
+ walletConnectPairThunk,
+} from '@suite-common/walletconnect';
+import { Button, Divider, HStack, IconButton, Input, Text, VStack } from '@suite-native/atoms';
+import { Translation } from '@suite-native/intl';
+import { Screen, ScreenHeader } from '@suite-native/navigation';
+import { ScanQRBottomSheet } from '@suite-native/qr-code';
+
+export const WalletConnectPairScreen = () => {
+ const dispatch = useDispatch();
+ const sessions = useSelector(selectSessions);
+
+ const [uri, setUri] = useState('');
+ const [qrVisible, setQrVisible] = useState(false);
+
+ const handlePair = () => {
+ dispatch(walletConnectPairThunk({ uri }));
+ setUri('');
+ };
+ const handleQr = () => {
+ setQrVisible(true);
+ };
+
+ return (
+
+
+
+ }
+ />
+ }
+ >
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+ :
+
+ {sessions.map(session => (
+
+
+ {session.peer.metadata.name}
+ {session.peer.metadata.url}
+
+ {session.topic}
+
+
+
+
+
+
+ ))}
+ {sessions.length === 0 && (
+
+
+
+ )}
+
+
+
+ }
+ isVisible={qrVisible}
+ onCodeScanned={setUri}
+ onClose={() => setQrVisible(false)}
+ />
+
+ );
+};
diff --git a/suite-native/module-connect-popup/src/screens/WalletConnectSessionPopupScreen.tsx b/suite-native/module-connect-popup/src/screens/WalletConnectSessionPopupScreen.tsx
new file mode 100644
index 00000000000..ec910d2e58f
--- /dev/null
+++ b/suite-native/module-connect-popup/src/screens/WalletConnectSessionPopupScreen.tsx
@@ -0,0 +1,137 @@
+import { useDispatch, useSelector } from 'react-redux';
+
+import { useNavigation } from '@react-navigation/native';
+
+import {
+ selectPendingProposal,
+ sessionProposalApproveThunk,
+ sessionProposalRejectThunk,
+} from '@suite-common/walletconnect';
+import {
+ AlertBox,
+ Badge,
+ Button,
+ HStack,
+ Image,
+ Text,
+ TitleHeader,
+ VStack,
+} from '@suite-native/atoms';
+import { Translation } from '@suite-native/intl';
+import { Screen, ScreenHeader } from '@suite-native/navigation';
+
+export const WalletConnectSessionPopupScreen = () => {
+ const navigation = useNavigation();
+
+ const dispatch = useDispatch();
+ const pendingProposal = useSelector(selectPendingProposal);
+
+ const handleAccept = () => {
+ if (pendingProposal?.eventId)
+ dispatch(sessionProposalApproveThunk({ eventId: pendingProposal?.eventId }));
+ navigation.goBack();
+ };
+ const handleReject = () => {
+ if (pendingProposal?.eventId)
+ dispatch(sessionProposalRejectThunk({ eventId: pendingProposal?.eventId }));
+ navigation.goBack();
+ };
+
+ return (
+
+
+
+ }
+ />
+ }
+ >
+
+
+
+ {!pendingProposal?.isScam && pendingProposal?.validation === 'VALID' && (
+
+ }
+ />
+ )}
+ {!pendingProposal?.isScam && pendingProposal?.validation === 'UNKNOWN' && (
+
+ }
+ />
+ )}
+ {(pendingProposal?.isScam || pendingProposal?.validation === 'INVALID') && (
+
+ }
+ />
+ )}
+
+
+
+
+
+ {pendingProposal?.isScam && (
+ }
+ />
+ )}
+ {pendingProposal?.validation === 'INVALID' && (
+
+ }
+ />
+ )}
+
+ {pendingProposal?.expired && (
+
+ }
+ />
+ )}
+
+
+
+
+
+
+
+ );
+};
diff --git a/suite-native/module-connect-popup/tsconfig.json b/suite-native/module-connect-popup/tsconfig.json
index c3c0c910538..a0e1b1e0890 100644
--- a/suite-native/module-connect-popup/tsconfig.json
+++ b/suite-native/module-connect-popup/tsconfig.json
@@ -8,6 +8,9 @@
{
"path": "../../suite-common/wallet-core"
},
+ {
+ "path": "../../suite-common/walletconnect"
+ },
{ "path": "../atoms" },
{ "path": "../config" },
{ "path": "../device" },
diff --git a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx
index 911f4fa82d5..78d75aaf9f0 100644
--- a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx
+++ b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx
@@ -14,6 +14,7 @@ const featureFlagsTitleMap = {
[FeatureFlagEnum.IsDeviceOnboardingEnabled]: 'Device onboarding',
[FeatureFlagEnum.IsTradingEnabled]: 'Trading',
[FeatureFlagEnum.IsFwRevisionCheckEnabled]: 'Firmware Revision Check',
+ [FeatureFlagEnum.IsWalletConnectEnabled]: 'WalletConnect',
} as const satisfies Record;
const FeatureFlag = ({ featureFlag }: { featureFlag: FeatureFlagEnum }) => {
diff --git a/suite-native/module-settings/src/components/FeaturesSettings.tsx b/suite-native/module-settings/src/components/FeaturesSettings.tsx
index bde29cfdb96..ad8a8676e16 100644
--- a/suite-native/module-settings/src/components/FeaturesSettings.tsx
+++ b/suite-native/module-settings/src/components/FeaturesSettings.tsx
@@ -22,6 +22,7 @@ export const FeaturesSettings = () => {
const isDevButtonVisible = useAtomValue(isDevButtonVisibleAtom);
const isUsbDeviceConnectFeatureEnabled = useFeatureFlag(FeatureFlag.IsDeviceConnectEnabled);
const isFwRevisionCheckEnabled = useFeatureFlag(FeatureFlag.IsFwRevisionCheckEnabled);
+ const isWalletConnectEnabled = useFeatureFlag(FeatureFlag.IsWalletConnectEnabled);
const navigation = useNavigation>();
const navigateTo = useSettingsNavigateTo();
@@ -85,6 +86,17 @@ export const FeaturesSettings = () => {
)}
>
)}
+ {isWalletConnectEnabled && (
+ }
+ subtitle={
+
+ }
+ onPress={() => navigation.navigate(RootStackRoutes.WalletConnectPair)}
+ testID="@settings/wallet-connect"
+ />
+ )}
);
};
diff --git a/suite-native/navigation/src/navigators.ts b/suite-native/navigation/src/navigators.ts
index d155b94ec4d..bdf8af0de86 100644
--- a/suite-native/navigation/src/navigators.ts
+++ b/suite-native/navigation/src/navigators.ts
@@ -221,6 +221,8 @@ export type RootStackParamList = {
[RootStackRoutes.SendStack]: NavigatorScreenParams;
[RootStackRoutes.CoinEnablingInit]: undefined;
[RootStackRoutes.ConnectPopup]: undefined;
+ [RootStackRoutes.WalletConnectSessionPopup]: undefined;
+ [RootStackRoutes.WalletConnectPair]: undefined;
[RootStackRoutes.SettingsScreenStack]: NavigatorScreenParams;
[RootStackRoutes.DeviceCompromisedModalScreen]: undefined;
};
diff --git a/suite-native/navigation/src/routes.ts b/suite-native/navigation/src/routes.ts
index 6ecc89be5aa..417fc3cb816 100644
--- a/suite-native/navigation/src/routes.ts
+++ b/suite-native/navigation/src/routes.ts
@@ -15,6 +15,8 @@ export enum RootStackRoutes {
AddCoinAccountStack = 'AddCoinAccountStack',
CoinEnablingInit = 'CoinEnablingInit',
ConnectPopup = 'ConnectPopup',
+ WalletConnectSessionPopup = 'WalletConnectSessionPopup',
+ WalletConnectPair = 'WalletConnectPair',
SettingsScreenStack = 'SettingsScreenStack',
DeviceCompromisedModalScreen = 'DeviceCompromisedModalScreen',
}
diff --git a/suite-native/state/package.json b/suite-native/state/package.json
index d8c1d1360d2..3fc4c626de7 100644
--- a/suite-native/state/package.json
+++ b/suite-native/state/package.json
@@ -21,6 +21,7 @@
"@suite-common/toast-notifications": "workspace:*",
"@suite-common/token-definitions": "workspace:*",
"@suite-common/wallet-core": "workspace:*",
+ "@suite-common/walletconnect": "workspace:*",
"@suite-native/blockchain": "workspace:*",
"@suite-native/device": "workspace:*",
"@suite-native/device-authorization": "workspace:*",
diff --git a/suite-native/state/src/reducers.ts b/suite-native/state/src/reducers.ts
index 68f1d9db7b0..caf32ce8007 100644
--- a/suite-native/state/src/reducers.ts
+++ b/suite-native/state/src/reducers.ts
@@ -20,6 +20,9 @@ import {
prepareStakeReducer,
prepareTransactionsReducer,
} from '@suite-common/wallet-core';
+// Suite Native has circular in @suite-native/test-utils -> @suite-native/state -> ... -> @suite-native/test-utils
+// This is causing problems handling types in WalletConnect, so we import the reducer directly instead of the whole module
+import { prepareWalletConnectReducer } from '@suite-common/walletconnect/src/walletConnectReducer';
import { deviceAuthorizationReducer } from '@suite-native/device-authorization';
import {
DiscoveryConfigState,
@@ -63,6 +66,7 @@ const sendFormReducer = sendFormSlice.prepareReducer(extraDependencies);
const stakeReducer = prepareStakeReducer(extraDependencies);
const firmwareReducer = prepareFirmwareReducer(extraDependencies);
const connectPopupReducer = prepareConnectPopupReducer(extraDependencies);
+const walletConnectReducer = prepareWalletConnectReducer(extraDependencies);
export const prepareRootReducers = async () => {
const appSettingsPersistedReducer = await preparePersistReducer({
@@ -85,6 +89,7 @@ export const prepareRootReducers = async () => {
fees: feesReducer,
stake: stakeReducer,
connectPopup: connectPopupReducer,
+ walletConnect: walletConnectReducer,
});
const walletPersistedReducer = await preparePersistReducer({
diff --git a/suite-native/state/tsconfig.json b/suite-native/state/tsconfig.json
index 6554093272b..b12495f364c 100644
--- a/suite-native/state/tsconfig.json
+++ b/suite-native/state/tsconfig.json
@@ -25,6 +25,9 @@
{
"path": "../../suite-common/wallet-core"
},
+ {
+ "path": "../../suite-common/walletconnect"
+ },
{ "path": "../blockchain" },
{ "path": "../device" },
{ "path": "../device-authorization" },
diff --git a/yarn.lock b/yarn.lock
index df86eb50732..942925e355f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7156,6 +7156,17 @@ __metadata:
languageName: node
linkType: hard
+"@react-native-async-storage/async-storage@npm:^2.1.1":
+ version: 2.1.1
+ resolution: "@react-native-async-storage/async-storage@npm:2.1.1"
+ dependencies:
+ merge-options: "npm:^3.0.4"
+ peerDependencies:
+ react-native: ^0.0.0-0 || >=0.65 <1.0
+ checksum: 10/ae65d10606e2ba307dc7a4362612c3568fdae3833dae407810c2f457ab1a6ec2c50f2979c8afbf6477b56c8033b8f332038c54e617165618d1b5305e91784300
+ languageName: node
+ linkType: hard
+
"@react-native-community/cli-clean@npm:15.1.2":
version: 15.1.2
resolution: "@react-native-community/cli-clean@npm:15.1.2"
@@ -10809,6 +10820,7 @@ __metadata:
"@gorhom/bottom-sheet": "npm:5.0.5"
"@jest/globals": "npm:^29.7.0"
"@mobily/ts-belt": "npm:^3.13.1"
+ "@react-native-async-storage/async-storage": "npm:^2.1.1"
"@react-native-community/cli": "npm:^15.1.2"
"@react-native-community/netinfo": "npm:^11.4.1"
"@react-native/babel-preset": "npm:^0.75.2"
@@ -10831,6 +10843,7 @@ __metadata:
"@suite-common/token-definitions": "workspace:*"
"@suite-common/wallet-core": "workspace:*"
"@suite-common/wallet-types": "workspace:*"
+ "@suite-common/walletconnect": "workspace:*"
"@suite-native/accounts": "workspace:*"
"@suite-native/alerts": "workspace:*"
"@suite-native/analytics": "workspace:*"
@@ -10874,8 +10887,11 @@ __metadata:
"@trezor/styles": "workspace:*"
"@trezor/theme": "workspace:*"
"@trezor/trezor-user-env-link": "workspace:*"
+ "@types/fast-text-encoding": "npm:^1"
"@types/jest": "npm:^29.5.12"
"@types/node": "npm:22.10.1"
+ "@types/react-native-get-random-values": "npm:^1"
+ "@walletconnect/react-native-compat": "npm:^2.18.0"
"@whatwg-node/events": "npm:0.1.2"
abortcontroller-polyfill: "npm:1.7.6"
babel-plugin-transform-inline-environment-variables: "npm:^0.4.4"
@@ -10901,6 +10917,7 @@ __metadata:
expo-system-ui: "npm:^4.0.2"
expo-updates: "npm:0.26.6"
expo-video: "npm:^2.0.1"
+ fast-text-encoding: "npm:^1.0.6"
jest: "npm:^29.7.0"
jest-junit: "npm:^16.0.0"
lottie-react-native: "npm:^7.1.0"
@@ -10911,6 +10928,7 @@ __metadata:
react-native: "npm:0.76.1"
react-native-edge-to-edge: "npm:^1.3.1"
react-native-gesture-handler: "npm:^2.21.0"
+ react-native-get-random-values: "npm:^1.11.0"
react-native-keyboard-aware-scroll-view: "npm:0.9.5"
react-native-mmkv: "npm:2.12.2"
react-native-quick-crypto: "npm:^0.7.6"
@@ -11554,6 +11572,7 @@ __metadata:
"@reduxjs/toolkit": "npm:1.9.5"
"@suite-common/suite-types": "workspace:*"
"@suite-common/wallet-core": "workspace:*"
+ "@suite-common/walletconnect": "workspace:*"
"@suite-native/atoms": "workspace:*"
"@suite-native/config": "workspace:*"
"@suite-native/device": "workspace:*"
@@ -11995,6 +12014,7 @@ __metadata:
"@suite-common/toast-notifications": "workspace:*"
"@suite-common/token-definitions": "workspace:*"
"@suite-common/wallet-core": "workspace:*"
+ "@suite-common/walletconnect": "workspace:*"
"@suite-native/blockchain": "workspace:*"
"@suite-native/device": "workspace:*"
"@suite-native/device-authorization": "workspace:*"
@@ -14379,6 +14399,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/fast-text-encoding@npm:^1":
+ version: 1.0.3
+ resolution: "@types/fast-text-encoding@npm:1.0.3"
+ checksum: 10/34ec2bbaf3e3ee36b7b74375293becc735378f77e9cd93b810ad988b42991ee80d30fb942e6ba03adfc1f0cb0e2024a0aeee84475847563ed6782e21c4c0f5f0
+ languageName: node
+ linkType: hard
+
"@types/file-saver@npm:^2.0.6":
version: 2.0.7
resolution: "@types/file-saver@npm:2.0.7"
@@ -15060,6 +15087,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/react-native-get-random-values@npm:^1":
+ version: 1.8.2
+ resolution: "@types/react-native-get-random-values@npm:1.8.2"
+ checksum: 10/08f3f82efbb5b6d9acd8f7f55a2dac9f228886323ac3018a1bab46cd1b45f24809d194fd2a3fe02a9ec4196606325e5cfffde0b0057ae785208b658fdc83c821
+ languageName: node
+ linkType: hard
+
"@types/react-qr-reader@npm:^2.1.7":
version: 2.1.7
resolution: "@types/react-qr-reader@npm:2.1.7"
@@ -15925,6 +15959,26 @@ __metadata:
languageName: node
linkType: hard
+"@walletconnect/react-native-compat@npm:^2.18.0":
+ version: 2.18.0
+ resolution: "@walletconnect/react-native-compat@npm:2.18.0"
+ dependencies:
+ events: "npm:3.3.0"
+ fast-text-encoding: "npm:1.0.6"
+ react-native-url-polyfill: "npm:2.0.0"
+ peerDependencies:
+ "@react-native-async-storage/async-storage": "*"
+ "@react-native-community/netinfo": "*"
+ expo-application: "*"
+ react-native: "*"
+ react-native-get-random-values: "*"
+ peerDependenciesMeta:
+ expo-application:
+ optional: true
+ checksum: 10/ef82bffb1f85f588b2f813ae30dbaf7ed87f37138548e5b3820e68df42f8a2c446d9c8a8a1f6c0fbd6d7a0c8ae89009aa02d75e208c7e58442433d2d93b97f2f
+ languageName: node
+ linkType: hard
+
"@walletconnect/relay-api@npm:1.0.11":
version: 1.0.11
resolution: "@walletconnect/relay-api@npm:1.0.11"
@@ -24942,6 +24996,13 @@ __metadata:
languageName: node
linkType: hard
+"fast-base64-decode@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "fast-base64-decode@npm:1.0.0"
+ checksum: 10/4c59eb1775a7f132333f296c5082476fdcc8f58d023c42ed6d378d2e2da4c328c7a71562f271181a725dd17cdaa8f2805346cc330cdbad3b8e4b9751508bd0a3
+ languageName: node
+ linkType: hard
+
"fast-copy@npm:^3.0.2":
version: 3.0.2
resolution: "fast-copy@npm:3.0.2"
@@ -25032,6 +25093,13 @@ __metadata:
languageName: node
linkType: hard
+"fast-text-encoding@npm:1.0.6, fast-text-encoding@npm:^1.0.6":
+ version: 1.0.6
+ resolution: "fast-text-encoding@npm:1.0.6"
+ checksum: 10/f7b9e2e7a21e4ae5f4b8d3729850be83fb45052b28c9c38c09b8366463a291d6dc5448359238bdaf87f6a9e907d5895a94319a2c5e0e9f0786859ad6312d1d06
+ languageName: node
+ linkType: hard
+
"fast-uri@npm:^3.0.1":
version: 3.0.1
resolution: "fast-uri@npm:3.0.1"
@@ -32211,6 +32279,15 @@ __metadata:
languageName: node
linkType: hard
+"merge-options@npm:^3.0.4":
+ version: 3.0.4
+ resolution: "merge-options@npm:3.0.4"
+ dependencies:
+ is-plain-obj: "npm:^2.1.0"
+ checksum: 10/d86ddb3dd6e85d558dbf25dc944f3527b6bacb944db3fdda6e84a3f59c4e4b85231095f58b835758b9a57708342dee0f8de0dffa352974a48221487fe9f4584f
+ languageName: node
+ linkType: hard
+
"merge-source-map@npm:1.0.4":
version: 1.0.4
resolution: "merge-source-map@npm:1.0.4"
@@ -37855,6 +37932,17 @@ __metadata:
languageName: node
linkType: hard
+"react-native-get-random-values@npm:^1.11.0":
+ version: 1.11.0
+ resolution: "react-native-get-random-values@npm:1.11.0"
+ dependencies:
+ fast-base64-decode: "npm:^1.0.0"
+ peerDependencies:
+ react-native: ">=0.56"
+ checksum: 10/eb04833ce2b66309d737f1447ab01ad32aca00a8d1cc4de7b4e751c23f4d9f8059a2643bb16e0b6f3e6b074a9e57e769bb2bf2afc50a912c5661d80a6ce4de34
+ languageName: node
+ linkType: hard
+
"react-native-iphone-x-helper@npm:^1.0.3":
version: 1.3.1
resolution: "react-native-iphone-x-helper@npm:1.3.1"
@@ -37984,6 +38072,17 @@ __metadata:
languageName: node
linkType: hard
+"react-native-url-polyfill@npm:2.0.0":
+ version: 2.0.0
+ resolution: "react-native-url-polyfill@npm:2.0.0"
+ dependencies:
+ whatwg-url-without-unicode: "npm:8.0.0-3"
+ peerDependencies:
+ react-native: "*"
+ checksum: 10/6a8d605eeb1b0ee9b0f47f1866acc2edfa2131a4a8fb1ea3839ceb507e225b894ed66f49a3bd826fc964f2c8005b3678c9d3b65d07eb0a3b979be830cb618686
+ languageName: node
+ linkType: hard
+
"react-native@npm:0.76.1":
version: 0.76.1
resolution: "react-native@npm:0.76.1"