diff --git a/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java b/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java index 50c3364..3576ba1 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java +++ b/app/src/main/java/net/mynero/wallet/fragment/dialog/WalletKeysBottomSheetDialog.java @@ -15,9 +15,12 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import net.mynero.wallet.R; import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.WalletManager; +import net.mynero.wallet.service.PrefService; +import net.mynero.wallet.util.Constants; import net.mynero.wallet.util.Helper; public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment { + public String password = ""; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -34,6 +37,11 @@ public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment { Wallet wallet = WalletManager.getInstance().getWallet(); String seed = wallet.getSeed(""); + boolean usesOffset = PrefService.getInstance().getBoolean(Constants.PREF_USES_OFFSET, false); + if(usesOffset) { + seed = wallet.getSeed(password); + view.findViewById(R.id.wallet_seed_offset_textview).setVisibility(View.VISIBLE); + } String privateViewKey = wallet.getSecretViewKey(); informationTextView.setText(seed); diff --git a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java index 382e63d..d4bcfdf 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java @@ -8,6 +8,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; @@ -23,18 +25,19 @@ import androidx.lifecycle.ViewModelProvider; import net.mynero.wallet.MainActivity; import net.mynero.wallet.MoneroApplication; import net.mynero.wallet.R; -import net.mynero.wallet.data.DefaultNodes; import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.service.PrefService; import net.mynero.wallet.util.Constants; import net.mynero.wallet.util.RestoreHeight; +import org.json.JSONObject; + import java.io.File; import java.util.Calendar; public class OnboardingFragment extends Fragment { - + private boolean useOffset = true; private OnboardingViewModel mViewModel; TextWatcher proxyAddressListener = new TextWatcher() { @Override @@ -91,12 +94,16 @@ public class OnboardingFragment extends Fragment { ImageView moreOptionsChevronImageView = view.findViewById(R.id.advanced_settings_chevron_imageview); SwitchCompat torSwitch = view.findViewById(R.id.tor_onboarding_switch); ConstraintLayout proxySettingsLayout = view.findViewById(R.id.wallet_proxy_settings_layout); + CheckBox seedOffsetCheckbox = view.findViewById(R.id.seed_offset_checkbox); walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext); walletProxyPortEditText = view.findViewById(R.id.wallet_proxy_port_edittext); + seedOffsetCheckbox.setChecked(useOffset); moreOptionsDropdownTextView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked()); moreOptionsChevronImageView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked()); + seedOffsetCheckbox.setOnCheckedChangeListener((compoundButton, b) -> useOffset = b); + createWalletButton.setOnClickListener(view1 -> { prepareDefaultNode(); ((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> { @@ -165,17 +172,18 @@ public class OnboardingFragment extends Fragment { } private void createOrImportWallet(String walletPassword, String walletSeed, String restoreHeightText) { + String offset = useOffset ? walletPassword : ""; MainActivity mainActivity = (MainActivity) getActivity(); if (mainActivity != null) { if (!walletPassword.isEmpty()) { PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_PASSWORD, true).apply(); } - long restoreHeight = -1; + long restoreHeight = getNewRestoreHeight(); File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME); Wallet wallet = null; if (walletSeed.isEmpty()) { Wallet tmpWallet = createTempWallet(mainActivity.getApplicationInfo().dataDir); //we do this to get seed, then recover wallet so we can use seed offset - wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, tmpWallet.getSeed(""), "", getNewRestoreHeight()); + wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, tmpWallet.getSeed(""), offset, restoreHeight); } else { if (!checkMnemonic(walletSeed)) { Toast.makeText(mainActivity, getString(R.string.invalid_mnemonic_code), Toast.LENGTH_SHORT).show(); @@ -184,7 +192,10 @@ public class OnboardingFragment extends Fragment { if (!restoreHeightText.isEmpty()) { restoreHeight = Long.parseLong(restoreHeightText); } - wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, walletSeed, "", restoreHeight); + if(!offset.isEmpty()) { + PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_OFFSET, true).apply(); + } + wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, walletSeed, offset, restoreHeight); } Wallet.Status walletStatus = wallet.getStatus(); wallet.close(); diff --git a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java index fbf066a..c32bfc7 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/settings/SettingsFragment.java @@ -156,7 +156,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia passwordDialog.listener = this; passwordDialog.show(getActivity().getSupportFragmentManager(), "password_dialog"); } else { - displaySeedDialog(); + displaySeedDialog(""); } }); @@ -183,14 +183,15 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia }); } - private void displaySeedDialog() { + private void displaySeedDialog(String password) { WalletKeysBottomSheetDialog informationDialog = new WalletKeysBottomSheetDialog(); + informationDialog.password = password; informationDialog.show(getActivity().getSupportFragmentManager(), "information_seed_dialog"); } @Override public void onPasswordSuccess(String password) { - displaySeedDialog(); + displaySeedDialog(password); } @Override diff --git a/app/src/main/java/net/mynero/wallet/util/Constants.java b/app/src/main/java/net/mynero/wallet/util/Constants.java index d93a815..2c285a1 100644 --- a/app/src/main/java/net/mynero/wallet/util/Constants.java +++ b/app/src/main/java/net/mynero/wallet/util/Constants.java @@ -9,6 +9,7 @@ public class Constants { public static final String PREF_PROXY = "pref_proxy"; public static final String PREF_NODE_2 = "pref_node_2"; public static final String PREF_CUSTOM_NODES = "pref_custom_nodes"; + public static final String PREF_USES_OFFSET = "pref_uses_offset"; public static final String URI_PREFIX = "monero:"; public static final String URI_ARG_AMOUNT = "tx_amount"; diff --git a/app/src/main/res/layout/fragment_onboarding.xml b/app/src/main/res/layout/fragment_onboarding.xml index a4246cf..65a8769 100644 --- a/app/src/main/res/layout/fragment_onboarding.xml +++ b/app/src/main/res/layout/fragment_onboarding.xml @@ -34,6 +34,14 @@ app:layout_constraintTop_toBottomOf="@id/create_wallet_textview" tools:visibility="visible" /> + + + app:layout_constraintTop_toBottomOf="@id/seed_offset_checkbox" /> + + + app:layout_constraintTop_toBottomOf="@id/wallet_seed_offset_textview" /> Edit Node Recovery phrase Anyone with your recovery phrase can spend ALL coins in this wallet! + Your wallet seed offset is the password you use to open the wallet. It will not be displayed here, but it is needed to fully restore this wallet. Private view-key Anyone with your private view-key can see all incoming transactions! Restore height Block Height + Use password as seed offset