From 0712efec784c5bcb711dc5974524839f7a988523 Mon Sep 17 00:00:00 2001 From: m2049r Date: Sun, 2 Jan 2022 20:50:07 +0100 Subject: [PATCH] allow seed offset generation & wallet restore (#804) --- app/build.gradle | 4 +- app/src/main/cpp/monerujo.cpp | 23 +- .../m2049r/xmrwallet/GenerateFragment.java | 26 ++- .../xmrwallet/GenerateReviewFragment.java | 209 +++++++++++++----- .../com/m2049r/xmrwallet/LoginActivity.java | 5 +- .../com/m2049r/xmrwallet/model/Wallet.java | 2 +- .../m2049r/xmrwallet/model/WalletManager.java | 14 +- .../res/drawable/ic_baseline_cancel_24.xml | 10 + .../ic_baseline_keyboard_arrow_down_24.xml | 10 + .../ic_baseline_keyboard_arrow_up_24.xml | 10 + app/src/main/res/layout/fragment_generate.xml | 44 +++- app/src/main/res/layout/fragment_review.xml | 58 +++-- app/src/main/res/values-cat/strings.xml | 5 +- app/src/main/res/values-de/strings.xml | 5 +- app/src/main/res/values-el/strings.xml | 5 +- app/src/main/res/values-eo/strings.xml | 5 +- app/src/main/res/values-es/strings.xml | 5 +- app/src/main/res/values-et/strings.xml | 5 +- app/src/main/res/values-fr/strings.xml | 5 +- app/src/main/res/values-hu/strings.xml | 5 +- app/src/main/res/values-it/strings.xml | 7 +- app/src/main/res/values-ja/strings.xml | 5 +- app/src/main/res/values-nb/strings.xml | 5 +- app/src/main/res/values-nl/strings.xml | 5 +- app/src/main/res/values-pt-rBR/strings.xml | 7 +- app/src/main/res/values-pt/strings.xml | 5 +- app/src/main/res/values-ro/strings.xml | 5 +- app/src/main/res/values-ru/strings.xml | 5 +- app/src/main/res/values-sk/strings.xml | 5 +- app/src/main/res/values-sr/strings.xml | 5 +- app/src/main/res/values-sv/strings.xml | 5 +- app/src/main/res/values-uk/strings.xml | 5 +- app/src/main/res/values-zh-rCN/strings.xml | 5 +- app/src/main/res/values-zh-rTW/strings.xml | 5 +- app/src/main/res/values/strings.xml | 5 +- 35 files changed, 412 insertions(+), 122 deletions(-) create mode 100644 app/src/main/res/drawable/ic_baseline_cancel_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_keyboard_arrow_down_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_keyboard_arrow_up_24.xml diff --git a/app/build.gradle b/app/build.gradle index cad4f198..4f5b7dee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.m2049r.xmrwallet" minSdkVersion 21 targetSdkVersion 30 - versionCode 1201 - versionName "2.2.1 'René'" + versionCode 1301 + versionName "2.3.1 'Doménikos'" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { diff --git a/app/src/main/cpp/monerujo.cpp b/app/src/main/cpp/monerujo.cpp index 64ee2e0c..a4e19284 100644 --- a/app/src/main/cpp/monerujo.cpp +++ b/app/src/main/cpp/monerujo.cpp @@ -229,7 +229,7 @@ std::vector java2cpp(JNIEnv *env, jobject arrayList) { return result; } -jobject cpp2java(JNIEnv *env, const std::vector& vector) { +jobject cpp2java(JNIEnv *env, const std::vector &vector) { jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "", "(I)V"); jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add", @@ -301,12 +301,13 @@ Java_com_m2049r_xmrwallet_model_WalletManager_openWalletJ(JNIEnv *env, jobject i JNIEXPORT jlong JNICALL Java_com_m2049r_xmrwallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobject instance, jstring path, jstring password, - jstring mnemonic, + jstring mnemonic, jstring offset, jint networkType, jlong restoreHeight) { const char *_path = env->GetStringUTFChars(path, nullptr); const char *_password = env->GetStringUTFChars(password, nullptr); const char *_mnemonic = env->GetStringUTFChars(mnemonic, nullptr); + const char *_offset = env->GetStringUTFChars(offset, nullptr); Monero::NetworkType _networkType = static_cast(networkType); Bitmonero::Wallet *wallet = @@ -315,11 +316,14 @@ Java_com_m2049r_xmrwallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobje std::string(_password), std::string(_mnemonic), _networkType, - (uint64_t) restoreHeight); + (uint64_t) restoreHeight, + 1, // kdf_rounds + std::string(_offset)); env->ReleaseStringUTFChars(path, _path); env->ReleaseStringUTFChars(password, _password); env->ReleaseStringUTFChars(mnemonic, _mnemonic); + env->ReleaseStringUTFChars(offset, _offset); return reinterpret_cast(wallet); } @@ -533,7 +537,7 @@ Java_com_m2049r_xmrwallet_model_WalletManager_resolveOpenAlias(JNIEnv *env, jobj JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_WalletManager_setProxy(JNIEnv *env, jobject instance, - jstring address) { + jstring address) { const char *_address = env->GetStringUTFChars(address, nullptr); bool rc = Bitmonero::WalletManagerFactory::getWalletManager()->setProxy(std::string(_address)); @@ -570,9 +574,12 @@ Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instan /**********************************/ JNIEXPORT jstring JNICALL -Java_com_m2049r_xmrwallet_model_Wallet_getSeed(JNIEnv *env, jobject instance) { +Java_com_m2049r_xmrwallet_model_Wallet_getSeed(JNIEnv *env, jobject instance, jstring seedOffset) { + const char *_seedOffset = env->GetStringUTFChars(seedOffset, nullptr); Bitmonero::Wallet *wallet = getHandle(env, instance); - return env->NewStringUTF(wallet->seed().c_str()); + jstring seed = env->NewStringUTF(wallet->seed(std::string(_seedOffset)).c_str()); + env->ReleaseStringUTFChars(seedOffset, _seedOffset); + return seed; } JNIEXPORT jstring JNICALL @@ -740,7 +747,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_getConnectionStatusJ(JNIEnv *env, jobject JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_Wallet_setProxy(JNIEnv *env, jobject instance, - jstring address) { + jstring address) { const char *_address = env->GetStringUTFChars(address, nullptr); Bitmonero::Wallet *wallet = getHandle(env, instance); bool rc = wallet->setProxy(std::string(_address)); @@ -1262,7 +1269,7 @@ jobject newTransactionInfo(JNIEnv *env, Bitmonero::TransactionInfo *info) { #include #include -jobject cpp2java(JNIEnv *env, const std::vector& vector) { +jobject cpp2java(JNIEnv *env, const std::vector &vector) { jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "", "(I)V"); jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add", diff --git a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java index 3048318d..42fe137b 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java @@ -81,6 +81,9 @@ public class GenerateFragment extends Fragment { private TextInputLayout etWalletRestoreHeight; private Button bGenerate; + private Button bSeedOffset; + private TextInputLayout etSeedOffset; + private String type = null; private void clearErrorOnTextEntry(final TextInputLayout textInputLayout) { @@ -118,6 +121,8 @@ public class GenerateFragment extends Fragment { etWalletSpendKey = view.findViewById(R.id.etWalletSpendKey); etWalletRestoreHeight = view.findViewById(R.id.etWalletRestoreHeight); bGenerate = view.findViewById(R.id.bGenerate); + bSeedOffset = view.findViewById(R.id.bSeedOffset); + etSeedOffset = view.findViewById(R.id.etSeedOffset); etWalletAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); etWalletViewKey.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); @@ -222,6 +227,8 @@ public class GenerateFragment extends Fragment { } return false; }); + bSeedOffset.setVisibility(View.VISIBLE); + bSeedOffset.setOnClickListener(v -> toggleSeedOffset()); break; case TYPE_KEY: case TYPE_VIEWONLY: @@ -288,6 +295,18 @@ public class GenerateFragment extends Fragment { return view; } + void toggleSeedOffset() { + if (etSeedOffset.getVisibility() == View.VISIBLE) { + etSeedOffset.getEditText().getText().clear(); + etSeedOffset.setVisibility(View.GONE); + bSeedOffset.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_keyboard_arrow_down_24, 0, 0, 0); + } else { + etSeedOffset.setVisibility(View.VISIBLE); + bSeedOffset.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_keyboard_arrow_up_24, 0, 0, 0); + etSeedOffset.requestFocusFromTouch(); + } + } + private boolean checkName() { String name = etWalletName.getEditText().getText().toString(); boolean ok = true; @@ -422,12 +441,13 @@ public class GenerateFragment extends Fragment { break; case TYPE_SEED: if (!checkMnemonic()) return; - String seed = etWalletMnemonic.getEditText().getText().toString(); + final String seed = etWalletMnemonic.getEditText().getText().toString(); bGenerate.setEnabled(false); if (fingerprintAuthAllowed) { KeyStoreHelper.saveWalletUserPass(requireActivity(), name, password); } - activityCallback.onGenerate(name, crazyPass, seed, height); + final String offset = etSeedOffset.getEditText().getText().toString(); + activityCallback.onGenerate(name, crazyPass, seed, offset, height); break; case TYPE_LEDGER: bGenerate.setEnabled(false); @@ -491,7 +511,7 @@ public class GenerateFragment extends Fragment { public interface Listener { void onGenerate(String name, String password); - void onGenerate(String name, String password, String seed, long height); + void onGenerate(String name, String password, String seed, String offset, long height); void onGenerate(String name, String password, String address, String viewKey, String spendKey, long height); diff --git a/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java b/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java index be1d7560..72ab77f6 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java @@ -32,6 +32,7 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.widget.Button; +import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ProgressBar; @@ -45,6 +46,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.progressindicator.CircularProgressIndicator; import com.google.android.material.switchmaterial.SwitchMaterial; import com.google.android.material.textfield.TextInputLayout; import com.m2049r.xmrwallet.ledger.Ledger; @@ -77,6 +79,7 @@ public class GenerateReviewFragment extends Fragment { private ProgressBar pbProgress; private TextView tvWalletPassword; private TextView tvWalletAddress; + private FrameLayout flWalletMnemonic; private TextView tvWalletMnemonic; private TextView tvWalletHeight; private TextView tvWalletViewKey; @@ -90,6 +93,9 @@ public class GenerateReviewFragment extends Fragment { private Button bAdvancedInfo; private Button bAccept; + private Button bSeedOffset; + private TextInputLayout etSeedOffset; + private String walletPath; private String walletName; @@ -106,6 +112,7 @@ public class GenerateReviewFragment extends Fragment { tvWalletViewKey = view.findViewById(R.id.tvWalletViewKey); tvWalletSpendKey = view.findViewById(R.id.tvWalletSpendKey); tvWalletMnemonic = view.findViewById(R.id.tvWalletMnemonic); + flWalletMnemonic = view.findViewById(R.id.flWalletMnemonic); tvWalletHeight = view.findViewById(R.id.tvWalletHeight); bCopyAddress = view.findViewById(R.id.bCopyAddress); bAdvancedInfo = view.findViewById(R.id.bAdvancedInfo); @@ -115,6 +122,9 @@ public class GenerateReviewFragment extends Fragment { llSpendKey = view.findViewById(R.id.llSpendKey); llViewKey = view.findViewById(R.id.llViewKey); + etSeedOffset = view.findViewById(R.id.etSeedOffset); + bSeedOffset = view.findViewById(R.id.bSeedOffset); + bAccept = view.findViewById(R.id.bAccept); boolean allowCopy = WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet; @@ -126,7 +136,25 @@ public class GenerateReviewFragment extends Fragment { view.findViewById(R.id.bCopyViewKey).setOnClickListener(v -> copyViewKey()); bCopyAddress.setEnabled(false); bCopyAddress.setOnClickListener(v -> copyAddress()); - view.findViewById(R.id.bAdvancedInfo).setOnClickListener(v -> showAdvancedInfo()); + bAdvancedInfo.setOnClickListener(v -> toggleAdvancedInfo()); + + bSeedOffset.setOnClickListener(v -> toggleSeedOffset()); + etSeedOffset.getEditText().addTextChangedListener(new TextWatcher() { + @Override + public void afterTextChanged(Editable s) { + showSeed(); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + } + }); Bundle args = getArguments(); type = args.getString(REQUEST_TYPE); @@ -136,18 +164,32 @@ public class GenerateReviewFragment extends Fragment { return view; } + String getSeedOffset() { + return etSeedOffset.getEditText().getText().toString(); + } + + boolean seedOffsetInProgress = false; + + void showSeed() { + synchronized (this) { + if (seedOffsetInProgress) return; + seedOffsetInProgress = true; + } + new AsyncShowSeed().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR, walletPath); + } + void showDetails() { tvWalletPassword.setText(null); new AsyncShow().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR, walletPath); } void copyViewKey() { - Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_viewkey), tvWalletViewKey.getText().toString()); + Helper.clipBoardCopy(requireActivity(), getString(R.string.label_copy_viewkey), tvWalletViewKey.getText().toString()); Toast.makeText(getActivity(), getString(R.string.message_copy_viewkey), Toast.LENGTH_SHORT).show(); } void copyAddress() { - Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_address), tvWalletAddress.getText().toString()); + Helper.clipBoardCopy(requireActivity(), getString(R.string.label_copy_address), tvWalletAddress.getText().toString()); Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show(); } @@ -155,15 +197,27 @@ public class GenerateReviewFragment extends Fragment { Toast.makeText(getActivity(), getString(R.string.message_nocopy), Toast.LENGTH_SHORT).show(); } - void showAdvancedInfo() { - llAdvancedInfo.setVisibility(View.VISIBLE); - bAdvancedInfo.setVisibility(View.GONE); - scrollview.post(new Runnable() { - @Override - public void run() { - scrollview.fullScroll(ScrollView.FOCUS_DOWN); - } - }); + void toggleAdvancedInfo() { + if (llAdvancedInfo.getVisibility() == View.VISIBLE) { + llAdvancedInfo.setVisibility(View.GONE); + bAdvancedInfo.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_keyboard_arrow_down_24, 0, 0, 0); + } else { + llAdvancedInfo.setVisibility(View.VISIBLE); + bAdvancedInfo.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_keyboard_arrow_up_24, 0, 0, 0); + scrollview.post(() -> scrollview.fullScroll(ScrollView.FOCUS_DOWN)); + } + } + + void toggleSeedOffset() { + if (etSeedOffset.getVisibility() == View.VISIBLE) { + etSeedOffset.getEditText().getText().clear(); + etSeedOffset.setVisibility(View.GONE); + bSeedOffset.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_keyboard_arrow_down_24, 0, 0, 0); + } else { + etSeedOffset.setVisibility(View.VISIBLE); + bSeedOffset.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_keyboard_arrow_up_24, 0, 0, 0); + etSeedOffset.requestFocusFromTouch(); + } } String type; @@ -215,14 +269,13 @@ public class GenerateReviewFragment extends Fragment { name = wallet.getName(); walletStatus = wallet.getStatus(); if (!walletStatus.isOk()) { - Timber.e(walletStatus.getErrorString()); if (closeWallet) wallet.close(); return false; } address = wallet.getAddress(); height = wallet.getRestoreHeight(); - seed = wallet.getSeed(); + seed = wallet.getSeed(getSeedOffset()); switch (wallet.getDeviceType()) { case Device_Ledger: viewKey = Ledger.Key(); @@ -367,7 +420,7 @@ public class GenerateReviewFragment extends Fragment { } public void hideProgress() { - pbProgress.setVisibility(View.GONE); + pbProgress.setVisibility(View.INVISIBLE); } boolean backOk() { @@ -408,8 +461,6 @@ public class GenerateReviewFragment extends Fragment { if (walletStatus.isOk()) { wallet.setPassword(newPassword); ok = true; - } else { - Timber.e(walletStatus.getErrorString()); } if (closeWallet) wallet.close(); return ok; @@ -469,7 +520,7 @@ public class GenerateReviewFragment extends Fragment { LayoutInflater li = LayoutInflater.from(getActivity()); View promptsView = li.inflate(R.layout.prompt_changepw, null); - AlertDialog.Builder alertDialogBuilder = new MaterialAlertDialogBuilder(getActivity()); + AlertDialog.Builder alertDialogBuilder = new MaterialAlertDialogBuilder(requireActivity()); alertDialogBuilder.setView(promptsView); final PasswordEntryView etPasswordA = promptsView.findViewById(R.id.etWalletPasswordA); @@ -483,23 +534,20 @@ public class GenerateReviewFragment extends Fragment { if (FingerprintHelper.isDeviceSupported(getActivity())) { llFingerprintAuth.setVisibility(View.VISIBLE); - swFingerprintAllowed.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (!swFingerprintAllowed.isChecked()) return; + swFingerprintAllowed.setOnClickListener(view -> { + if (!swFingerprintAllowed.isChecked()) return; - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(getActivity()); - builder.setMessage(Html.fromHtml(getString(R.string.generate_fingerprint_warn))) - .setCancelable(false) - .setPositiveButton(getString(R.string.label_ok), null) - .setNegativeButton(getString(R.string.label_cancel), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - swFingerprintAllowed.setChecked(false); - } - }) - .show(); - } + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(requireActivity()); + builder.setMessage(Html.fromHtml(getString(R.string.generate_fingerprint_warn))) + .setCancelable(false) + .setPositiveButton(getString(R.string.label_ok), null) + .setNegativeButton(getString(R.string.label_cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + swFingerprintAllowed.setChecked(false); + } + }) + .show(); }); swFingerprintAllowed.setChecked(FingerprintHelper.isFingerPassValid(getActivity(), walletName)); @@ -550,7 +598,7 @@ public class GenerateReviewFragment extends Fragment { .setNegativeButton(getString(R.string.label_cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - Helper.hideKeyboardAlways(getActivity()); + Helper.hideKeyboardAlways(requireActivity()); dialog.cancel(); openDialog = null; } @@ -566,7 +614,7 @@ public class GenerateReviewFragment extends Fragment { etPasswordB.setError(getString(R.string.generate_bad_passwordB)); } else { new AsyncChangePassword().execute(newPasswordA, Boolean.toString(swFingerprintAllowed.isChecked())); - Helper.hideKeyboardAlways(getActivity()); + Helper.hideKeyboardAlways(requireActivity()); openDialog.dismiss(); openDialog = null; } @@ -574,25 +622,23 @@ public class GenerateReviewFragment extends Fragment { }); // accept keyboard "ok" - etPasswordB.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() { - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) - || (actionId == EditorInfo.IME_ACTION_DONE)) { - String newPasswordA = etPasswordA.getEditText().getText().toString(); - String newPasswordB = etPasswordB.getEditText().getText().toString(); - // disallow empty passwords - if (!newPasswordA.equals(newPasswordB)) { - etPasswordB.setError(getString(R.string.generate_bad_passwordB)); - } else { - new AsyncChangePassword().execute(newPasswordA, Boolean.toString(swFingerprintAllowed.isChecked())); - Helper.hideKeyboardAlways(getActivity()); - openDialog.dismiss(); - openDialog = null; - } - return true; + etPasswordB.getEditText().setOnEditorActionListener((v, actionId, event) -> { + if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) + || (actionId == EditorInfo.IME_ACTION_DONE)) { + String newPasswordA = etPasswordA.getEditText().getText().toString(); + String newPasswordB = etPasswordB.getEditText().getText().toString(); + // disallow empty passwords + if (!newPasswordA.equals(newPasswordB)) { + etPasswordB.setError(getString(R.string.generate_bad_passwordB)); + } else { + new AsyncChangePassword().execute(newPasswordA, Boolean.toString(swFingerprintAllowed.isChecked())); + Helper.hideKeyboardAlways(requireActivity()); + openDialog.dismiss(); + openDialog = null; } - return false; + return true; } + return false; }); if (Helper.preventScreenshot()) { @@ -608,4 +654,61 @@ public class GenerateReviewFragment extends Fragment { && !key.toLowerCase().equals("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ledger implmenetation returns the spend key as f's } + + private class AsyncShowSeed extends AsyncTask { + String seed; + String offset; + Wallet.Status walletStatus; + + @Override + protected void onPreExecute() { + super.onPreExecute(); + offset = getSeedOffset(); + flWalletMnemonic.setAlpha(0.1f); + } + + @Override + protected Boolean doInBackground(String... params) { + if (params.length != 1) return false; + String walletPath = params[0]; + + Wallet wallet; + boolean closeWallet; + if (type.equals(GenerateReviewFragment.VIEW_TYPE_WALLET)) { + wallet = GenerateReviewFragment.this.walletCallback.getWallet(); + closeWallet = false; + } else { + wallet = WalletManager.getInstance().openWallet(walletPath, getPassword()); + closeWallet = true; + } + walletStatus = wallet.getStatus(); + if (!walletStatus.isOk()) { + if (closeWallet) wallet.close(); + return false; + } + + seed = wallet.getSeed(offset); + if (closeWallet) wallet.close(); + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + if (!isAdded()) return; // never mind + if (result) { + if (!seed.isEmpty()) { + llMnemonic.setVisibility(View.VISIBLE); + tvWalletMnemonic.setText(seed); + } + } else { + tvWalletMnemonic.setText(walletStatus.toString()); + } + seedOffsetInProgress = false; + if (!getSeedOffset().equals(offset)) { // make sure we have encrypted with the correct offset + showSeed(); // seed has changed in the meantime - recalc + } else + flWalletMnemonic.setAlpha(1); + } + } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java index d6ba1108..0b630175 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java @@ -929,7 +929,8 @@ public class LoginActivity extends BaseActivity } @Override - public void onGenerate(final String name, final String password, final String seed, + public void onGenerate(final String name, final String password, + final String seed, final String offset, final long restoreHeight) { createWallet(name, password, new WalletCreator() { @@ -941,7 +942,7 @@ public class LoginActivity extends BaseActivity @Override public boolean createWallet(File aFile, String password) { Wallet newWallet = WalletManager.getInstance() - .recoveryWallet(aFile, password, seed, restoreHeight); + .recoveryWallet(aFile, password, seed, offset, restoreHeight); return checkAndCloseWallet(newWallet); } }); diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java index 1baf640b..e85d0f85 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java @@ -129,7 +129,7 @@ public class Wallet { ConnectionStatus_WrongVersion } - public native String getSeed(); + public native String getSeed(String offset); public native String getSeedLanguage(); diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java b/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java index 433f7f02..555a1796 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java @@ -124,19 +124,19 @@ public class WalletManager { private native long openWalletJ(String path, String password, int networkType); - public Wallet recoveryWallet(File aFile, String password, String mnemonic) { - return recoveryWallet(aFile, password, mnemonic, 0); - } - - public Wallet recoveryWallet(File aFile, String password, String mnemonic, long restoreHeight) { - long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), password, mnemonic, + public Wallet recoveryWallet(File aFile, String password, + String mnemonic, String offset, + long restoreHeight) { + long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), password, + mnemonic, offset, getNetworkType().getValue(), restoreHeight); Wallet wallet = new Wallet(walletHandle); manageWallet(wallet); return wallet; } - private native long recoveryWalletJ(String path, String password, String mnemonic, + private native long recoveryWalletJ(String path, String password, + String mnemonic, String offset, int networkType, long restoreHeight); public Wallet createWalletWithKeys(File aFile, String password, String language, long restoreHeight, diff --git a/app/src/main/res/drawable/ic_baseline_cancel_24.xml b/app/src/main/res/drawable/ic_baseline_cancel_24.xml new file mode 100644 index 00000000..583a772b --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_cancel_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_keyboard_arrow_down_24.xml b/app/src/main/res/drawable/ic_baseline_keyboard_arrow_down_24.xml new file mode 100644 index 00000000..d6ed3084 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_keyboard_arrow_down_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_keyboard_arrow_up_24.xml b/app/src/main/res/drawable/ic_baseline_keyboard_arrow_up_24.xml new file mode 100644 index 00000000..5df167a1 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_keyboard_arrow_up_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_generate.xml b/app/src/main/res/layout/fragment_generate.xml index 20dbad75..8b2a2a99 100644 --- a/app/src/main/res/layout/fragment_generate.xml +++ b/app/src/main/res/layout/fragment_generate.xml @@ -15,7 +15,6 @@ style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/header_top_first" app:errorEnabled="true"> @@ -92,12 +91,41 @@ android:textAlignment="textStart" /> + + + + + + + @@ -179,7 +207,7 @@ style="@style/MoneroButton" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="8dp" + android:layout_marginTop="@dimen/header_top_first" android:text="@string/generate_buttonGenerate" /> diff --git a/app/src/main/res/layout/fragment_review.xml b/app/src/main/res/layout/fragment_review.xml index e8ccffc2..6c1ac1b6 100644 --- a/app/src/main/res/layout/fragment_review.xml +++ b/app/src/main/res/layout/fragment_review.xml @@ -18,12 +18,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:indeterminate="true" - android:visibility="gone" /> + android:visibility="invisible" /> + android:layout_height="wrap_content"> + android:visibility="visible"> - + android:layout_marginTop="@dimen/data_top"> + + + + + + + + + + + app:icon="@drawable/ic_baseline_keyboard_arrow_down_24" /> diff --git a/app/src/main/res/values-cat/strings.xml b/app/src/main/res/values-cat/strings.xml index d373da1e..48c3fab9 100644 --- a/app/src/main/res/values-cat/strings.xml +++ b/app/src/main/res/values-cat/strings.xml @@ -23,7 +23,7 @@ D\'acord Cancel·lar Tancar - Premi aquí per informació més detallada + Informació més detallada Enviat correctament! Fet @@ -431,4 +431,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d52df95e..adbfbe18 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -24,7 +24,7 @@ OK Abbrechen Schließen - Berühren für Detailinfos + Detailinfos Erfolgreich gesendet Fertig @@ -432,4 +432,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 1f5b1fcd..78542466 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -22,7 +22,7 @@ OK Άκυρο Κλείσιμο - Πάτησε για λεπτομερείς πληροφορίες + Λεπτομερείς πληροφορίες Αποστολή με επιτυχία Έγινε @@ -433,4 +433,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 6f23bed5..6db51898 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -23,7 +23,7 @@ OK Nuligi Fermi - Tuŝi por pli detalaj informoj. + Detalaj informoj Sukcese sendis Farite @@ -433,4 +433,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 1f638e84..067eb577 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -23,7 +23,7 @@ Aceptar Cancelar Cerrar - Toca para información más detallada + Información más detallada ¡Éxito! Hecho @@ -424,4 +424,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 3aeb44f9..1bddbd91 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -23,7 +23,7 @@ OK Katkesta Sulge - Puuduta lisainfo saamiseks + Lisainfo Edukalt saadetud Tehtud @@ -431,4 +431,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 09b628f8..c0d7b00d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -23,7 +23,7 @@ OK Annuler Fermer - Toucher pour plus d\'infos + Plus d\'infos Envoi réussi Fait @@ -437,4 +437,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 0d691ea0..877d0457 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -23,7 +23,7 @@ OK Mégsem Bezárás - Koppints a részletes informcáióért + Részletes információk Sikeresen elküldve Kész @@ -435,4 +435,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 2b2caa3d..b65a7e71 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -23,7 +23,7 @@ OK Cancella Chiudi - Tocca per informazioni dettagliate + Informazioni dettagliate Invio riuscito Fatto @@ -430,10 +430,13 @@ Importazione fallita! Resetta portafogli! - Il reset del portafogli cancellerà tutte le informazioni locali (note, nomi di account & sottoindirizzi, chiavi di transazione private, ...)! Procedi solo se il portafogli è corrotto e non si carica! + Tor required \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index da64c028..ad491ad7 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -23,7 +23,6 @@ OK キャンセル 閉じる - タッチして詳細情報を見る 送金成功 完了 @@ -436,4 +435,8 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + タッチして詳細情報を見る + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index bfe1afc1..7760a570 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -23,7 +23,7 @@ OK Avbryt Lukk - Trykk for detaljert informasjon + Detaljert informasjon Sendt suksessfullt! Ferdig @@ -433,4 +433,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 3fbb6572..0743afc1 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -23,7 +23,7 @@ OK Annuleren Sluiten - Tik voor meer informatie + Meer informatie Verzonden Klaar @@ -433,4 +433,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index e44f0712..ce28cbeb 100755 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -23,7 +23,7 @@ OK Cancelar Fechar - Toque para mais detalhes + Mais detalhes Enviado com sucesso Concluído @@ -420,10 +420,13 @@ aqui. Importação falhou! Resetar carteira! - Esta carteira será resetada, perdendo todos os dados "off-chain" (como notas, contas & nomes de subendereços, chaves de transações privadas, ...)! Use isso SOMENTE se esta carteira estiver corrompida e não carrega! + Tor required \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 2a122365..90d44934 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -23,7 +23,7 @@ OK Cancelar Fechar - Toca para informação detalhada + Informação detalhada Enviado com sucesso Feito @@ -437,4 +437,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index fdf965ed..1ae3c8bb 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -22,7 +22,7 @@ OK Anulează Închide - Atinge pentru informații detaliate + Informații detaliate Trimis cu succes Gata @@ -433,4 +433,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index bcaaf91e..867abdbb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -23,7 +23,7 @@ Ок Отмена Закрыть - Нажмите для доп. информации + Дополнительная информация Успешно отправлено Готово @@ -437,4 +437,7 @@ \u00A0ОЖИДАНИЕ УЗЛА\u00A0 Необходимо выбрать "Allow Background Starts" в настройках Orbot для использования Tor! SideShift.ai не поддерживает Tor.\nОтключите Tor для обмена XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 341a72b4..bbf75676 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -23,7 +23,7 @@ OK Zrušiť Zatvoriť - Klepni pre viac info + Viac info úspešne odoslané Hotovo @@ -434,4 +434,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index ecaa26ad..b6eedda2 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -23,7 +23,7 @@ OK Otkaži Zatvori - Takni za detaljne informacije + Detaljne informacije Uspešno poslato Gotovo @@ -432,4 +432,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 7fc6e546..694c3753 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -23,7 +23,7 @@ OK Avbryt Stäng - Tryck för detaljerad information + Detaljerad information Har skickats Färdig @@ -425,4 +425,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 6c33563f..93665d75 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -23,7 +23,7 @@ Ok Відміна Закрити - Натисніть для дод. інформації + Додатковій інформації Успішно відправлено Готово @@ -437,4 +437,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index dc5dbd77..aafeac1a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -19,7 +19,6 @@ 确认 取消 关闭 - 点击以查看详情 发送成功 完成 点此获取QR码 @@ -357,4 +356,8 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + 点击以查看详情 + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index e0e6c944..a6003f1e 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -23,7 +23,6 @@ 好的 取消 關閉 - 點選以獲得詳細資訊 已成功發送 完成 @@ -432,4 +431,8 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + 點選以獲得詳細資訊 + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index acad7c7f..a9534970 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,7 +25,7 @@ OK Cancel Close - Touch for detailed information + Detailed information Successfully sent Done @@ -507,4 +507,7 @@ \u00A0WAITING FOR NODE\u00A0 "Allow Background Starts" in Orbot Settings to use Tor! SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR. + + Seed encryption (EXPERIMENTAL) + Seed Offset Phrase (optional)