Skip to content

Commit 439f112

Browse files
committed
feat(lightning): set max dust htlc exposure in dev settings
1 parent 0f8c6f8 commit 439f112

File tree

3 files changed

+145
-2
lines changed

3 files changed

+145
-2
lines changed

src/screens/Settings/DevSettings/LdkDebug.tsx

Lines changed: 133 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Clipboard from '@react-native-clipboard/clipboard';
22
import lm from '@synonymdev/react-native-ldk';
33
import React, { ReactElement, memo, useState } from 'react';
44
import { useTranslation } from 'react-i18next';
5-
import { ScrollView, StyleSheet } from 'react-native';
5+
import { ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native';
66
import RNFS from 'react-native-fs';
77
import Share from 'react-native-share';
88

@@ -13,17 +13,19 @@ import { useLightningBalance } from '../../../hooks/lightning';
1313
import { useAppDispatch, useAppSelector } from '../../../hooks/redux';
1414
import { useSheetRef } from '../../../sheets/SheetRefsProvider';
1515
import { openChannelsSelector } from '../../../store/reselect/lightning';
16+
import { settingsSelector } from '../../../store/reselect/settings';
1617
import {
1718
selectedNetworkSelector,
1819
selectedWalletSelector,
1920
} from '../../../store/reselect/wallet';
2021
import { removeLightningPeer } from '../../../store/slices/lightning';
22+
import { updateSettings } from '../../../store/slices/settings';
2123
import {
2224
createLightningInvoice,
2325
savePeer,
2426
} from '../../../store/utils/lightning';
2527
import { TextInput, View as ThemedView } from '../../../styles/components';
26-
import { Caption13Up } from '../../../styles/text';
28+
import { BodyM, Caption13Up } from '../../../styles/text';
2729
import {
2830
addPeer,
2931
getNodeId,
@@ -53,6 +55,15 @@ const LdkDebug = (): ReactElement => {
5355
const selectedWallet = useAppSelector(selectedWalletSelector);
5456
const selectedNetwork = useAppSelector(selectedNetworkSelector);
5557
const openChannels = useAppSelector(openChannelsSelector);
58+
const settings = useAppSelector(settingsSelector);
59+
60+
// Max Dust HTLC Exposure form state
61+
const [selectedType, setSelectedType] = useState<
62+
'fixed_limit' | 'fee_rate_multiplier' | null
63+
>(settings?.max_dust_htlc_exposure_type ?? null);
64+
const [exposureValue, setExposureValue] = useState<string>(
65+
settings?.max_dust_htlc_exposure?.toString() ?? '1000',
66+
);
5667

5768
const onNodeId = async (): Promise<void> => {
5869
const nodeId = await getNodeId();
@@ -435,6 +446,97 @@ const LdkDebug = (): ReactElement => {
435446
</>
436447
)}
437448

449+
<Caption13Up style={styles.sectionTitle} color="secondary">
450+
Max Dust HTLC Exposure
451+
</Caption13Up>
452+
453+
{/* Radio buttons for type selection */}
454+
<TouchableOpacity
455+
style={styles.radioOption}
456+
onPress={() =>
457+
setSelectedType(
458+
selectedType === 'fixed_limit' ? null : 'fixed_limit',
459+
)
460+
}>
461+
<View
462+
style={[
463+
styles.radioButton,
464+
selectedType === 'fixed_limit' && styles.radioButtonSelected,
465+
]}
466+
/>
467+
<BodyM style={styles.radioLabel}>Fixed Limit (sats)</BodyM>
468+
</TouchableOpacity>
469+
470+
<TouchableOpacity
471+
style={styles.radioOption}
472+
onPress={() =>
473+
setSelectedType(
474+
selectedType === 'fee_rate_multiplier'
475+
? null
476+
: 'fee_rate_multiplier',
477+
)
478+
}>
479+
<View
480+
style={[
481+
styles.radioButton,
482+
selectedType === 'fee_rate_multiplier' &&
483+
styles.radioButtonSelected,
484+
]}
485+
/>
486+
<BodyM style={styles.radioLabel}>Fee Rate Multiplier</BodyM>
487+
</TouchableOpacity>
488+
489+
{/* Number input - only show when a type is selected */}
490+
{selectedType && (
491+
<TextInput
492+
style={styles.textInput}
493+
value={exposureValue}
494+
onChangeText={setExposureValue}
495+
placeholder={selectedType === 'fixed_limit' ? '1000' : '10'}
496+
keyboardType="numeric"
497+
autoCapitalize="none"
498+
autoComplete="off"
499+
autoCorrect={false}
500+
/>
501+
)}
502+
503+
{/* Action buttons */}
504+
<View style={styles.buttonRow}>
505+
<Button
506+
style={[styles.button, styles.buttonHalf]}
507+
text="Set max dust"
508+
disabled={!selectedType || !exposureValue}
509+
onPress={(): void => {
510+
const numValue = Number.parseInt(exposureValue, 10);
511+
if (!Number.isNaN(numValue) && selectedType) {
512+
dispatch(
513+
updateSettings({
514+
max_dust_htlc_exposure_type: selectedType,
515+
max_dust_htlc_exposure: numValue,
516+
}),
517+
);
518+
}
519+
}}
520+
/>
521+
{(settings?.max_dust_htlc_exposure_type ||
522+
settings?.max_dust_htlc_exposure) && (
523+
<Button
524+
style={[styles.button, styles.buttonHalf]}
525+
text="Reset max dust"
526+
onPress={(): void => {
527+
setSelectedType(null);
528+
setExposureValue('1000');
529+
dispatch(
530+
updateSettings({
531+
max_dust_htlc_exposure_type: undefined,
532+
max_dust_htlc_exposure: undefined,
533+
}),
534+
);
535+
}}
536+
/>
537+
)}
538+
</View>
539+
438540
<SafeAreaInset type="bottom" minPadding={16} />
439541
</ScrollView>
440542
</ThemedView>
@@ -467,6 +569,35 @@ const styles = StyleSheet.create({
467569
button: {
468570
marginTop: 8,
469571
},
572+
radioOption: {
573+
flexDirection: 'row',
574+
alignItems: 'center',
575+
marginTop: 12,
576+
},
577+
radioButton: {
578+
width: 20,
579+
height: 20,
580+
borderRadius: 10,
581+
borderWidth: 2,
582+
borderColor: '#666',
583+
marginRight: 12,
584+
},
585+
radioButtonSelected: {
586+
borderColor: '#FF6600',
587+
backgroundColor: '#FF6600',
588+
},
589+
radioLabel: {
590+
flex: 1,
591+
},
592+
buttonRow: {
593+
flexDirection: 'row',
594+
marginTop: 16,
595+
gap: 8,
596+
},
597+
buttonHalf: {
598+
flex: 1,
599+
marginTop: 0,
600+
},
470601
});
471602

472603
export default memo(LdkDebug);

src/store/slices/settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export type TSettings = {
5151
transferIntroSeen: boolean;
5252
spendingIntroSeen: boolean;
5353
savingsIntroSeen: boolean;
54+
max_dust_htlc_exposure_type?: 'fixed_limit' | 'fee_rate_multiplier';
55+
max_dust_htlc_exposure?: number;
5456
};
5557

5658
export const settingsSlice = createSlice({

src/utils/lightning/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,16 @@ export const setupLdk = async ({
483483
negotiate_anchors_zero_fee_htlc_tx: true,
484484
},
485485
manually_accept_inbound_channels: true,
486+
channel_config: {
487+
...defaultUserConfig.channel_config,
488+
...(getStore().settings.max_dust_htlc_exposure_type && {
489+
max_dust_htlc_exposure_type:
490+
getStore().settings.max_dust_htlc_exposure_type,
491+
}),
492+
...(getStore().settings.max_dust_htlc_exposure && {
493+
max_dust_htlc_exposure: getStore().settings.max_dust_htlc_exposure,
494+
}),
495+
},
486496
},
487497
rapidGossipSyncUrl,
488498
skipParamCheck: true, //Switch off for debugging LDK networking issues

0 commit comments

Comments
 (0)