Cleanup onboarding screen

This commit is contained in:
pokkst 2023-05-13 02:28:47 -05:00
parent 430874a715
commit 991a806748
No known key found for this signature in database
GPG key ID: 90C2ED85E67A50FF
3 changed files with 204 additions and 165 deletions

View file

@ -1,5 +1,6 @@
package net.mynero.wallet.fragment.onboarding; package net.mynero.wallet.fragment.onboarding;
import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -85,6 +86,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
private TextView moreOptionsDropdownTextView; private TextView moreOptionsDropdownTextView;
private SwitchCompat torSwitch; private SwitchCompat torSwitch;
private ConstraintLayout proxySettingsLayout; private ConstraintLayout proxySettingsLayout;
private ConstraintLayout advancedOptionsLayout;
private ImageView moreOptionsChevronImageView; private ImageView moreOptionsChevronImageView;
private CheckBox seedOffsetCheckbox; private CheckBox seedOffsetCheckbox;
private Button selectNodeButton; private Button selectNodeButton;
@ -113,6 +115,7 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext); walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext);
walletProxyPortEditText = view.findViewById(R.id.wallet_proxy_port_edittext); walletProxyPortEditText = view.findViewById(R.id.wallet_proxy_port_edittext);
seedOffsetCheckbox.setChecked(useOffset); seedOffsetCheckbox.setChecked(useOffset);
advancedOptionsLayout = view.findViewById(R.id.more_options_layout);
bindListeners(); bindListeners();
bindObservers(); bindObservers();
@ -122,14 +125,16 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
mViewModel.showMoreOptions.observe(getViewLifecycleOwner(), show -> { mViewModel.showMoreOptions.observe(getViewLifecycleOwner(), show -> {
if (show) { if (show) {
moreOptionsChevronImageView.setImageResource(R.drawable.ic_keyboard_arrow_up); moreOptionsChevronImageView.setImageResource(R.drawable.ic_keyboard_arrow_up);
walletSeedEditText.setVisibility(View.VISIBLE); advancedOptionsLayout.setVisibility(View.VISIBLE);
walletRestoreHeightEditText.setVisibility(View.VISIBLE);
} else { } else {
moreOptionsChevronImageView.setImageResource(R.drawable.ic_keyboard_arrow_down); moreOptionsChevronImageView.setImageResource(R.drawable.ic_keyboard_arrow_down);
walletSeedEditText.setVisibility(View.GONE); advancedOptionsLayout.setVisibility(View.GONE);
walletRestoreHeightEditText.setVisibility(View.GONE);
} }
}); });
mViewModel.enableCreateButton.observe(getViewLifecycleOwner(), enable -> {
createWalletButton.setEnabled(enable);
});
} }
private void bindListeners() { private void bindListeners() {
@ -230,47 +235,9 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
} }
private void createOrImportWallet(String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText) { private void createOrImportWallet(String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText) {
String offset = useOffset ? walletPassword : ""; Activity activity = getActivity();
MainActivity mainActivity = (MainActivity) getActivity(); if(activity != null) {
if (mainActivity != null) { mViewModel.createOrImportWallet(activity, walletPassword, confirmedPassword, walletSeed, restoreHeightText, useOffset);
if (!walletPassword.isEmpty()) {
if(!walletPassword.equals(confirmedPassword)) {
mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, getString(R.string.invalid_confirmed_password), Toast.LENGTH_SHORT).show());
return;
}
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_PASSWORD, true).apply();
}
long restoreHeight = getNewRestoreHeight();
File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME);
Wallet wallet = null;
if(!offset.isEmpty()) {
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_OFFSET, true).apply();
}
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(""), offset, restoreHeight);
} else {
if (!checkMnemonic(walletSeed)) {
mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, getString(R.string.invalid_mnemonic_code), Toast.LENGTH_SHORT).show());
return;
}
if (!restoreHeightText.isEmpty()) {
restoreHeight = Long.parseLong(restoreHeightText);
}
wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, walletSeed, offset, restoreHeight);
}
Wallet.Status walletStatus = wallet.getStatus();
wallet.close();
boolean ok = walletStatus.isOk();
walletFile.delete(); // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too.
if (ok) {
mainActivity.init(walletFile, walletPassword);
mainActivity.runOnUiThread(mainActivity::onBackPressed);
} else {
mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, getString(R.string.create_wallet_failed, walletStatus.getErrorString()), Toast.LENGTH_SHORT).show());
}
} }
} }
@ -294,21 +261,6 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS
} }
} }
private long getNewRestoreHeight() {
Calendar restoreDate = Calendar.getInstance();
restoreDate.add(Calendar.DAY_OF_MONTH, 0);
return RestoreHeight.getInstance().getHeight(restoreDate.getTime());
}
private Wallet createTempWallet(String dir) {
File tmpWalletFile = new File(dir, Constants.WALLET_NAME + "_tmp");
return WalletManager.getInstance().createWallet(tmpWalletFile, "", Constants.MNEMONIC_LANGUAGE, 0);
}
private boolean checkMnemonic(String seed) {
return (seed.split("\\s").length == 25);
}
@Override @Override
public void onNodeSelected() { public void onNodeSelected() {
Node node = PrefService.getInstance().getNode(); Node node = PrefService.getInstance().getNode();

View file

@ -1,20 +1,30 @@
package net.mynero.wallet.fragment.onboarding; package net.mynero.wallet.fragment.onboarding;
import android.app.Activity;
import android.util.Patterns; import android.util.Patterns;
import android.widget.Toast;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
import net.mynero.wallet.MainActivity;
import net.mynero.wallet.MoneroApplication; import net.mynero.wallet.MoneroApplication;
import net.mynero.wallet.data.DefaultNodes; import net.mynero.wallet.R;
import net.mynero.wallet.model.Wallet;
import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.model.WalletManager;
import net.mynero.wallet.service.PrefService; import net.mynero.wallet.service.PrefService;
import net.mynero.wallet.util.Constants; import net.mynero.wallet.util.Constants;
import net.mynero.wallet.util.RestoreHeight;
import java.io.File;
import java.util.Calendar;
public class OnboardingViewModel extends ViewModel { public class OnboardingViewModel extends ViewModel {
private final MutableLiveData<Boolean> _showMoreOptions = new MutableLiveData<>(false); private final MutableLiveData<Boolean> _showMoreOptions = new MutableLiveData<>(false);
public LiveData<Boolean> showMoreOptions = _showMoreOptions; public LiveData<Boolean> showMoreOptions = _showMoreOptions;
private final MutableLiveData<Boolean> _enableCreateButton = new MutableLiveData<>(true);
public LiveData<Boolean> enableCreateButton = _enableCreateButton;
private String proxyAddress = ""; private String proxyAddress = "";
private String proxyPort = ""; private String proxyPort = "";
@ -51,4 +61,70 @@ public class OnboardingViewModel extends ViewModel {
public void setProxyPort(String port) { public void setProxyPort(String port) {
this.proxyPort = port; this.proxyPort = port;
} }
public void createOrImportWallet(Activity mainActivity, String walletPassword, String confirmedPassword, String walletSeed, String restoreHeightText, boolean useOffset) {
MoneroApplication application = (MoneroApplication)mainActivity.getApplication();
application.getExecutor().execute(() -> {
mainActivity.runOnUiThread(() -> {
_enableCreateButton.setValue(false);
});
String offset = useOffset ? walletPassword : "";
if (!walletPassword.isEmpty()) {
if(!walletPassword.equals(confirmedPassword)) {
mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, application.getString(R.string.invalid_confirmed_password), Toast.LENGTH_SHORT).show());
return;
}
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_PASSWORD, true).apply();
}
long restoreHeight = getNewRestoreHeight();
File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME);
Wallet wallet = null;
if(!offset.isEmpty()) {
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_OFFSET, true).apply();
}
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(""), offset, restoreHeight);
} else {
if (!checkMnemonic(walletSeed)) {
mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, application.getString(R.string.invalid_mnemonic_code), Toast.LENGTH_SHORT).show());
return;
}
if (!restoreHeightText.isEmpty()) {
restoreHeight = Long.parseLong(restoreHeightText);
}
wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, walletSeed, offset, restoreHeight);
}
Wallet.Status walletStatus = wallet.getStatus();
wallet.close();
boolean ok = walletStatus.isOk();
walletFile.delete(); // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too.
if (ok) {
((MainActivity)mainActivity).init(walletFile, walletPassword);
mainActivity.runOnUiThread(mainActivity::onBackPressed);
} else {
mainActivity.runOnUiThread(() -> {
_enableCreateButton.setValue(true);
Toast.makeText(mainActivity, application.getString(R.string.create_wallet_failed, walletStatus.getErrorString()), Toast.LENGTH_SHORT).show();
});
}
});
}
private long getNewRestoreHeight() {
Calendar restoreDate = Calendar.getInstance();
restoreDate.add(Calendar.DAY_OF_MONTH, 0);
return RestoreHeight.getInstance().getHeight(restoreDate.getTime());
}
private Wallet createTempWallet(String dir) {
File tmpWalletFile = new File(dir, Constants.WALLET_NAME + "_tmp");
return WalletManager.getInstance().createWallet(tmpWalletFile, "", Constants.MNEMONIC_LANGUAGE, 0);
}
private boolean checkMnemonic(String seed) {
return (seed.split("\\s").length == 25);
}
} }

View file

@ -17,32 +17,15 @@
android:id="@+id/create_wallet_textview" android:id="@+id/create_wallet_textview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="32dp" android:layout_marginBottom="16dp"
android:text="@string/create_wallet" android:text="@string/create_wallet"
android:textSize="32sp" android:textSize="32sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/select_node_button" app:layout_constraintBottom_toTopOf="@id/wallet_password_edittext"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/select_node_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
tools:text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
android:background="@drawable/button_bg"
android:ellipsize="middle"
android:singleLine="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/create_wallet_textview"
tools:ignore="SpeakableTextPresentCheck" />
<EditText <EditText
android:id="@+id/wallet_password_edittext" android:id="@+id/wallet_password_edittext"
android:layout_width="0dp" android:layout_width="0dp"
@ -50,11 +33,11 @@
android:background="@drawable/edittext_bg" android:background="@drawable/edittext_bg"
android:hint="@string/password_optional" android:hint="@string/password_optional"
android:inputType="textPassword" android:inputType="textPassword"
android:layout_marginTop="16dp" android:minHeight="48dp"
app:layout_constraintBottom_toTopOf="@id/wallet_password_confirm_edittext" app:layout_constraintBottom_toTopOf="@id/wallet_password_confirm_edittext"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/select_node_button" app:layout_constraintTop_toBottomOf="@id/create_wallet_textview"
tools:visibility="visible" /> tools:visibility="visible" />
<EditText <EditText
@ -76,11 +59,89 @@
android:id="@+id/seed_offset_checkbox" android:id="@+id/seed_offset_checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:minHeight="48dp"
android:text="@string/use_password_as_seed_offset" android:text="@string/use_password_as_seed_offset"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_password_confirm_edittext"/> app:layout_constraintTop_toBottomOf="@id/wallet_password_confirm_edittext"/>
<TextView
android:id="@+id/advanced_settings_dropdown_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="@string/more_options"
android:textStyle="bold"
android:paddingTop="4dp"
android:paddingBottom="4dp"
app:layout_constraintBottom_toTopOf="@id/more_options_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/seed_offset_checkbox" />
<ImageView
android:id="@+id/advanced_settings_chevron_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="24dp"
android:minHeight="24dp"
android:src="@drawable/ic_keyboard_arrow_down"
app:layout_constraintBottom_toBottomOf="@id/advanced_settings_dropdown_textview"
app:layout_constraintStart_toEndOf="@id/advanced_settings_dropdown_textview"
app:layout_constraintTop_toTopOf="@id/advanced_settings_dropdown_textview" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/more_options_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/advanced_settings_dropdown_textview">
<Button
android:id="@+id/select_node_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
tools:text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
android:background="@drawable/button_bg"
android:ellipsize="middle"
android:singleLine="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="SpeakableTextPresentCheck" />
<EditText
android:id="@+id/wallet_seed_edittext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="32dp"
android:background="@drawable/edittext_bg"
android:hint="@string/recovery_phrase_optional"
android:minHeight="48dp"
app:layout_constraintBottom_toTopOf="@id/wallet_restore_height_edittext"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/select_node_button" />
<EditText
android:id="@+id/wallet_restore_height_edittext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/edittext_bg"
android:hint="@string/restore_height_optional"
android:inputType="number"
android:minHeight="48dp"
app:layout_constraintBottom_toTopOf="@id/tor_onboarding_switch"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_seed_edittext" />
<TextView <TextView
android:id="@+id/tor_onboarding_switch_label" android:id="@+id/tor_onboarding_switch_label"
android:layout_width="0dp" android:layout_width="0dp"
@ -97,8 +158,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="48dp" android:minHeight="48dp"
android:minWidth="48dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/seed_offset_checkbox" /> app:layout_constraintTop_toBottomOf="@id/wallet_restore_height_edittext" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/wallet_proxy_settings_layout" android:id="@+id/wallet_proxy_settings_layout"
@ -106,9 +169,10 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone" android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/tor_onboarding_switch" app:layout_constraintTop_toBottomOf="@id/tor_onboarding_switch"
app:layout_constraintBottom_toTopOf="@id/advanced_settings_dropdown_textview" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"> app:layout_constraintEnd_toEndOf="parent"
tools:visibility="visible">
<EditText <EditText
android:id="@+id/wallet_proxy_address_edittext" android:id="@+id/wallet_proxy_address_edittext"
android:layout_width="0dp" android:layout_width="0dp"
@ -117,6 +181,7 @@
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:background="@drawable/edittext_bg" android:background="@drawable/edittext_bg"
android:hint="@string/wallet_proxy_address_hint" android:hint="@string/wallet_proxy_address_hint"
android:minHeight="48dp"
app:layout_constraintBottom_toTopOf="@id/wallet_proxy_port_edittext" app:layout_constraintBottom_toTopOf="@id/wallet_proxy_port_edittext"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -129,67 +194,13 @@
android:background="@drawable/edittext_bg" android:background="@drawable/edittext_bg"
android:hint="@string/wallet_proxy_port_hint" android:hint="@string/wallet_proxy_port_hint"
android:inputType="number" android:inputType="number"
android:minHeight="48dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_proxy_address_edittext" /> app:layout_constraintTop_toBottomOf="@id/wallet_proxy_address_edittext" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/advanced_settings_dropdown_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="16dp"
android:text="@string/more_options"
android:textStyle="bold"
android:paddingTop="4dp"
android:paddingBottom="4dp"
app:layout_constraintBottom_toTopOf="@id/wallet_seed_edittext"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_proxy_settings_layout" />
<ImageView
android:id="@+id/advanced_settings_chevron_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="24dp"
android:minHeight="24dp"
android:src="@drawable/ic_keyboard_arrow_down"
app:layout_constraintBottom_toBottomOf="@id/advanced_settings_dropdown_textview"
app:layout_constraintStart_toEndOf="@id/advanced_settings_dropdown_textview"
app:layout_constraintTop_toTopOf="@id/advanced_settings_dropdown_textview" />
<EditText
android:id="@+id/wallet_seed_edittext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:background="@drawable/edittext_bg"
android:hint="@string/recovery_phrase_optional"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/wallet_restore_height_edittext"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/advanced_settings_dropdown_textview"
tools:visibility="visible" />
<EditText
android:id="@+id/wallet_restore_height_edittext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/edittext_bg"
android:hint="@string/restore_height_optional"
android:inputType="number"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/create_wallet_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_seed_edittext"
tools:visibility="visible" />
<Button <Button
android:id="@+id/create_wallet_button" android:id="@+id/create_wallet_button"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -199,5 +210,5 @@
android:text="@string/create_wallet" android:text="@string/create_wallet"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_restore_height_edittext" /> app:layout_constraintTop_toBottomOf="@id/more_options_layout" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>