Skip to content
Draft
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
3 changes: 3 additions & 0 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import ShareModal from './components/Modals/ShareModal';
import NewChannelModal from './components/Modals/NewChannelModal';
import GraphSyncPromptModal from './components/Modals/GraphSyncPromptModal';
import NWCPendingPaymentsModal from './components/Modals/NWCPendingPaymentsModal';
import RestoreChannelModal from './components/Modals/RestoreChannelModal';

// Views
import Transaction from './views/Transaction';
Expand Down Expand Up @@ -1381,6 +1382,8 @@ export default class App extends React.PureComponent {
<NWCPendingPaymentsModal />
{/* @ts-ignore:next-line */}
<InfoModal />
{/* @ts-ignore:next-line */}
<RestoreChannelModal />
</GestureHandlerRootView>
</PushNotificationManager>
</AppContainer>
Expand Down
140 changes: 140 additions & 0 deletions components/Modals/RestoreChannelModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { inject, observer } from 'mobx-react';

import Text from '../../components/Text';
import Button from '../../components/Button';
import ModalBox from '../ModalBox';

import { localeString } from '../../utils/LocaleUtils';
import { themeColor } from '../../utils/ThemeUtils';
import { font } from '../../utils/FontUtils';

import ModalStore from '../../stores/ModalStore';

interface ChannelBackupModalProps {
ModalStore?: ModalStore;
}

@inject('ModalStore')
@observer
export default class ChannelBackupModal extends React.Component<ChannelBackupModalProps> {
render() {
const { ModalStore } = this.props;
const {
showRestoreChannelModal,
toggleRestoreChannelModal,
onCheckOlympus,
onImportFile,
onContinueWithoutBackup,
onCancelBackupModal
} = ModalStore!;

return (
<ModalBox
isOpen={showRestoreChannelModal}
style={{
backgroundColor: themeColor('background'),
borderRadius: 24,
height: 480,
width: '90%'
}}
onClosed={() => toggleRestoreChannelModal({ show: false })}
swipeToClose={false}
backButtonClose={true}
backdropPressToClose={false}
backdrop={true}
position="center"
>
<View style={styles.container}>
<Text
style={{
...styles.title,
fontFamily: font('marlideBold'),
color: themeColor('text')
}}
>
{localeString('views.Tools.migration.import')}
</Text>

<Text
style={{
...styles.description,
color: themeColor('text')
}}
>
{`${localeString(
'views.Tools.migration.import.message1'
)}\n\n${localeString(
'views.Tools.migration.import.message2'
)}`}
</Text>

<Button
title={localeString(
'views.Tools.migration.import.olympus'
)}
onPress={() => {
if (onCheckOlympus) onCheckOlympus();
toggleRestoreChannelModal({ show: false });
}}
containerStyle={{ marginBottom: 16 }}
/>

<Button
title={localeString(
'views.Tools.migration.import.local'
)}
onPress={() => {
if (onImportFile) onImportFile();
toggleRestoreChannelModal({ show: false });
}}
containerStyle={{ marginBottom: 16 }}
/>

<Button
title={localeString(
'views.Tools.migration.import.noBackup'
)}
onPress={() => {
if (onContinueWithoutBackup)
onContinueWithoutBackup();
toggleRestoreChannelModal({ show: false });
}}
containerStyle={{ marginBottom: 16 }}
warning
/>

<Button
title={localeString('general.cancel')}
onPress={() => {
if (onCancelBackupModal) onCancelBackupModal();
toggleRestoreChannelModal({ show: false });
}}
secondary
/>
</View>
</ModalBox>
);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
alignItems: 'center',
justifyContent: 'center'
},
title: {
fontSize: 32,
marginBottom: 12,
textAlign: 'center'
},
description: {
fontFamily: 'PPNeueMontreal-Book',
fontSize: 18,
marginBottom: 28,
textAlign: 'left'
}
});
33 changes: 32 additions & 1 deletion locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,16 @@
"views.Wallet.BalancePane.backup.text": "Create a backup to never lose access to your bitcoin.",
"views.Wallet.BalancePane.backup.action": "Start backup ->",
"views.Wallet.BalancePane.goToWalletConfig": "Go to Wallet config",
"views.Wallet.BalancePane.migration.title": "Your wallet is locked",
"views.Wallet.BalancePane.migration.text1": "This wallet is in channel migration state. Access is restricted to protect your funds.",
"views.Wallet.BalancePane.migration.text2": "Please delete this wallet and restore it on a different device using your 24-word seed phrase and the exported channel backup file to restore your channels.",
"views.Wallet.BalancePane.migration.action.unlock": "I don't want to migrate",
"views.Wallet.BalancePane.migration.alert.title": "Cancel Migration?",
"views.Wallet.BalancePane.migration.alert.text1": "DANGER: Only proceed if you have NOT imported your channel backup on another device.",
"views.Wallet.BalancePane.migration.alert.text2": "Using the same channels on two devices simultaneously will result in FORCE CLOSURE OF YOUR CHANNELS.",
"views.Wallet.BalancePane.migration.alert.text3": "Are you sure you want to unlock this wallet?",
"views.Wallet.BalancePane.migration.alert.cancel": "Keep Locked",
"views.Wallet.BalancePane.migration.alert.confirm": "Unlock Wallet",
"views.Wallet.Channels.local": "Local",
"views.Wallet.Channels.remote": "Remote",
"views.Wallet.Channels.noChannels": "No Channels",
Expand Down Expand Up @@ -900,6 +910,27 @@
"views.Tools.watchtowers.numSessions": "Number of Sessions",
"views.Tools.watchtowers.serverPubkey": "Server pubkey",
"views.Tools.watchtowers.clientNotActive": "Watchtower client is not active. Please restart your LND node with the --wtclient.active flag to enable watchtower functionality.",
"views.Tools.migration.export": "Export Channels to other device",
"views.Tools.migration.import": "Restore Channels",
"views.Tools.migration.export.title": "Export Channels Backup",
"views.Tools.migration.export.text1": "This will export your active channel database. You can use this file to restore your channels on a different device.",
"views.Tools.migration.export.text2": "WARNING: After exporting, this wallet will be locked, as running the same wallet on multiple devices will force close the existing channels.",
"views.Tools.migration.databaseNotFound": "Could not find channel database.",
"views.Tools.migration.export.confirm": "Export",
"views.Tools.migration.export.success": "Backup Successful",
"views.Tools.migration.import.success": "Import Successful",
"views.Tools.migration.export.success.text": "Your channel database has been exported. Please restart the app to apply the configuration and lock the wallet.",
"views.Tools.migration.import.success.text1": "Your channel database has been restored. Please restart the app to initialize your channels.",
"views.Tools.migration.import.success.text2": "Please note: It may take several minutes for your channels to sync and come back online.",
"views.Tools.migration.import.message1": "Do you have a channel database backup from your old device?",
"views.Tools.migration.import.message2": "If you don't have a channel backup, ZEUS will attempt to force close your channels so that you can restore existing funds on-chain.",
"views.Tools.migration.import.skip": "No, Skip",
"views.Tools.migration.import.olympus": "Check Olympus for backup",
"views.Tools.migration.import.local": "Import backup from local file",
"views.Tools.migration.import.noBackup": "Continue without backup",
"views.Tools.migration.import.invalidExtension": "Invalid file type. Please select a .sqlite or .db file.",
"views.Tools.migration.import.emptyFile": "The selected file is empty.",
"views.Tools.migration.import.fileNotFound": "Could not read the selected file.",
"views.WithdrawalRedemption.redeeming": "Redeeming withdrawal request",
"views.WithdrawalRedemption.success": "Withdrawal request redemption successful",
"views.Tools.ErrorCreateWithdrawalRequest": "Error creating withdrawal request",
Expand Down Expand Up @@ -2059,4 +2090,4 @@
"backends.NWC.permissionDenied": "Permission denied for this operation",
"androidNotification.nwcRunningBackground": "Nostr Wallet Connect is running in the background",
"androidNotification.nwcShutdown": "Stop Service"
}
}
30 changes: 30 additions & 0 deletions stores/ModalStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default class ModalStore {
@observable public showShareModal: boolean = false;
@observable public showNewChannelModal: boolean = false;
@observable public showNWCPendingPaymentsModal: boolean = false;
@observable public showRestoreChannelModal: boolean = false;
@observable public nwcPendingPaymentsData?: {
pendingEvents: any[];
totalAmount: number;
Expand All @@ -29,6 +30,11 @@ export default class ModalStore {
@observable public onShareGiftLink?: () => void;
@observable public onPress: () => void;

@observable public onCheckOlympus?: () => void;
@observable public onImportFile?: () => void;
@observable public onContinueWithoutBackup?: () => void;
@observable public onCancelBackupModal?: () => void;

/* External Link Modal */
@action
public toggleExternalLinkModal = (status: boolean) => {
Expand Down Expand Up @@ -128,6 +134,30 @@ export default class ModalStore {
this.showAndroidNfcModal = status;
};

/* Channel Backup Modal */
@action
public toggleRestoreChannelModal = (params?: {
show: boolean;
onCheckOlympus?: () => void;
onImportFile?: () => void;
onContinueWithoutBackup?: () => void;
onCancel?: () => void;
}) => {
if (!params || !params.show) {
this.showRestoreChannelModal = false;
this.onCheckOlympus = undefined;
this.onImportFile = undefined;
this.onContinueWithoutBackup = undefined;
this.onCancelBackupModal = undefined;
} else {
this.showRestoreChannelModal = true;
this.onCheckOlympus = params.onCheckOlympus;
this.onImportFile = params.onImportFile;
this.onContinueWithoutBackup = params.onContinueWithoutBackup;
this.onCancelBackupModal = params.onCancel;
}
};

@action
public closeVisibleModalDialog = () => {
if (this.showExternalLinkModal) {
Expand Down
5 changes: 5 additions & 0 deletions stores/SettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,7 @@ export default class SettingsStore {
@observable public initialStart: boolean = true;
@observable public embeddedLndStarted: boolean = false;
@observable public lndFolderMissing: boolean = false;
@observable public isChannelMigrating: boolean = false;
// NWC
@observable public nostrWalletConnectUrl: string;

Expand All @@ -1547,6 +1548,10 @@ export default class SettingsStore {
this.lndFolderMissing = status;
};

public setChannelMigrating = (status: boolean) => {
this.isChannelMigrating = status;
};

public fetchBTCPayConfig = (data: string) => {
const configRoute = data.split('config=')[1];
this.btcPayError = null;
Expand Down
Loading