feat (ldk): add VSS server step to wallet recovery

This commit is contained in:
Shubham Kumar
2026-07-13 11:24:16 +05:30
parent 268bfb32c1
commit 6fbf3a2497
4 changed files with 203 additions and 14 deletions
+8 -1
View File
@@ -226,7 +226,8 @@ import EditFee from './views/EditFee';
// Embedded LND/LDK
import Seed from './views/Settings/Seed';
import SeedRecovery from './views/Settings/SeedRecovery';
import LdkWalletRecoverySettings from './views/Settings/LdkWalletRecoverySettings';
import LdkWalletRecoverySettings from './views/Settings/LdkRecovery/LdkWalletRecoverySettings';
import LdkRecoveryVssServer from './views/Settings/LdkRecovery/LdkRecoveryVssServer';
import SeedQRExport from './views/Settings/SeedQRExport';
import Sync from './views/Sync';
import SyncRecovery from './views/SyncRecovery';
@@ -1092,6 +1093,12 @@ export default class App extends React.PureComponent {
LdkWalletRecoverySettings
}
/>
<Stack.Screen
name="LdkRecoveryVssServer" // @ts-ignore:next-line
component={
LdkRecoveryVssServer
}
/>
<Stack.Screen
name="SeedQRExport" // @ts-ignore:next-line
component={
@@ -0,0 +1,180 @@
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { Route } from '@react-navigation/native';
import Button from '../../../components/Button';
import DropdownSetting from '../../../components/DropdownSetting';
import Header from '../../../components/Header';
import Screen from '../../../components/Screen';
import Text from '../../../components/Text';
import TextInput from '../../../components/TextInput';
import { LDK_VSS_SERVER_KEYS } from '../../../stores/SettingsStore';
import { themeColor } from '../../../utils/ThemeUtils';
import { localeString } from '../../../utils/LocaleUtils';
import { DEFAULT_VSS_SERVER } from '../../../utils/LdkNodeUtils';
import UrlUtils from '../../../utils/UrlUtils';
interface LdkRecoveryVssServerProps {
navigation: NativeStackNavigationProp<any, any>;
route: Route<
'LdkRecoveryVssServer',
{
network: string;
nickname?: string;
photo?: string;
wordCount: 12 | 24;
}
>;
}
interface LdkRecoveryVssServerState {
selectedValue: string;
customServer: string;
}
export default class LdkRecoveryVssServer extends React.Component<
LdkRecoveryVssServerProps,
LdkRecoveryVssServerState
> {
state = {
selectedValue: DEFAULT_VSS_SERVER,
customServer: ''
};
private getEffectiveServer = (): string => {
const { selectedValue, customServer } = this.state;
return selectedValue === 'custom' ? customServer.trim() : selectedValue;
};
private continueToRecovery = () => {
const { navigation, route } = this.props;
const { network, nickname, photo, wordCount } = route.params ?? {};
navigation.navigate('SeedRecovery', {
network,
implementation: 'ldk-node',
nickname,
photo,
wordCount,
vssServer: this.getEffectiveServer() || undefined
});
};
render() {
const { navigation } = this.props;
const { selectedValue, customServer } = this.state;
const customServerTrimmed = customServer.trim();
const isCustom = selectedValue === 'custom';
const showInvalidUrlError =
isCustom &&
customServerTrimmed !== '' &&
!UrlUtils.isValidUrl(customServer);
const disabled =
isCustom && (customServerTrimmed === '' || showInvalidUrlError);
return (
<Screen>
<Header
leftComponent="Back"
centerComponent={{
text: localeString(
'views.Settings.EmbeddedNode.VssServer.title'
),
style: {
color: themeColor('text'),
fontFamily: 'PPNeueMontreal-Book'
}
}}
navigation={navigation}
/>
<View style={styles.content}>
<Text
style={{
...styles.subtitle,
color: themeColor('secondaryText')
}}
>
{localeString(
'views.Settings.EmbeddedNode.VssServer.subtitle'
)}
</Text>
<DropdownSetting
title={localeString(
'views.Settings.EmbeddedNode.VssServer.serverUrl'
)}
selectedValue={selectedValue}
onValueChange={(value: string) => {
this.setState({
selectedValue: value,
customServer:
value === 'custom' ? customServer : ''
});
}}
values={LDK_VSS_SERVER_KEYS}
/>
{isCustom && (
<>
<TextInput
value={customServer}
placeholder={DEFAULT_VSS_SERVER}
onChangeText={(text: string) =>
this.setState({ customServer: text })
}
autoCapitalize="none"
autoCorrect={false}
/>
{showInvalidUrlError && (
<Text
style={{
...styles.error,
color: themeColor('error')
}}
>
{localeString(
'views.Settings.EmbeddedNode.invalidServerUrl'
)}
</Text>
)}
</>
)}
<View style={styles.button}>
<Button
title={localeString('general.next')}
onPress={this.continueToRecovery}
disabled={disabled}
/>
</View>
</View>
</Screen>
);
}
}
const styles = StyleSheet.create({
content: {
flex: 1,
paddingHorizontal: 20,
paddingTop: 20
},
subtitle: {
fontFamily: 'PPNeueMontreal-Book',
fontSize: 15,
marginBottom: 24
},
error: {
fontFamily: 'PPNeueMontreal-Book',
fontSize: 12,
marginTop: 4
},
button: {
marginTop: 24
}
});
@@ -3,13 +3,13 @@ import { View, StyleSheet } from 'react-native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { Route } from '@react-navigation/native';
import Button from '../../components/Button';
import Header from '../../components/Header';
import Screen from '../../components/Screen';
import Text from '../../components/Text';
import Button from '../../../components/Button';
import Header from '../../../components/Header';
import Screen from '../../../components/Screen';
import Text from '../../../components/Text';
import { themeColor } from '../../utils/ThemeUtils';
import { localeString } from '../../utils/LocaleUtils';
import { themeColor } from '../../../utils/ThemeUtils';
import { localeString } from '../../../utils/LocaleUtils';
interface LdkWalletRecoverySettingsProps {
navigation: NativeStackNavigationProp<any, any>;
@@ -27,13 +27,12 @@ export default class LdkWalletRecoverySettings extends React.Component<
LdkWalletRecoverySettingsProps,
{}
> {
private continueToRecovery = (wordCount: 12 | 24) => {
private continueToVssServer = (wordCount: 12 | 24) => {
const { navigation, route } = this.props;
const { network, nickname, photo } = route.params ?? {};
navigation.navigate('SeedRecovery', {
navigation.navigate('LdkRecoveryVssServer', {
network,
implementation: 'ldk-node',
nickname,
photo,
wordCount
@@ -85,7 +84,7 @@ export default class LdkWalletRecoverySettings extends React.Component<
title={localeString(
'views.Settings.WalletConfiguration.seedPhraseLength.12'
)}
onPress={() => this.continueToRecovery(12)}
onPress={() => this.continueToVssServer(12)}
/>
</View>
<View style={styles.button}>
@@ -93,7 +92,7 @@ export default class LdkWalletRecoverySettings extends React.Component<
title={localeString(
'views.Settings.WalletConfiguration.seedPhraseLength.24'
)}
onPress={() => this.continueToRecovery(24)}
onPress={() => this.continueToVssServer(24)}
secondary
/>
</View>
+5 -2
View File
@@ -102,6 +102,7 @@ interface SeedRecoveryProps {
photo?: string;
isSqlite?: boolean;
wordCount?: 12 | 24;
vssServer?: string;
}
>;
}
@@ -467,7 +468,7 @@ export default class SeedRecovery extends React.PureComponent<
ldkPassphrase,
ldkEsploraServer: getDefaultEsploraServer(networkType),
ldkRgsServer: getDefaultRgsServer(networkType),
ldkVssServer: DEFAULT_VSS_SERVER
ldkVssServer: route.params?.vssServer || DEFAULT_VSS_SERVER
};
let nodes: any;
@@ -808,7 +809,9 @@ export default class SeedRecovery extends React.PureComponent<
scorerUrl: DEFAULT_SCORER_URL,
lsps1Config,
trustedPeers0conf: trustedPeers,
vssServerUrl: DEFAULT_VSS_SERVER
vssServerUrl:
this.props.route.params?.vssServer ||
DEFAULT_VSS_SERVER
});
// Node is already built — tell Wallet.tsx to skip re-init