diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index a8adc8d..7287aac 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -60,9 +60,13 @@ set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_wserialization.a) ############# -# Monero set(libs_to_merge wallet cryptonote_core cryptonote_basic mnemonics common cncrypto ringct) +# Monero ############# +add_library(wallet_api STATIC IMPORTED) +set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libwallet_api.a) + add_library(wallet STATIC IMPORTED) set_target_properties(wallet PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libwallet.a) @@ -91,11 +95,9 @@ add_library(ringct STATIC IMPORTED) set_target_properties(ringct PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct.a) -##### - -add_library(p2p STATIC IMPORTED) -set_target_properties(p2p PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libp2p.a) +add_library(ringct_basic STATIC IMPORTED) +set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct_basic.a) add_library(blockchain_db STATIC IMPORTED) set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION @@ -113,7 +115,6 @@ add_library(unbound STATIC IMPORTED) set_target_properties(unbound PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libunbound.a) -#### add_library(epee STATIC IMPORTED) set_target_properties(epee PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libepee.a) @@ -122,9 +123,21 @@ add_library(blocks STATIC IMPORTED) set_target_properties(blocks PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libblocks.a) -add_library(miniupnpc STATIC IMPORTED) -set_target_properties(miniupnpc PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libminiupnpc.a) +add_library(checkpoints STATIC IMPORTED) +set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libcheckpoints.a) + +add_library(device STATIC IMPORTED) +set_target_properties(device PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice.a) + +add_library(multisig STATIC IMPORTED) +set_target_properties(multisig PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libmultisig.a) + +add_library(version STATIC IMPORTED) +set_target_properties(version PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libversion.a) ############# # System @@ -137,23 +150,26 @@ include_directories( ${EXTERNAL_LIBS_DIR}/monero/include ) message(STATUS EXTERNAL_LIBS_DIR : ${EXTERNAL_LIBS_DIR}) target_link_libraries( monerujo + + wallet_api wallet cryptonote_core cryptonote_basic mnemonics ringct + ringct_basic common cncrypto - blockchain_db lmdb easylogging unbound - p2p - epee blocks - miniupnpc + checkpoints + device + multisig + version boost_chrono boost_date_time diff --git a/app/build.gradle b/app/build.gradle index 1de14fa..a3e3e41 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.m2049r.xmrwallet" minSdkVersion 21 targetSdkVersion 25 - versionCode 74 - versionName "1.3.14 'Satoshis Dream'" + versionCode 82 + versionName "1.4.2 'Monero Spedner'" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { @@ -42,7 +42,7 @@ android { enable true reset() include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' - universalApk false + universalApk true } } @@ -104,5 +104,7 @@ dependencyVerification { 'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d', 'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850', 'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4', + 'com.jakewharton.timber:timber:35c22867f2673132e97e17857d36bb2fc25f5790f0425406833ed0254d62fc66', + 'com.nulab-inc:zxcvbn:18d7862a6abd2705defec478d77dedadf8f3bb7cf811df22995494f05485785f', ] } diff --git a/app/src/main/cpp/monerujo.cpp b/app/src/main/cpp/monerujo.cpp index abdf0ef..626f713 100644 --- a/app/src/main/cpp/monerujo.cpp +++ b/app/src/main/cpp/monerujo.cpp @@ -253,17 +253,18 @@ JNIEXPORT jlong JNICALL Java_com_m2049r_xmrwallet_model_WalletManager_createWalletJ(JNIEnv *env, jobject instance, jstring path, jstring password, jstring language, - jboolean isTestNet) { + jint networkType) { const char *_path = env->GetStringUTFChars(path, NULL); const char *_password = env->GetStringUTFChars(password, NULL); const char *_language = env->GetStringUTFChars(language, NULL); + Monero::NetworkType _networkType = static_cast(networkType); Bitmonero::Wallet *wallet = Bitmonero::WalletManagerFactory::getWalletManager()->createWallet( std::string(_path), std::string(_password), std::string(_language), - isTestNet); + _networkType); env->ReleaseStringUTFChars(path, _path); env->ReleaseStringUTFChars(password, _password); @@ -274,15 +275,16 @@ Java_com_m2049r_xmrwallet_model_WalletManager_createWalletJ(JNIEnv *env, jobject JNIEXPORT jlong JNICALL Java_com_m2049r_xmrwallet_model_WalletManager_openWalletJ(JNIEnv *env, jobject instance, jstring path, jstring password, - jboolean isTestNet) { + jint networkType) { const char *_path = env->GetStringUTFChars(path, NULL); const char *_password = env->GetStringUTFChars(password, NULL); + Monero::NetworkType _networkType = static_cast(networkType); Bitmonero::Wallet *wallet = Bitmonero::WalletManagerFactory::getWalletManager()->openWallet( std::string(_path), std::string(_password), - isTestNet); + _networkType); env->ReleaseStringUTFChars(path, _path); env->ReleaseStringUTFChars(password, _password); @@ -293,19 +295,20 @@ JNIEXPORT jlong JNICALL Java_com_m2049r_xmrwallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobject instance, jstring path, jstring password, jstring mnemonic, - jboolean isTestNet, + jint networkType, jlong restoreHeight) { const char *_path = env->GetStringUTFChars(path, NULL); const char *_password = env->GetStringUTFChars(password, NULL); const char *_mnemonic = env->GetStringUTFChars(mnemonic, NULL); + Monero::NetworkType _networkType = static_cast(networkType); Bitmonero::Wallet *wallet = Bitmonero::WalletManagerFactory::getWalletManager()->recoveryWallet( std::string(_path), std::string(_password), std::string(_mnemonic), - isTestNet, - restoreHeight); + _networkType, + (uint64_t) restoreHeight); env->ReleaseStringUTFChars(path, _path); env->ReleaseStringUTFChars(password, _password); @@ -314,10 +317,10 @@ Java_com_m2049r_xmrwallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobje } JNIEXPORT jlong JNICALL -Java_com_m2049r_xmrwallet_model_WalletManager_createWalletWithKeysJ(JNIEnv *env, jobject instance, +Java_com_m2049r_xmrwallet_model_WalletManager_createWalletFromKeysJ(JNIEnv *env, jobject instance, jstring path, jstring password, jstring language, - jboolean isTestNet, + jint networkType, jlong restoreHeight, jstring addressString, jstring viewKeyString, @@ -325,17 +328,18 @@ Java_com_m2049r_xmrwallet_model_WalletManager_createWalletWithKeysJ(JNIEnv *env, const char *_path = env->GetStringUTFChars(path, NULL); const char *_password = env->GetStringUTFChars(password, NULL); const char *_language = env->GetStringUTFChars(language, NULL); + Monero::NetworkType _networkType = static_cast(networkType); const char *_addressString = env->GetStringUTFChars(addressString, NULL); const char *_viewKeyString = env->GetStringUTFChars(viewKeyString, NULL); const char *_spendKeyString = env->GetStringUTFChars(spendKeyString, NULL); Bitmonero::Wallet *wallet = - Bitmonero::WalletManagerFactory::getWalletManager()->createWalletWithKeys( + Bitmonero::WalletManagerFactory::getWalletManager()->createWalletFromKeys( std::string(_path), std::string(_password), std::string(_language), - isTestNet, - restoreHeight, + _networkType, + (uint64_t) restoreHeight, std::string(_addressString), std::string(_viewKeyString), std::string(_spendKeyString)); @@ -356,7 +360,7 @@ Java_com_m2049r_xmrwallet_model_WalletManager_walletExists(JNIEnv *env, jobject bool exists = Bitmonero::WalletManagerFactory::getWalletManager()->walletExists(std::string(_path)); env->ReleaseStringUTFChars(path, _path); - return exists; + return static_cast(exists); } JNIEXPORT jboolean JNICALL @@ -371,7 +375,7 @@ Java_com_m2049r_xmrwallet_model_WalletManager_verifyWalletPassword(JNIEnv *env, std::string(_keys_file_name), std::string(_password), watch_only); env->ReleaseStringUTFChars(keys_file_name, _keys_file_name); env->ReleaseStringUTFChars(password, _password); - return passwordOk; + return static_cast(passwordOk); } @@ -440,7 +444,7 @@ Java_com_m2049r_xmrwallet_model_WalletManager_getBlockTarget(JNIEnv *env, jobjec JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_WalletManager_isMining(JNIEnv *env, jobject instance) { - return Bitmonero::WalletManagerFactory::getWalletManager()->isMining(); + return static_cast(Bitmonero::WalletManagerFactory::getWalletManager()->isMining()); } JNIEXPORT jboolean JNICALL @@ -454,12 +458,12 @@ Java_com_m2049r_xmrwallet_model_WalletManager_startMining(JNIEnv *env, jobject i background_mining, ignore_battery); env->ReleaseStringUTFChars(address, _address); - return success; + return static_cast(success); } JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_WalletManager_stopMining(JNIEnv *env, jobject instance) { - return Bitmonero::WalletManagerFactory::getWalletManager()->stopMining(); + return static_cast(Bitmonero::WalletManagerFactory::getWalletManager()->stopMining()); } JNIEXPORT jstring JNICALL @@ -493,7 +497,7 @@ Java_com_m2049r_xmrwallet_model_WalletManager_closeJ(JNIEnv *env, jobject instan } } LOGD("wallet closed"); - return closeSuccess; + return static_cast(closeSuccess); } @@ -543,7 +547,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_setPassword(JNIEnv *env, jobject instance Bitmonero::Wallet *wallet = getHandle(env, instance); bool success = wallet->setPassword(std::string(_password)); env->ReleaseStringUTFChars(password, _password); - return success; + return static_cast(success); } JNIEXPORT jstring JNICALL @@ -558,10 +562,10 @@ Java_com_m2049r_xmrwallet_model_Wallet_getPath(JNIEnv *env, jobject instance) { return env->NewStringUTF(wallet->path().c_str()); } -JNIEXPORT jboolean JNICALL -Java_com_m2049r_xmrwallet_model_Wallet_isTestNet(JNIEnv *env, jobject instance) { +JNIEXPORT jint JNICALL +Java_com_m2049r_xmrwallet_model_Wallet_nettype(JNIEnv *env, jobject instance) { Bitmonero::Wallet *wallet = getHandle(env, instance); - return wallet->testnet(); + return wallet->nettype(); } //TODO virtual void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const = 0; @@ -599,7 +603,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_store(JNIEnv *env, jobject instance, LOGE("store() %s", wallet->errorString().c_str()); } env->ReleaseStringUTFChars(path, _path); - return success; + return static_cast(success); } JNIEXPORT jstring JNICALL @@ -619,12 +623,13 @@ Java_com_m2049r_xmrwallet_model_Wallet_initJ(JNIEnv *env, jobject instance, const char *_daemon_username = env->GetStringUTFChars(daemon_username, NULL); const char *_daemon_password = env->GetStringUTFChars(daemon_password, NULL); Bitmonero::Wallet *wallet = getHandle(env, instance); - bool status = wallet->init(_daemon_address, upper_transaction_size_limit, _daemon_username, + bool status = wallet->init(_daemon_address, (uint64_t) upper_transaction_size_limit, + _daemon_username, _daemon_password); env->ReleaseStringUTFChars(daemon_address, _daemon_address); env->ReleaseStringUTFChars(daemon_username, _daemon_username); env->ReleaseStringUTFChars(daemon_password, _daemon_password); - return status; + return static_cast(status); } // virtual bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const = 0; @@ -655,7 +660,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_getUnlockedBalance(JNIEnv *env, jobject i JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_Wallet_isWatchOnly(JNIEnv *env, jobject instance) { Bitmonero::Wallet *wallet = getHandle(env, instance); - return wallet->watchOnly(); + return static_cast(wallet->watchOnly()); } JNIEXPORT jlong JNICALL @@ -687,7 +692,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_getDaemonBlockChainTargetHeight(JNIEnv *e JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_Wallet_isSynchronized(JNIEnv *env, jobject instance) { Bitmonero::Wallet *wallet = getHandle(env, instance); - return wallet->synchronized(); + return static_cast(wallet->synchronized()); } JNIEXPORT jstring JNICALL @@ -722,16 +727,17 @@ Java_com_m2049r_xmrwallet_model_Wallet_isPaymentIdValid(JNIEnv *env, jobject cla const char *_payment_id = env->GetStringUTFChars(payment_id, NULL); bool isValid = Bitmonero::Wallet::paymentIdValid(_payment_id); env->ReleaseStringUTFChars(payment_id, _payment_id); - return isValid; + return static_cast(isValid); } JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_Wallet_isAddressValid(JNIEnv *env, jobject clazz, - jstring address, jboolean isTestNet) { + jstring address, jint networkType) { const char *_address = env->GetStringUTFChars(address, NULL); - bool isValid = Bitmonero::Wallet::addressValid(_address, isTestNet); + Monero::NetworkType _networkType = static_cast(networkType); + bool isValid = Bitmonero::Wallet::addressValid(_address, _networkType); env->ReleaseStringUTFChars(address, _address); - return isValid; + return static_cast(isValid); } //TODO static static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error); @@ -739,9 +745,10 @@ Java_com_m2049r_xmrwallet_model_Wallet_isAddressValid(JNIEnv *env, jobject clazz JNIEXPORT jstring JNICALL Java_com_m2049r_xmrwallet_model_Wallet_getPaymentIdFromAddress(JNIEnv *env, jobject clazz, jstring address, - jboolean isTestNet) { + jint networkType) { + Monero::NetworkType _networkType = static_cast(networkType); const char *_address = env->GetStringUTFChars(address, NULL); - std::string payment_id = Bitmonero::Wallet::paymentIdFromAddress(_address, isTestNet); + std::string payment_id = Bitmonero::Wallet::paymentIdFromAddress(_address, _networkType); env->ReleaseStringUTFChars(address, _address); return env->NewStringUTF(payment_id.c_str()); } @@ -766,7 +773,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_pauseRefresh(JNIEnv *env, jobject instanc JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_Wallet_refresh(JNIEnv *env, jobject instance) { Bitmonero::Wallet *wallet = getHandle(env, instance); - return wallet->refresh(); + return static_cast(wallet->refresh()); } JNIEXPORT void JNICALL @@ -880,7 +887,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_setUserNote(JNIEnv *env, jobject instance env->ReleaseStringUTFChars(txid, _txid); env->ReleaseStringUTFChars(note, _note); - return success; + return static_cast(success); } JNIEXPORT jstring JNICALL @@ -1029,7 +1036,7 @@ Java_com_m2049r_xmrwallet_model_PendingTransaction_commit(JNIEnv *env, jobject i bool success = tx->commit(_filename, overwrite); env->ReleaseStringUTFChars(filename, _filename); - return success; + return static_cast(success); } @@ -1051,10 +1058,13 @@ Java_com_m2049r_xmrwallet_model_PendingTransaction_getFee(JNIEnv *env, jobject i // TODO this returns a vector of strings - deal with this later - for now return first one JNIEXPORT jstring JNICALL -Java_com_m2049r_xmrwallet_model_PendingTransaction_getFirstTxId(JNIEnv *env, jobject instance) { +Java_com_m2049r_xmrwallet_model_PendingTransaction_getFirstTxIdJ(JNIEnv *env, jobject instance) { Bitmonero::PendingTransaction *tx = getHandle(env, instance); std::vector txids = tx->txid(); - return env->NewStringUTF(txids.front().c_str()); + if (!txids.empty()) + return env->NewStringUTF(txids.front().c_str()); + else + return nullptr; } diff --git a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java index f5aa566..c2b5956 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java @@ -386,7 +386,7 @@ public class GenerateFragment extends Fragment { private boolean checkAddress() { String address = etWalletAddress.getEditText().getText().toString(); - boolean ok = Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet()); + boolean ok = Wallet.isAddressValid(address); if (!ok) { etWalletAddress.setError(getString(R.string.generate_check_address)); } else { diff --git a/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java b/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java index 8ec29c7..97a4b33 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java @@ -34,6 +34,7 @@ import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; +import com.m2049r.xmrwallet.model.NetworkType; import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.WalletManager; @@ -81,7 +82,7 @@ public class GenerateReviewFragment extends Fragment { bAccept = (Button) view.findViewById(R.id.bAccept); - boolean testnet = WalletManager.getInstance().isTestNet(); + boolean testnet = WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet; tvWalletMnemonic.setTextIsSelectable(testnet); tvWalletSpendKey.setTextIsSelectable(testnet); @@ -185,6 +186,7 @@ public class GenerateReviewFragment extends Fragment { name = wallet.getName(); status = wallet.getStatus(); if (status != Wallet.Status.Status_Ok) { + Timber.e(wallet.getErrorString()); if (closeWallet) wallet.close(); return false; } diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java index 50d1d88..48deca4 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java @@ -45,10 +45,12 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; +import com.m2049r.xmrwallet.data.WalletNode; import com.m2049r.xmrwallet.dialog.AboutFragment; -import com.m2049r.xmrwallet.dialog.DonationFragment; +import com.m2049r.xmrwallet.dialog.CreditsFragment; import com.m2049r.xmrwallet.dialog.HelpFragment; import com.m2049r.xmrwallet.dialog.PrivacyFragment; +import com.m2049r.xmrwallet.model.NetworkType; import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.service.WalletService; @@ -60,7 +62,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.nio.channels.FileChannel; @@ -120,8 +121,8 @@ public class LoginActivity extends SecureActivity case Toolbar.BUTTON_CLOSE: finish(); break; - case Toolbar.BUTTON_DONATE: - DonationFragment.display(getSupportFragmentManager()); + case Toolbar.BUTTON_CREDITS: + CreditsFragment.display(getSupportFragmentManager()); break; case Toolbar.BUTTON_NONE: default: @@ -147,14 +148,14 @@ public class LoginActivity extends SecureActivity } @Override - public boolean onWalletSelected(String walletName, String daemon, boolean testnet) { + public boolean onWalletSelected(String walletName, String daemon) { if (daemon.length() == 0) { Toast.makeText(this, getString(R.string.prompt_daemon_missing), Toast.LENGTH_SHORT).show(); return false; } if (checkServiceRunning()) return false; try { - WalletNode aWalletNode = new WalletNode(walletName, daemon, testnet); + WalletNode aWalletNode = new WalletNode(walletName, daemon, WalletManager.getInstance().getNetworkType()); new AsyncOpenWallet().execute(aWalletNode); } catch (IllegalArgumentException ex) { Timber.e(ex.getLocalizedMessage()); @@ -165,9 +166,8 @@ public class LoginActivity extends SecureActivity } @Override - public void onWalletDetails(final String walletName, boolean testnet) { - setNet(testnet); - Timber.d("details for wallet ." + walletName + "."); + public void onWalletDetails(final String walletName) { + Timber.d("details for wallet .%s.", walletName); if (checkServiceRunning()) return; DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override @@ -203,9 +203,8 @@ public class LoginActivity extends SecureActivity } @Override - public void onWalletReceive(String walletName, boolean testnet) { - setNet(testnet); - Timber.d("receive for wallet ." + walletName + "."); + public void onWalletReceive(String walletName) { + Timber.d("receive for wallet .%s.", walletName); if (checkServiceRunning()) return; final File walletFile = Helper.getWalletFile(this, walletName); if (WalletManager.getInstance().walletExists(walletFile)) { @@ -439,8 +438,7 @@ public class LoginActivity extends SecureActivity } @Override - public void onAddWallet(boolean testnet, String type) { - setNet(testnet); + public void onAddWallet(String type) { if (checkServiceRunning()) return; startGenerateFragment(type); } @@ -537,7 +535,7 @@ public class LoginActivity extends SecureActivity } private boolean checkWalletPassword(String walletName, String password) { - String walletPath = new File(Helper.getStorageRoot(getApplicationContext()), + String walletPath = new File(Helper.getWalletRoot(getApplicationContext()), walletName + ".keys").getAbsolutePath(); // only test view key return WalletManager.getInstance().verifyWalletPassword(walletPath, password, true); @@ -566,20 +564,30 @@ public class LoginActivity extends SecureActivity @Override public File getStorageRoot() { - return Helper.getStorageRoot(getApplicationContext()); + return Helper.getWalletRoot(getApplicationContext()); } //////////////////////////////////////// //////////////////////////////////////// @Override - public void showNet(boolean testnet) { - if (testnet) { - toolbar.setBackgroundResource(R.color.colorPrimaryDark); - } else { - toolbar.setBackgroundResource(R.drawable.backgound_toolbar_mainnet); + public void showNet() { + switch (WalletManager.getInstance().getNetworkType()) { + case NetworkType_Mainnet: + toolbar.setSubtitle(getString(R.string.connect_mainnet)); + toolbar.setBackgroundResource(R.drawable.backgound_toolbar_mainnet); + break; + case NetworkType_Testnet: + toolbar.setSubtitle(getString(R.string.connect_testnet)); + toolbar.setBackgroundResource(R.color.colorPrimaryDark); + break; + case NetworkType_Stagenet: + toolbar.setSubtitle(getString(R.string.connect_stagenet)); + toolbar.setBackgroundResource(R.color.colorPrimaryDark); + break; + default: + throw new IllegalStateException("NetworkType unknown: " + WalletManager.getInstance().getNetworkType()); } - toolbar.setSubtitle(getString(testnet ? R.string.connect_testnet : R.string.connect_mainnet)); } @Override @@ -636,7 +644,7 @@ public class LoginActivity extends SecureActivity private class MyProgressDialog extends ProgressDialog { Activity activity; - public MyProgressDialog(Activity activity, int msgId) { + MyProgressDialog(Activity activity, int msgId) { super(activity); this.activity = activity; setCancelable(false); @@ -735,6 +743,7 @@ public class LoginActivity extends SecureActivity } void startLoginFragment() { + Helper.setMoneroHome(this); Fragment fragment = new LoginFragment(); getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, fragment).commit(); @@ -784,8 +793,8 @@ public class LoginActivity extends SecureActivity File newWalletFile; - public AsyncCreateWallet(final String name, final String password, - final WalletCreator walletCreator) { + AsyncCreateWallet(final String name, final String password, + final WalletCreator walletCreator) { super(); this.walletName = name; this.walletPassword = password; @@ -1081,6 +1090,7 @@ public class LoginActivity extends SecureActivity getSupportFragmentManager().findFragmentById(R.id.fragment_container); item.setChecked(loginFragment.onTestnetMenuItem()); } catch (ClassCastException ex) { + // never mind then } return true; default: @@ -1088,59 +1098,8 @@ public class LoginActivity extends SecureActivity } } - private void setNet(boolean testnet) { - WalletManager.getInstance().setDaemon("", testnet, "", ""); - } - - static class WalletNode { - String name = null; - String host = ""; - int port = 28081; - String user = ""; - String password = ""; - boolean isTestnet; - - WalletNode(String walletName, String daemon, boolean isTestnet) { - if ((daemon == null) || daemon.isEmpty()) return; - this.name = walletName; - String daemonAddress; - String a[] = daemon.split("@"); - if (a.length == 1) { // no credentials - daemonAddress = a[0]; - } else if (a.length == 2) { // credentials - String userPassword[] = a[0].split(":"); - if (userPassword.length != 2) - throw new IllegalArgumentException("User:Password invalid"); - user = userPassword[0]; - if (!user.isEmpty()) password = userPassword[1]; - daemonAddress = a[1]; - } else { - throw new IllegalArgumentException("Too many @"); - } - - String da[] = daemonAddress.split(":"); - if ((da.length > 2) || (da.length < 1)) - throw new IllegalArgumentException("Too many ':' or too few"); - host = da[0]; - if (da.length == 2) { - try { - port = Integer.parseInt(da[1]); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException("Port not numeric"); - } - } else { - port = (isTestnet ? 28081 : 18081); - } - this.isTestnet = isTestnet; - } - - String getAddress() { - return host + ":" + port; - } - - boolean isValid() { - return !host.isEmpty(); - } + public void setNetworkType(NetworkType networkType) { + WalletManager.getInstance().setNetworkType(networkType); } private class AsyncOpenWallet extends AsyncTask { @@ -1167,22 +1126,22 @@ public class LoginActivity extends SecureActivity try { long timeDA = new Date().getTime(); - SocketAddress address = new InetSocketAddress(walletNode.host, walletNode.port); + SocketAddress address = walletNode.getSocketAddress(); long timeDB = new Date().getTime(); - Timber.d("Resolving " + walletNode.host + " took " + (timeDB - timeDA) + "ms."); + Timber.d("Resolving " + walletNode.getAddress() + " took " + (timeDB - timeDA) + "ms."); Socket socket = new Socket(); long timeA = new Date().getTime(); socket.connect(address, LoginActivity.DAEMON_TIMEOUT); socket.close(); long timeB = new Date().getTime(); long time = timeB - timeA; - Timber.d("Daemon " + walletNode.host + " is " + time + "ms away."); + Timber.d("Daemon " + walletNode.getAddress() + " is " + time + "ms away."); return (time < LoginActivity.DAEMON_TIMEOUT ? OK : TIMEOUT); } catch (IOException ex) { - Timber.d("Cannot reach daemon " + walletNode.host + "/" + walletNode.port + " because " + ex.getMessage()); + Timber.d("Cannot reach daemon %s because %s", walletNode.getAddress(), ex.getMessage()); return IOEX; } catch (IllegalArgumentException ex) { - Timber.d("Cannot reach daemon " + walletNode.host + "/" + walletNode.port + " because " + ex.getMessage()); + Timber.d("Cannot reach daemon %s because %s", walletNode.getAddress(), ex.getMessage()); return INVALID; } } @@ -1196,7 +1155,7 @@ public class LoginActivity extends SecureActivity dismissProgressDialog(); switch (result) { case OK: - Timber.d("selected wallet is ." + walletNode.name + "."); + Timber.d("selected wallet is .%s.", walletNode.getName()); // now it's getting real, onValidateFields if wallet exists promptAndStart(walletNode); break; @@ -1214,11 +1173,10 @@ public class LoginActivity extends SecureActivity } void promptAndStart(WalletNode walletNode) { - File walletFile = Helper.getWalletFile(this, walletNode.name); + File walletFile = Helper.getWalletFile(this, walletNode.getName()); if (WalletManager.getInstance().walletExists(walletFile)) { - WalletManager.getInstance(). - setDaemon(walletNode.getAddress(), walletNode.isTestnet, walletNode.user, walletNode.password); - promptPassword(walletNode.name, new PasswordAction() { + WalletManager.getInstance().setDaemon(walletNode); + promptPassword(walletNode.getName(), new PasswordAction() { @Override public void action(String walletName, String password) { startWallet(walletName, password); diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java index df480f8..b52fceb 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java @@ -45,6 +45,7 @@ import android.widget.Toast; import com.m2049r.xmrwallet.dialog.HelpFragment; import com.m2049r.xmrwallet.layout.WalletInfoAdapter; +import com.m2049r.xmrwallet.model.NetworkType; import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.NodeList; @@ -81,11 +82,11 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter File getStorageRoot(); - boolean onWalletSelected(String wallet, String daemon, boolean testnet); + boolean onWalletSelected(String wallet, String daemon); - void onWalletDetails(String wallet, boolean testnet); + void onWalletDetails(String wallet); - void onWalletReceive(String wallet, boolean testnet); + void onWalletReceive(String wallet); void onWalletRename(String name); @@ -93,14 +94,16 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter void onWalletArchive(String walletName); - void onAddWallet(boolean testnet, String type); + void onAddWallet(String type); - void showNet(boolean testnet); + void showNet(); void setToolbarButton(int type); void setTitle(String title); + void setNetworkType(NetworkType networkType); + } @Override @@ -126,8 +129,8 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter super.onResume(); Timber.d("onResume()"); activityCallback.setTitle(null); - activityCallback.setToolbarButton(Toolbar.BUTTON_DONATE); - activityCallback.showNet(isTestnet()); + activityCallback.setToolbarButton(Toolbar.BUTTON_CREDITS); + activityCallback.showNet(); } @Override @@ -244,13 +247,13 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter // Callbacks from WalletInfoAdapter @Override public void onInteraction(final View view, final WalletManager.WalletInfo infoItem) { - String x = isTestnet() ? "9A-" : "4-"; - if (x.indexOf(infoItem.address.charAt(0)) < 0) { + String addressPrefix = addressPrefix(); + if (addressPrefix.indexOf(infoItem.address.charAt(0)) < 0) { Toast.makeText(getActivity(), getString(R.string.prompt_wrong_net), Toast.LENGTH_LONG).show(); return; } - if (activityCallback.onWalletSelected(infoItem.name, getDaemon(), isTestnet())) { + if (activityCallback.onWalletSelected(infoItem.name, getDaemon())) { savePrefs(); } } @@ -279,11 +282,24 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter return true; } + private String addressPrefix() { + switch (WalletManager.getInstance().getNetworkType()) { + case NetworkType_Testnet: + return "9A-"; + case NetworkType_Mainnet: + return "4-"; + case NetworkType_Stagenet: + return "5-"; + default: + throw new IllegalStateException("Unsupported Network: " + WalletManager.getInstance().getNetworkType()); + } + } + private void filterList() { displayedList.clear(); - String x = isTestnet() ? "9A" : "4"; + String addressPrefix = addressPrefix(); for (WalletManager.WalletInfo s : walletList) { - if (x.indexOf(s.address.charAt(0)) >= 0) displayedList.add(s); + if (addressPrefix.indexOf(s.address.charAt(0)) >= 0) displayedList.add(s); } } @@ -313,11 +329,11 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter } private void showInfo(@NonNull String name) { - activityCallback.onWalletDetails(name, isTestnet()); + activityCallback.onWalletDetails(name); } private void showReceive(@NonNull String name) { - activityCallback.onWalletReceive(name, isTestnet()); + activityCallback.onWalletReceive(name); } @Override @@ -329,29 +345,31 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.list_menu, menu); - menu.findItem(R.id.action_testnet).setChecked(isTestnet()); + menu.findItem(R.id.action_testnet).setChecked(testnetCheckMenu); super.onCreateOptionsMenu(menu, inflater); } - private boolean testnet = BuildConfig.DEBUG; + private boolean testnetCheckMenu = BuildConfig.DEBUG; - boolean isTestnet() { - return testnet; - } + //boolean isTestnet() { + // return testnet; + //} public boolean onTestnetMenuItem() { - boolean lastState = testnet; + boolean lastState = testnetCheckMenu; setNet(!lastState, true); // set and save return !lastState; } - public void setNet(boolean testnet, boolean save) { - this.testnet = testnet; - activityCallback.showNet(testnet); + public void setNet(boolean testnetChecked, boolean save) { + this.testnetCheckMenu = testnetChecked; + NetworkType net = testnetChecked ? NetworkType.NetworkType_Testnet : NetworkType.NetworkType_Mainnet; + activityCallback.setNetworkType(net); + activityCallback.showNet(); if (save) { savePrefs(true); // use previous state as we just clicked it } - if (testnet) { + if (testnetChecked) { setDaemon(daemonTestNet); } else { setDaemon(daemonMainNet); @@ -379,7 +397,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter daemonMainNet = new NodeList(sharedPref.getString(PREF_DAEMON_MAINNET, PREF_DAEMONLIST_MAINNET)); daemonTestNet = new NodeList(sharedPref.getString(PREF_DAEMON_TESTNET, PREF_DAEMONLIST_TESTNET)); - setNet(isTestnet(), false); + setNet(testnetCheckMenu, false); showXmrtoEnabled = sharedPref.getBoolean(PREF_SHOW_XMRTO_ENABLED, true); } @@ -398,7 +416,7 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter void savePrefs(boolean usePreviousTestnetState) { Timber.d("SAVE / %s", usePreviousTestnetState); // save the daemon address for the net - boolean testnet = isTestnet() ^ usePreviousTestnetState; + boolean testnet = testnetCheckMenu ^ usePreviousTestnetState; String daemon = getDaemon(); if (testnet) { daemonTestNet.setRecent(daemon); @@ -484,19 +502,19 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter case R.id.fabNew: fabScreen.setVisibility(View.INVISIBLE); isFabOpen = false; - activityCallback.onAddWallet(isTestnet(), GenerateFragment.TYPE_NEW); + activityCallback.onAddWallet(GenerateFragment.TYPE_NEW); break; case R.id.fabView: animateFAB(); - activityCallback.onAddWallet(isTestnet(), GenerateFragment.TYPE_VIEWONLY); + activityCallback.onAddWallet(GenerateFragment.TYPE_VIEWONLY); break; case R.id.fabKey: animateFAB(); - activityCallback.onAddWallet(isTestnet(), GenerateFragment.TYPE_KEY); + activityCallback.onAddWallet(GenerateFragment.TYPE_KEY); break; case R.id.fabSeed: animateFAB(); - activityCallback.onAddWallet(isTestnet(), GenerateFragment.TYPE_SEED); + activityCallback.onAddWallet(GenerateFragment.TYPE_SEED); break; case R.id.fabScreen: animateFAB(); diff --git a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java index e7b8dae..91222f9 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/ReceiveFragment.java @@ -300,7 +300,7 @@ public class ReceiveFragment extends Fragment { String paymentId = etPaymentId.getEditText().getText().toString(); String xmrAmount = evAmount.getAmount(); Timber.d("%s/%s/%s", xmrAmount, paymentId, address); - if ((xmrAmount == null) || !Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet())) { + if ((xmrAmount == null) || !Wallet.isAddressValid(address)) { clearQR(); Timber.d("CLEARQR"); return; diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java index 91ff7bd..a08b32c 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java @@ -36,7 +36,7 @@ import android.widget.Toast; import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.TxData; -import com.m2049r.xmrwallet.dialog.DonationFragment; +import com.m2049r.xmrwallet.dialog.CreditsFragment; import com.m2049r.xmrwallet.dialog.HelpFragment; import com.m2049r.xmrwallet.fragment.send.SendAddressWizardFragment; import com.m2049r.xmrwallet.fragment.send.SendFragment; @@ -159,8 +159,8 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis case R.id.action_info: onWalletDetails(); return true; - case R.id.action_donate: - DonationFragment.display(getSupportFragmentManager()); + case R.id.action_credits: + CreditsFragment.display(getSupportFragmentManager()); return true; case R.id.action_share: onShareTxInfo(); @@ -213,8 +213,8 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis case Toolbar.BUTTON_CLOSE: finish(); break; - case Toolbar.BUTTON_DONATE: - Toast.makeText(WalletActivity.this, getString(R.string.label_donate), Toast.LENGTH_SHORT).show(); + case Toolbar.BUTTON_CREDITS: + Toast.makeText(WalletActivity.this, getString(R.string.label_credits), Toast.LENGTH_SHORT).show(); case Toolbar.BUTTON_NONE: default: Timber.e("Button " + type + "pressed - how can this be?"); @@ -222,13 +222,6 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis } }); - boolean testnet = WalletManager.getInstance().isTestNet(); - if (testnet) { - toolbar.setBackgroundResource(R.color.colorPrimaryDark); - } else { - toolbar.setBackgroundResource(R.drawable.backgound_toolbar_mainnet); - } - Fragment walletFragment = new WalletFragment(); getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, walletFragment, WalletFragment.class.getName()).commit(); @@ -238,6 +231,23 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis Timber.d("onCreate() done."); } + public void showNet() { + switch (WalletManager.getInstance().getNetworkType()) { + case NetworkType_Mainnet: + toolbar.setBackgroundResource(R.drawable.backgound_toolbar_mainnet); + break; + case NetworkType_Testnet: + toolbar.setBackgroundResource(R.color.colorPrimaryDark); + break; + case NetworkType_Stagenet: + toolbar.setBackgroundResource(R.color.colorPrimaryDark); + break; + default: + throw new IllegalStateException("Unsupported Network: " + WalletManager.getInstance().getNetworkType()); + } + } + + public Wallet getWallet() { if (mBoundService == null) throw new IllegalStateException("WalletService not bound."); return mBoundService.getWallet(); @@ -798,7 +808,7 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis @Override public boolean verifyWalletPassword(String password) { - String walletPath = new File(Helper.getStorageRoot(this), + String walletPath = new File(Helper.getWalletRoot(this), getWalletName() + ".keys").getAbsolutePath(); return WalletManager.getInstance().verifyWalletPassword(walletPath, password, true); } diff --git a/app/src/main/java/com/m2049r/xmrwallet/XmrWalletApplication.java b/app/src/main/java/com/m2049r/xmrwallet/XmrWalletApplication.java index 520a817..f6fecc5 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/XmrWalletApplication.java +++ b/app/src/main/java/com/m2049r/xmrwallet/XmrWalletApplication.java @@ -19,13 +19,15 @@ package com.m2049r.xmrwallet; import android.app.Application; +import com.m2049r.xmrwallet.util.Helper; + import timber.log.Timber; public class XmrWalletApplication extends Application { @Override public void onCreate() { super.onCreate(); - + if (BuildConfig.DEBUG) { Timber.plant(new Timber.DebugTree()); } diff --git a/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java b/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java index 3ff9e04..1471c89 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java +++ b/app/src/main/java/com/m2049r/xmrwallet/data/BarcodeData.java @@ -18,6 +18,7 @@ package com.m2049r.xmrwallet.data; import android.net.Uri; +import com.m2049r.xmrwallet.model.NetworkType; import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.util.BitcoinAddressValidator; @@ -178,7 +179,7 @@ public class BarcodeData { return null; // we have an amount but its not a number! } } - if (!BitcoinAddressValidator.validate(address, WalletManager.getInstance().isTestNet())) { + if (!BitcoinAddressValidator.validate(address)) { Timber.d("address invalid"); return null; } @@ -190,7 +191,7 @@ public class BarcodeData { if (address == null) return null; - if (!BitcoinAddressValidator.validate(address, WalletManager.getInstance().isTestNet())) { + if (!BitcoinAddressValidator.validate(address)) { Timber.d("address invalid"); return null; } diff --git a/app/src/main/java/com/m2049r/xmrwallet/data/WalletNode.java b/app/src/main/java/com/m2049r/xmrwallet/data/WalletNode.java new file mode 100644 index 0000000..378b5c4 --- /dev/null +++ b/app/src/main/java/com/m2049r/xmrwallet/data/WalletNode.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018 m2049r + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.m2049r.xmrwallet.data; + +import com.m2049r.xmrwallet.model.NetworkType; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +public class WalletNode { + private final String name; + private final String host; + private final int port; + private final String user; + private final String password; + private final NetworkType networkType; + + public WalletNode(String walletName, String daemon, NetworkType networkType) { + if ((daemon == null) || daemon.isEmpty()) + throw new IllegalArgumentException("daemon is empty"); + this.name = walletName; + String daemonAddress; + String a[] = daemon.split("@"); + if (a.length == 1) { // no credentials + daemonAddress = a[0]; + user = ""; + password = ""; + } else if (a.length == 2) { // credentials + String userPassword[] = a[0].split(":"); + if (userPassword.length != 2) + throw new IllegalArgumentException("User:Password invalid"); + user = userPassword[0]; + if (!user.isEmpty()) { + password = userPassword[1]; + } else { + password = ""; + } + daemonAddress = a[1]; + } else { + throw new IllegalArgumentException("Too many @"); + } + + String da[] = daemonAddress.split(":"); + if ((da.length > 2) || (da.length < 1)) + throw new IllegalArgumentException("Too many ':' or too few"); + host = da[0]; + if (da.length == 2) { + try { + port = Integer.parseInt(da[1]); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException("Port not numeric"); + } + } else { + switch (networkType) { + case NetworkType_Mainnet: + port = 18081; + break; + case NetworkType_Testnet: + port = 28081; + break; + case NetworkType_Stagenet: + port = 38081; + break; + default: + port = 0; + } + } + this.networkType = networkType; + } + + public String getName() { + return name; + } + + public String getAddress() { + return host + ":" + port; + } + + public String getUsername() { + return user; + } + + public String getPassword() { + return password; + } + + public SocketAddress getSocketAddress() { + return new InetSocketAddress(host, port); + } + + public boolean isValid() { + return !host.isEmpty(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/m2049r/xmrwallet/dialog/DonationFragment.java b/app/src/main/java/com/m2049r/xmrwallet/dialog/CreditsFragment.java similarity index 68% rename from app/src/main/java/com/m2049r/xmrwallet/dialog/DonationFragment.java rename to app/src/main/java/com/m2049r/xmrwallet/dialog/CreditsFragment.java index f50c681..89b443b 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/dialog/DonationFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/dialog/CreditsFragment.java @@ -28,16 +28,14 @@ import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; -import android.widget.Toast; import com.m2049r.xmrwallet.R; -import com.m2049r.xmrwallet.util.Helper; -public class DonationFragment extends DialogFragment { +public class CreditsFragment extends DialogFragment { static final String TAG = "DonationFragment"; - public static DonationFragment newInstance() { - return new DonationFragment(); + public static CreditsFragment newInstance() { + return new CreditsFragment(); } public static void display(FragmentManager fm) { @@ -47,24 +45,14 @@ public class DonationFragment extends DialogFragment { ft.remove(prev); } - DonationFragment.newInstance().show(ft, TAG); + CreditsFragment.newInstance().show(ft, TAG); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_donation, null); + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_credits, null); - ((TextView) view.findViewById(R.id.tvCredits)).setText(Html.fromHtml(getString(R.string.donation_credits))); - - (view.findViewById(R.id.bCopyAddress)). - setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_address), - ((TextView) view.findViewById(R.id.tvWalletAddress)).getText().toString()); - Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show(); - } - }); + ((TextView) view.findViewById(R.id.tvCredits)).setText(Html.fromHtml(getString(R.string.credits_text))); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setView(view); diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java index 77ad8cd..984eb11 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendAddressWizardFragment.java @@ -212,7 +212,7 @@ public class SendAddressWizardFragment extends SendWizardFragment { private boolean checkAddressNoError() { String address = etAddress.getEditText().getText().toString(); return Wallet.isAddressValid(address) - || BitcoinAddressValidator.validate(address, WalletManager.getInstance().isTestNet()); + || BitcoinAddressValidator.validate(address); } private boolean checkAddress() { @@ -228,13 +228,13 @@ public class SendAddressWizardFragment extends SendWizardFragment { private boolean isIntegratedAddress() { String address = etAddress.getEditText().getText().toString(); return (address.length() == INTEGRATED_ADDRESS_LENGTH) - && Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet()); + && Wallet.isAddressValid(address); } private boolean isBitcoinAddress() { String address = etAddress.getEditText().getText().toString(); if ((address.length() >= 27) && (address.length() <= 34)) - return BitcoinAddressValidator.validate(address, WalletManager.getInstance().isTestNet()); + return BitcoinAddressValidator.validate(address); else return false; } diff --git a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendSettingsWizardFragment.java b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendSettingsWizardFragment.java index 42da401..2fc78c0 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendSettingsWizardFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/fragment/send/SendSettingsWizardFragment.java @@ -54,7 +54,8 @@ public class SendSettingsWizardFragment extends SendWizardFragment { TxData getTxData(); } - final static int Mixins[] = {4, 7, 12, 25}; // must match the layout XML + // Mixin = Ringsize - 1 + final static int Mixins[] = {6, 9, 12, 25}; // must match the layout XML / "@array/mixin" final static PendingTransaction.Priority Priorities[] = {PendingTransaction.Priority.Priority_Default, PendingTransaction.Priority.Priority_Low, diff --git a/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java b/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java index c0f0bdf..c739c08 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java +++ b/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java @@ -137,12 +137,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter 35) return false; diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java index b771b6c..0c8ea06 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java +++ b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java @@ -31,12 +31,15 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.VectorDrawable; import android.os.Environment; import android.support.v4.content.ContextCompat; +import android.system.ErrnoException; +import android.system.Os; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.inputmethod.InputMethodManager; import com.m2049r.xmrwallet.R; +import com.m2049r.xmrwallet.model.NetworkType; import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.WalletManager; @@ -55,16 +58,21 @@ import timber.log.Timber; public class Helper { static private final String WALLET_DIR = "monerujo"; + static private final String HOME_DIR = "monero"; static public int DISPLAY_DIGITS_INFO = 5; - static public File getStorageRoot(Context context) { + static public File getWalletRoot(Context context) { + return getStorage(context, WALLET_DIR); + } + + static public File getStorage(Context context, String folderName) { if (!isExternalStorageWritable()) { String msg = context.getString(R.string.message_strorage_not_writable); Timber.e(msg); throw new IllegalStateException(msg); } - File dir = new File(Environment.getExternalStorageDirectory(), WALLET_DIR); + File dir = new File(Environment.getExternalStorageDirectory(), folderName); if (!dir.exists()) { Timber.i("Creating %s", dir.getAbsolutePath()); dir.mkdirs(); // try to make it @@ -114,9 +122,9 @@ public class Helper { } static public File getWalletFile(Context context, String aWalletName) { - File walletDir = getStorageRoot(context); + File walletDir = getWalletRoot(context); File f = new File(walletDir, aWalletName); - Timber.d("wallet= %s size= %d", f.getAbsolutePath(), f.length()); + Timber.d("wallet=%s size= %d", f.getAbsolutePath(), f.length()); return f; } @@ -263,10 +271,20 @@ public class Helper { } static public HttpUrl getXmrToBaseUrl() { - if ((WalletManager.getInstance() == null) || WalletManager.getInstance().isTestNet()) { + if ((WalletManager.getInstance() == null) + || (WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet)) { return HttpUrl.parse("https://test.xmr.to/api/v2/xmr2btc/"); } else { return HttpUrl.parse("https://xmr.to/api/v2/xmr2btc/"); } } + + static public void setMoneroHome(Context context) { + try { + String home = getStorage(context, HOME_DIR).getAbsolutePath(); + Os.setenv("HOME", home, true); + } catch (ErrnoException ex) { + throw new IllegalStateException(ex); + } + } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/widget/Toolbar.java b/app/src/main/java/com/m2049r/xmrwallet/widget/Toolbar.java index e06c081..8f96d12 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/widget/Toolbar.java +++ b/app/src/main/java/com/m2049r/xmrwallet/widget/Toolbar.java @@ -45,7 +45,7 @@ public class Toolbar extends android.support.v7.widget.Toolbar { ImageView toolbarImage; TextView toolbarTitle; TextView toolbarSubtitle; - Button bDonate; + Button bCredits; public Toolbar(Context context) { super(context); @@ -87,8 +87,8 @@ public class Toolbar extends android.support.v7.widget.Toolbar { toolbarTitle = (TextView) findViewById(R.id.toolbarTitle); toolbarSubtitle = (TextView) findViewById(R.id.toolbarSubtitle); - bDonate = (Button) findViewById(R.id.bDonate); - bDonate.setOnClickListener(new View.OnClickListener() { + bCredits = (Button) findViewById(R.id.bCredits); + bCredits.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (onButtonListener != null) { onButtonListener.onButton(buttonType); @@ -116,43 +116,43 @@ public class Toolbar extends android.support.v7.widget.Toolbar { public final static int BUTTON_NONE = 0; public final static int BUTTON_BACK = 1; public final static int BUTTON_CLOSE = 2; - public final static int BUTTON_DONATE = 3; + public final static int BUTTON_CREDITS = 3; public final static int BUTTON_CANCEL = 4; - int buttonType = BUTTON_DONATE; + int buttonType = BUTTON_CREDITS; public void setButton(int type) { switch (type) { case BUTTON_BACK: Timber.d("BUTTON_BACK"); - bDonate.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_arrow_back_white_24dp, 0, 0, 0); - bDonate.setText(null); - bDonate.setVisibility(View.VISIBLE); + bCredits.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_arrow_back_white_24dp, 0, 0, 0); + bCredits.setText(null); + bCredits.setVisibility(View.VISIBLE); break; case BUTTON_CLOSE: Timber.d("BUTTON_CLOSE"); - bDonate.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_close_white_24dp, 0, 0, 0); - bDonate.setText(R.string.label_close); - bDonate.setVisibility(View.VISIBLE); + bCredits.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_close_white_24dp, 0, 0, 0); + bCredits.setText(R.string.label_close); + bCredits.setVisibility(View.VISIBLE); break; - case BUTTON_DONATE: - Timber.d("BUTTON_DONATE"); - bDonate.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_favorite_white_24dp, 0, 0, 0); - bDonate.setText(R.string.label_donate); - bDonate.setVisibility(View.VISIBLE); + case BUTTON_CREDITS: + Timber.d("BUTTON_CREDITS"); + bCredits.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_favorite_white_24dp, 0, 0, 0); + bCredits.setText(R.string.label_credits); + bCredits.setVisibility(View.VISIBLE); break; case BUTTON_CANCEL: Timber.d("BUTTON_CANCEL"); - bDonate.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_close_white_24dp, 0, 0, 0); - bDonate.setText(R.string.label_cancel); - bDonate.setVisibility(View.VISIBLE); + bCredits.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_close_white_24dp, 0, 0, 0); + bCredits.setText(R.string.label_cancel); + bCredits.setVisibility(View.VISIBLE); break; case BUTTON_NONE: default: Timber.d("BUTTON_NONE"); - bDonate.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - bDonate.setText(null); - bDonate.setVisibility(View.INVISIBLE); + bCredits.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + bCredits.setText(null); + bCredits.setVisibility(View.INVISIBLE); } buttonType = type; } diff --git a/app/src/main/res/drawable/gunther_donate.png b/app/src/main/res/drawable/gunther_coder.png similarity index 100% rename from app/src/main/res/drawable/gunther_donate.png rename to app/src/main/res/drawable/gunther_coder.png diff --git a/app/src/main/res/layout/fragment_credits.xml b/app/src/main/res/layout/fragment_credits.xml new file mode 100644 index 0000000..5d2128b --- /dev/null +++ b/app/src/main/res/layout/fragment_credits.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_donation.xml b/app/src/main/res/layout/fragment_donation.xml deleted file mode 100644 index 835fa82..0000000 --- a/app/src/main/res/layout/fragment_donation.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/view_toolbar.xml b/app/src/main/res/layout/view_toolbar.xml index 597d919..2c68671 100644 --- a/app/src/main/res/layout/view_toolbar.xml +++ b/app/src/main/res/layout/view_toolbar.xml @@ -3,12 +3,12 @@ xmlns:tools="http://schemas.android.com/tools">