1
mirror of https://github.com/m2049r/xmrwallet synced 2024-11-24 14:37:14 +01:00

changes for monero v0.12 (#214)

* new version id & name
* witness checksums
* build docs updated for v0.12
* remove binaries
* setenv HOME for ringdb to 'monero' in shared storage
* min ringsize 7
* remove boost_locale and zmq from build - don't need them for wallet_api
* splits for all archs
* throw IndexOutOfBounds in case the TX is empty
* donate, you ungrateful bastards! (removed donations to make google happy)
This commit is contained in:
m2049r 2018-03-29 22:35:31 +02:00 committed by GitHub
parent b1f530e64a
commit a9092497b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
164 changed files with 943 additions and 548 deletions

View File

@ -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

View File

@ -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',
]
}

View File

@ -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<Monero::NetworkType>(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<Monero::NetworkType>(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<Monero::NetworkType>(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<Monero::NetworkType>(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<jboolean>(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<jboolean>(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<jboolean>(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<jboolean>(success);
}
JNIEXPORT jboolean JNICALL
Java_com_m2049r_xmrwallet_model_WalletManager_stopMining(JNIEnv *env, jobject instance) {
return Bitmonero::WalletManagerFactory::getWalletManager()->stopMining();
return static_cast<jboolean>(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<jboolean>(closeSuccess);
}
@ -543,7 +547,7 @@ Java_com_m2049r_xmrwallet_model_Wallet_setPassword(JNIEnv *env, jobject instance
Bitmonero::Wallet *wallet = getHandle<Bitmonero::Wallet>(env, instance);
bool success = wallet->setPassword(std::string(_password));
env->ReleaseStringUTFChars(password, _password);
return success;
return static_cast<jboolean>(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<Bitmonero::Wallet>(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<jboolean>(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<Bitmonero::Wallet>(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<jboolean>(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<Bitmonero::Wallet>(env, instance);
return wallet->watchOnly();
return static_cast<jboolean>(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<Bitmonero::Wallet>(env, instance);
return wallet->synchronized();
return static_cast<jboolean>(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<jboolean>(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<Monero::NetworkType>(networkType);
bool isValid = Bitmonero::Wallet::addressValid(_address, _networkType);
env->ReleaseStringUTFChars(address, _address);
return isValid;
return static_cast<jboolean>(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<Monero::NetworkType>(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<Bitmonero::Wallet>(env, instance);
return wallet->refresh();
return static_cast<jboolean>(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<jboolean>(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<jboolean>(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<Bitmonero::PendingTransaction>(env, instance);
std::vector<std::string> txids = tx->txid();
return env->NewStringUTF(txids.front().c_str());
if (!txids.empty())
return env->NewStringUTF(txids.front().c_str());
else
return nullptr;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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<WalletNode, Void, Integer> {
@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -137,12 +137,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
ivTxType.setVisibility(View.GONE); // gives us more space for the amount
}
long realAmount = infoItem.amount;
if (infoItem.isPending) {
realAmount = realAmount - infoItem.fee;
}
String displayAmount = Helper.getDisplayAmount(realAmount, Helper.DISPLAY_DIGITS_INFO);
String displayAmount = Helper.getDisplayAmount(infoItem.amount, Helper.DISPLAY_DIGITS_INFO);
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
tvAmount.setText(context.getString(R.string.tx_list_amount_negative, displayAmount));
} else {

View File

@ -0,0 +1,45 @@
/*
* 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.model;
public enum NetworkType {
NetworkType_Mainnet(0),
NetworkType_Testnet(1),
NetworkType_Stagenet(2);
public static NetworkType fromInteger(int n) {
switch (n) {
case 0:
return NetworkType_Mainnet;
case 1:
return NetworkType_Testnet;
case 2:
return NetworkType_Stagenet;
}
return null;
}
public int getValue() {
return value;
}
private int value;
NetworkType(int value) {
this.value = value;
}
}

View File

@ -84,7 +84,14 @@ public class PendingTransaction {
public native long getFee();
public native String getFirstTxId();
public String getFirstTxId() {
String id = getFirstTxIdJ();
if (id == null)
throw new IndexOutOfBoundsException();
return id;
}
public native String getFirstTxIdJ();
public native long getTxCount();

View File

@ -79,7 +79,11 @@ public class Wallet {
public native String getPath();
public native boolean isTestNet();
public NetworkType getNetworkType() {
return NetworkType.fromInteger(nettype());
}
public native int nettype();
//TODO virtual void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const = 0;
//TODO virtual bool useForkRules(uint8_t version, int64_t early_blocks) const = 0;
@ -155,10 +159,10 @@ public class Wallet {
public static native boolean isPaymentIdValid(String payment_id);
public static boolean isAddressValid(String address) {
return isAddressValid(address, WalletManager.getInstance().isTestNet());
return isAddressValid(address, WalletManager.getInstance().getNetworkType().getValue());
}
public static native boolean isAddressValid(String address, boolean isTestNet);
public static native boolean isAddressValid(String address, int networkType);
//TODO static static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);

View File

@ -16,6 +16,8 @@
package com.m2049r.xmrwallet.model;
import com.m2049r.xmrwallet.data.WalletNode;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@ -69,22 +71,22 @@ public class WalletManager {
}
public Wallet createWallet(File aFile, String password, String language) {
long walletHandle = createWalletJ(aFile.getAbsolutePath(), password, language, isTestNet());
long walletHandle = createWalletJ(aFile.getAbsolutePath(), password, language, getNetworkType().getValue());
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet);
return wallet;
}
private native long createWalletJ(String path, String password, String language, boolean isTestNet);
private native long createWalletJ(String path, String password, String language, int networkType);
public Wallet openWallet(String path, String password) {
long walletHandle = openWalletJ(path, password, isTestNet());
long walletHandle = openWalletJ(path, password, getNetworkType().getValue());
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet);
return wallet;
}
private native long openWalletJ(String path, String password, boolean isTestNet);
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);
@ -92,28 +94,28 @@ public class WalletManager {
public Wallet recoveryWallet(File aFile, String password, String mnemonic, long restoreHeight) {
long walletHandle = recoveryWalletJ(aFile.getAbsolutePath(), password, mnemonic,
isTestNet(), restoreHeight);
getNetworkType().getValue(), restoreHeight);
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet);
return wallet;
}
private native long recoveryWalletJ(String path, String password, String mnemonic,
boolean isTestNet, long restoreHeight);
int networkType, long restoreHeight);
public Wallet createWalletWithKeys(File aFile, String password, String language, long restoreHeight,
String addressString, String viewKeyString, String spendKeyString) {
long walletHandle = createWalletWithKeysJ(aFile.getAbsolutePath(), password,
language, isTestNet(), restoreHeight,
long walletHandle = createWalletFromKeysJ(aFile.getAbsolutePath(), password,
language, getNetworkType().getValue(), restoreHeight,
addressString, viewKeyString, spendKeyString);
Wallet wallet = new Wallet(walletHandle);
manageWallet(wallet);
return wallet;
}
private native long createWalletWithKeysJ(String path, String password,
private native long createWalletFromKeysJ(String path, String password,
String language,
boolean isTestNet,
int networkType,
long restoreHeight,
String addressString,
String viewKeyString,
@ -204,24 +206,23 @@ public class WalletManager {
//TODO virtual bool checkPayment(const std::string &address, const std::string &txid, const std::string &txkey, const std::string &daemon_address, uint64_t &received, uint64_t &height, std::string &error) const = 0;
private String daemonAddress = null;
private boolean testnet = true;
private NetworkType networkType = null;
public boolean isTestNet() {
if (daemonAddress == null) {
return true;
// assume testnet not explicitly initialised
//throw new IllegalStateException("use setDaemon() to initialise daemon and net first!");
}
return testnet;
public NetworkType getNetworkType() {
return networkType;
}
public void setDaemon(String address, boolean testnet, String username, String password) {
//Timber.d("SETDAEMON " + username + "/" + password + "/" + address);
this.daemonAddress = address;
this.testnet = testnet;
this.daemonUsername = username;
this.daemonPassword = password;
setDaemonAddressJ(address);
//public void setDaemon(String address, NetworkType networkType, String username, String password) {
public void setDaemon(WalletNode walletNode) {
this.daemonAddress = walletNode.getAddress();
this.networkType = networkType;
this.daemonUsername = walletNode.getUsername();
this.daemonPassword = walletNode.getPassword();
setDaemonAddressJ(daemonAddress);
}
public void setNetworkType(NetworkType networkType) {
this.networkType = networkType;
}
public String getDaemonAddress() {

View File

@ -524,7 +524,7 @@ public class WalletService extends Service {
showProgress(20);
Wallet wallet = null;
WalletManager walletMgr = WalletManager.getInstance();
Timber.d("WalletManager testnet=%s", walletMgr.isTestNet());
Timber.d("WalletManager network=%s", walletMgr.getNetworkType().name());
showProgress(30);
if (walletMgr.walletExists(path)) {
Timber.d("open wallet %s", path);

View File

@ -18,6 +18,9 @@ package com.m2049r.xmrwallet.util;
// based on https://rosettacode.org/wiki/Bitcoin/address_validation#Java
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.model.WalletManager;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -27,6 +30,11 @@ public class BitcoinAddressValidator {
private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
public static boolean validate(String addrress) {
return validate(addrress,
WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet);
}
public static boolean validate(String addrress, boolean testnet) {
if (addrress.length() < 26 || addrress.length() > 35)
return false;

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingEnd="16dp"
android:paddingStart="16dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:src="@drawable/gunther_coder" />
<TextView
android:id="@+id/tvCredits"
style="@style/MoneroText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/header_top"
android:autoLink="web"
android:gravity="center"
android:text="@string/credits_text" />
</LinearLayout>
</ScrollView>

View File

@ -1,79 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingEnd="16dp"
android:paddingStart="16dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:src="@drawable/gunther_donate" />
<TextView
style="@style/MoneroText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/donation_text"
android:textSize="14sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/header_top"
android:background="@drawable/backgound_spinner"
android:orientation="vertical"
android:padding="@dimen/header_top">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
style="@style/MoneroLabel.Heading.Donation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:text="@string/donation_address_label" />
<ImageButton
android:id="@+id/bCopyAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="8dp"
android:background="?android:selectableItemBackground"
android:src="@drawable/ic_content_copy_black_24dp" />
</FrameLayout>
<TextView
android:id="@+id/tvWalletAddress"
style="@style/MoneroText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/data_top"
android:text="@string/donation_address"
android:textAlignment="center"
android:textColor="@color/moneroBlack"
android:textSize="17sp" />
</LinearLayout>
<TextView
android:id="@+id/tvCredits"
style="@style/MoneroText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/header_top"
android:autoLink="web"
android:gravity="center"
android:text="@string/donation_credits" />
</LinearLayout>
</ScrollView>

View File

@ -3,12 +3,12 @@
xmlns:tools="http://schemas.android.com/tools">
<Button
android:id="@+id/bDonate"
android:id="@+id/bCredits"
style="@style/ToolBarStyle.ActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_favorite_white_24dp"
android:text="@string/label_donate" />
android:text="@string/label_credits" />
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"

View File

@ -3,10 +3,10 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_donate"
android:id="@+id/action_credits"
android:icon="@drawable/ic_favorite_white_24dp"
android:orderInCategory="10"
android:title="@string/label_donate"
android:title="@string/label_credits"
app:showAsAction="ifRoom" />
<item

View File

@ -4,13 +4,7 @@
<string name="about_close">Cerrar</string>
<string name="about_version">Versión %1$s (%2$d)</string>
<string name="donation_text">
\"¡Donad, bastardos ingratos!\"
</string>
<string name="donation_address_label">Donaciones</string>
<string name="donation_credits"><![CDATA[
<string name="credits_text"><![CDATA[
<b>Créditos</b>
<br/>
m2049r, baltsar777, anhdres, keejef,

View File

@ -20,7 +20,7 @@
<string name="password_very_strong">¡Bien ahí, hacker nivel 4!</string>
<string name="label_login_wallets">Monederos</string>
<string name="label_donate">Donar</string>
<string name="label_credits">Créditos</string>
<string name="label_ok">Aceptar</string>
<string name="label_cancel">Cancelar</string>
<string name="label_close">Cerrar</string>
@ -59,6 +59,7 @@
<string name="label_daemon">Nodo</string>
<string name="prompt_daemon">([&lt;usuario&gt;:&lt;contraseña&gt;@]&lt;daemon&gt;[:&lt;puerto&gt;])</string>
<string name="prompt_mainnet">Selección de Red</string>
<string name="connect_stagenet">StageNet</string>
<string name="connect_testnet">TestNet</string>
<string name="connect_mainnet">MainNet</string>
<string name="status_walletlist_loading">Cargando lista de monederos</string>

View File

@ -5,14 +5,7 @@
<string name="about_whoami">I am monerujo</string>
<string name="about_version">Version %1$s (%2$d)</string>
<string name="donation_text">
\"Donate you ungrateful bastards!\"
</string>
<string name="donation_address_label">Donations Address</string>
<string name="donation_address" translatable="false">4AdkPJoxn7JCvAby9szgnt93MSEwdnxdhaASxbTBm6x5dCwmsDep2UYN4FhStDn5i11nsJbpU7oj59ahg8gXb1Mg3viqCuk</string>
<string name="donation_credits"><![CDATA[
<string name="credits_text"><![CDATA[
<b>Credits</b>
<br/>
m2049r, baltsar777, anhdres, keejef,

View File

@ -22,7 +22,7 @@
<string name="password_very_strong">Yeah baby, h4x0r style!</string>
<string name="label_login_wallets">Wallets</string>
<string name="label_donate">Donate</string>
<string name="label_credits">Credits</string>
<string name="label_ok">OK</string>
<string name="label_cancel">Cancel</string>
<string name="label_close">Close</string>
@ -124,6 +124,7 @@
<string name="label_daemon">Node</string>
<string name="prompt_daemon">([&lt;user&gt;:&lt;pass&gt;@]&lt;daemon&gt;[:&lt;port&gt;])</string>
<string name="prompt_mainnet">Net Selection</string>
<string name="connect_stagenet">StageNet</string>
<string name="connect_testnet">TestNet</string>
<string name="connect_mainnet">MainNet</string>
<string name="status_walletlist_loading">Loading Wallet List</string>
@ -348,8 +349,8 @@
<string name="archive_alert_no">No thanks!</string>
<string-array name="mixin" translatable="false">
<item>Ringsize 5</item>
<item>Ringsize 8</item>
<item>Ringsize 7</item>
<item>Ringsize 10</item>
<item>Ringsize 13</item>
<item>Ringsize 26</item>
</string-array>

View File

@ -4,27 +4,35 @@ Based on https://forum.getmonero.org/5/support/87643/building-monero-v0-10-3-1-f
Do not follow this blindly.
These instructions are tailored to building ```wallep_api```.
These instructions build all supported architectures: ```'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'```.
Yes, lots of copy&paste here. TODO: Script this.
## Prepare Ubuntu environment
```
```Shell
sudo apt-get install build-essential cmake tofrodos libtool-bin
sudo mkdir /opt/android
sudo chown $LOGNAME /opt/android
```
## Install Android NDK
```
```Shell
cd /opt/android
wget https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip
unzip android-ndk-r15c-linux-x86_64.zip
android-ndk-r15c/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch arm --install-dir /opt/android/tool32
android-ndk-r15c/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch arm64 --install-dir /opt/android/tool64
android-ndk-r15c/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch x86 --install-dir /opt/android/toolx86
android-ndk-r15c/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch x86_64 --install-dir /opt/android/toolx86_64
wget https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip
unzip android-ndk-r16b-linux-x86_64.zip
ln -s android-ndk-r16b ndk
ndk/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch arm --install-dir /opt/android/tool/arm
ndk/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch arm64 --install-dir /opt/android/tool/arm64
ndk/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch x86 --install-dir /opt/android/tool/x86
ndk/build/tools/make_standalone_toolchain.py --api 21 --stl=libc++ --arch x86_64 --install-dir /opt/android/tool/x86_64
```
## Prepare output
```Shell
mkdir -p /opt/android/build
```
## Build OpenSSL
@ -32,131 +40,81 @@ Best is to compile openssl from sources. Copying from your phone or elsewhere (d
If you don't want to build for all architectures, edit ```build-all-arch.sh``` before running it (Line 12).
```
```Shell
cd /opt/android
git clone https://github.com/m2049r/android-openssl.git
wget https://github.com/openssl/openssl/archive/OpenSSL_1_0_2l.tar.gz
cd android-openssl
tar xfz ../OpenSSL_1_0_2l.tar.gz
export ANDROID_NDK_ROOT=/opt/android/android-ndk-r15c
./build-all-arch.sh
ANDROID_NDK_ROOT=/opt/android/ndk ./build-all-arch.sh
```
### Make symlinks
### Install & make symlinks
```Shell
mkdir -p /opt/android/build/openssl/{arm,arm64,x86,x86_64}
cp -a /opt/android/android-openssl/prebuilt/armeabi /opt/android/build/openssl/arm/lib
cp -a /opt/android/android-openssl/prebuilt/arm64-v8a /opt/android/build/openssl/arm64/lib
cp -a /opt/android/android-openssl/prebuilt/x86 /opt/android/build/openssl/x86/lib
cp -a /opt/android/android-openssl/prebuilt/x86_64 /opt/android/build/openssl/x86_64/lib
cp -aL /opt/android/android-openssl/openssl-OpenSSL_1_0_2l/include/openssl/ /opt/android/build/openssl/include
ln -s /opt/android/build/openssl/include /opt/android/build/openssl/arm/include
ln -s /opt/android/build/openssl/include /opt/android/build/openssl/arm64/include
ln -s /opt/android/build/openssl/include /opt/android/build/openssl/x86/include
ln -s /opt/android/build/openssl/include /opt/android/build/openssl/x86_64/include
```
cd /opt/android/tool32/sysroot/usr/include
ln -s ../../../../android-openssl/openssl-OpenSSL_1_0_2l/include/openssl/
cd /opt/android/tool32/sysroot/usr/lib
ln -s ../../../../android-openssl/prebuilt/armeabi/libssl.so
ln -s ../../../../android-openssl/prebuilt/armeabi/libcrypto.so
```Shell
ln -sf /opt/android/build/openssl/include /opt/android/tool/arm/sysroot/usr/include/openssl
ln -sf /opt/android/build/openssl/lib/armeabi-v7a/*.so /opt/android/tool/arm/sysroot/usr/lib
cd /opt/android/tool64/sysroot/usr/include
ln -s ../../../../android-openssl/openssl-OpenSSL_1_0_2l/include/openssl/
cd /opt/android/tool64/sysroot/usr/lib
ln -s ../../../../android-openssl/prebuilt/arm64-v8a/libssl.so
ln -s ../../../../android-openssl/prebuilt/arm64-v8a/libcrypto.so
ln -sf /opt/android/build/openssl/include /opt/android/tool/arm64/sysroot/usr/include/openssl
ln -sf /opt/android/build/openssl/lib/arm64-v8a/*.so /opt/android/tool/arm64/sysroot/usr/lib
cd /opt/android/toolx86/sysroot/usr/include
ln -s ../../../../android-openssl/openssl-OpenSSL_1_0_2l/include/openssl/
cd /opt/android/toolx86/sysroot/usr/lib
ln -s ../../../../android-openssl/prebuilt/x86/libssl.so
ln -s ../../../../android-openssl/prebuilt/x86/libcrypto.so
ln -sf /opt/android/build/openssl/include /opt/android/tool/x86/sysroot/usr/include/openssl
ln -sf /opt/android/build/openssl/lib/x86/*.so /opt/android/tool/x86/sysroot/usr/lib
cd /opt/android/toolx86_64/sysroot/usr/include
ln -s ../../../../android-openssl/openssl-OpenSSL_1_0_2l/include/openssl/
cd /opt/android/toolx86_64/sysroot/usr/lib
ln -s ../../../../android-openssl/prebuilt/x86_64/libssl.so
ln -s ../../../../android-openssl/prebuilt/x86_64/libcrypto.so
ln -sf /opt/android/build/openssl/include /opt/android/tool/x86_64/sysroot/usr/include/openssl
ln -sf /opt/android/build/openssl/lib/x86_64/*.so /opt/android/tool/x86_64/sysroot/usr/lib64
```
## Build Boost
```
```Shell
cd /opt/android
wget https://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.gz/download -O boost_1_58_0.tar.gz
tar xfz boost_1_58_0.tar.gz
cd boost_1_58_0
./bootstrap.sh
```
The NDK r15c above gives errors about fsetpos and fgetpos not found(!?!), so we "just" comment them out in the include file:
* `vi /opt/android/tool32/include/c++/4.9.x/cstdio` (`//using ::fgetpos`, `//using ::fsetpos`)
* `vi /opt/android/tool64/include/c++/4.9.x/cstdio` (`//using ::fgetpos`, `//using ::fsetpos`)
* `vi /opt/android/toolx86/include/c++/4.9.x/cstdio` (`//using ::fgetpos`, `//using ::fsetpos`)
* `vi /opt/android/toolx86_64/include/c++/4.9.x/cstdio` (`//using ::fgetpos`, `//using ::fsetpos`)
Comment out ```using ::fgetpos;``` & ```using ::fsetpos;``` in ```cstdio```.
Then:
```
PATH=/opt/android/tool32/arm-linux-androideabi/bin:/opt/android/tool32/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=android32 --stagedir=android32 toolset=clang threading=multi threadapi=pthread target-os=android stage
PATH=/opt/android/tool64/aarch64-linux-android/bin:/opt/android/tool64/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=android64 --stagedir=android64 toolset=clang threading=multi threadapi=pthread target-os=android stage
PATH=/opt/android/toolx86/i686-linux-android/bin:/opt/android/toolx86/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=androidx86 --stagedir=androidx86 toolset=clang threading=multi threadapi=pthread target-os=android stage
PATH=/opt/android/toolx86_64/x86_64-linux-android/bin:/opt/android/toolx86_64/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=androidx86_64 --stagedir=androidx86_64 toolset=clang threading=multi threadapi=pthread target-os=android stage
Then build & install to ```/opt/android/build/boost``` with
```Shell
PATH=/opt/android/tool/arm/arm-linux-androideabi/bin:/opt/android/tool/arm/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=android-arm --prefix=/opt/android/build/boost/arm --includedir=/opt/android/build/boost/include toolset=clang threading=multi threadapi=pthread target-os=android install
ln -sf ../include /opt/android/build/boost/arm
PATH=/opt/android/tool/arm64/aarch64-linux-android/bin:/opt/android/tool/arm64/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=android-arm64 --prefix=/opt/android/build/boost/arm64 --includedir=/opt/android/build/boost/include toolset=clang threading=multi threadapi=pthread target-os=android install
ln -sf ../include /opt/android/build/boost/arm64
PATH=/opt/android/tool/x86/i686-linux-android/bin:/opt/android/tool/x86/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=android-x86 --prefix=/opt/android/build/boost/x86 --includedir=/opt/android/build/boost/include toolset=clang threading=multi threadapi=pthread target-os=android install
ln -sf ../include /opt/android/build/boost/x86
PATH=/opt/android/tool/x86_64/x86_64-linux-android/bin:/opt/android/tool/x86_64/bin:$PATH ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --build-dir=android-x86_64 --prefix=/opt/android/build/boost/x86_64 --includedir=/opt/android/build/boost/include toolset=clang threading=multi threadapi=pthread target-os=android install
ln -sf ../include /opt/android/build/boost/x86_64
```
## And finally: Build Monero
```
```Shell
cd /opt/android
git clone https://github.com/m2049r/monero.git
cd /opt/android/monero
mkdir -p build/release.android32
cd build/release.android32
PATH=/opt/android/tool32/arm-linux-androideabi/bin:/opt/android/tool32/bin:$PATH CC=clang CXX=clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android" -D BOOST_ROOT=/opt/android/boost_1_58_0 -D BOOST_LIBRARYDIR=/opt/android/boost_1_58_0/android32/lib -D OPENSSL_ROOT_DIR=/opt/android/android-openssl/openssl-OpenSSL_1_0_2l -D OPENSSL_CRYPTO_LIBRARY=/opt/android/android-openssl/prebuilt/armeabi/libcrypto.so -D OPENSSL_SSL_LIBRARY=/opt/android/android-openssl/prebuilt/armeabi/libssl.so -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true ../..
make
find . -name '*.a' -exec cp '{}' lib \;
cd /opt/android/monero
mkdir -p build/release.android64
cd build/release.android64
PATH=/opt/android/tool64/aarch64-linux-android/bin:/opt/android/tool64/bin:$PATH CC=clang CXX=clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv8-a" -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android" -D BOOST_ROOT=/opt/android/boost_1_58_0 -D BOOST_LIBRARYDIR=/opt/android/boost_1_58_0/android64/lib -D OPENSSL_ROOT_DIR=/opt/android/android-openssl/openssl-OpenSSL_1_0_2l -D OPENSSL_CRYPTO_LIBRARY=/opt/android/android-openssl/prebuilt/arm64-v8a/libcrypto.so -D OPENSSL_SSL_LIBRARY=/opt/android/android-openssl/prebuilt/arm64-v8a/libssl.so -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true ../..
make
find . -name '*.a' -exec cp '{}' lib \;
cd /opt/android/monero
mkdir -p build/release.androidx86
cd build/release.androidx86
PATH=/opt/android/toolx86/i686-linux-android/bin:/opt/android/toolx86/bin:$PATH CC=clang CXX=clang++ cmake -D BUILD_TESTS=OFF -D ARCH="i686" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android" -D BOOST_ROOT=/opt/android/boost_1_58_0 -D BOOST_LIBRARYDIR=/opt/android/boost_1_58_0/androidx86/lib -D OPENSSL_ROOT_DIR=/opt/android/android-openssl/openssl-OpenSSL_1_0_2l -D OPENSSL_CRYPTO_LIBRARY=/opt/android/android-openssl/prebuilt/x86/libcrypto.so -D OPENSSL_SSL_LIBRARY=/opt/android/android-openssl/prebuilt/x86/libssl.so -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true ../..
make
find . -name '*.a' -exec cp '{}' lib \;
cd /opt/android/monero
mkdir -p build/release.androidx86_64
cd build/release.androidx86_64
PATH=/opt/android/toolx86_64/x86_64-linux-android/bin:/opt/android/toolx86_64/bin:$PATH CC=clang CXX=clang++ cmake -D BUILD_TESTS=OFF -D ARCH="x86-64" -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D BUILD_TAG="android" -D BOOST_ROOT=/opt/android/boost_1_58_0 -D BOOST_LIBRARYDIR=/opt/android/boost_1_58_0/androidx86_64/lib -D OPENSSL_ROOT_DIR=/opt/android/android-openssl/openssl-OpenSSL_1_0_2l -D OPENSSL_CRYPTO_LIBRARY=/opt/android/android-openssl/prebuilt/x86_64/libcrypto.so -D OPENSSL_SSL_LIBRARY=/opt/android/android-openssl/prebuilt/x86_64/libssl.so -D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true ../..
make
find . -name '*.a' -exec cp '{}' lib \;
cd /opt/android/monero/build
./build-all-arch.sh
```
Ignore the warning from ```find``` - all monero static libraries are now in `lib`.
# Bringing it all together
- Copy all .a libraries into the appropriate `external-libs` folders.
- Copy `/opt/android/monero/src/wallet/wallet2_api.h` into `external-libs/monero/include`
- Copy `/opt/android/monero/src/wallet/api/wallet2_api.h` into `external-libs/monero/include`
If using default locations, this would mean:
```
mkdir -p ~/StudioProjects/xmrwallet/external-libs/boost/lib/armeabi-v7a
cp -a /opt/android/boost_1_58_0/android32/lib/*.a ~/StudioProjects/xmrwallet/external-libs/boost/lib/armeabi-v7a
mkdir -p ~/StudioProjects/xmrwallet/external-libs/openssl/lib/armeabi-v7a
cp -a /opt/android/android-openssl/prebuilt/armeabi/*.a ~/StudioProjects/xmrwallet/external-libs/openssl/lib/armeabi-v7a
mkdir -p ~/StudioProjects/xmrwallet/external-libs/monero/lib/armeabi-v7a
cp -a /opt/android/monero/build/release.android32/lib/*.a ~/StudioProjects/xmrwallet/external-libs/monero/lib/armeabi-v7a
mkdir -p ~/StudioProjects/xmrwallet/external-libs/boost/lib/arm64-v8a
cp -a /opt/android/boost_1_58_0/android64/lib/*.a ~/StudioProjects/xmrwallet/external-libs/boost/lib/arm64-v8a
mkdir -p ~/StudioProjects/xmrwallet/external-libs/openssl/lib/arm64-v8a
cp -a /opt/android/android-openssl/prebuilt/arm64-v8a/*.a ~/StudioProjects/xmrwallet/external-libs/openssl/lib/arm64-v8a
mkdir -p ~/StudioProjects/xmrwallet/external-libs/monero/lib/arm64-v8a
cp -a /opt/android/monero/build/release.android64/lib/*.a ~/StudioProjects/xmrwallet/external-libs/monero/lib/arm64-v8a
mkdir -p ~/StudioProjects/xmrwallet/external-libs/boost/lib/x86
cp -a /opt/android/boost_1_58_0/androidx86/lib/*.a ~/StudioProjects/xmrwallet/external-libs/boost/lib/x86
mkdir -p ~/StudioProjects/xmrwallet/external-libs/openssl/lib/x86
cp -a /opt/android/android-openssl/prebuilt/x86/*.a ~/StudioProjects/xmrwallet/external-libs/openssl/lib/x86
mkdir -p ~/StudioProjects/xmrwallet/external-libs/monero/lib/x86
cp -a /opt/android/monero/build/release.androidx86/lib/*.a ~/StudioProjects/xmrwallet/external-libs/monero/lib/x86
mkdir -p ~/StudioProjects/xmrwallet/external-libs/boost/lib/x86_64
cp -a /opt/android/boost_1_58_0/androidx86_64/lib/*.a ~/StudioProjects/xmrwallet/external-libs/boost/lib/x86_64
mkdir -p ~/StudioProjects/xmrwallet/external-libs/openssl/lib/x86_64
cp -a /opt/android/android-openssl/prebuilt/x86_64/*.a ~/StudioProjects/xmrwallet/external-libs/openssl/lib/x86_64
mkdir -p ~/StudioProjects/xmrwallet/external-libs/monero/lib/x86_64
cp -a /opt/android/monero/build/release.androidx86_64/lib/*.a ~/StudioProjects/xmrwallet/external-libs/monero/lib/x86_64
```Shell
cd <path-to-xmrwallet>/external-libs
# remove old stuff
find . -name "*.a" -or -name "*.h" -type f -delete
./collect.sh
```

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

45
external-libs/collect.sh Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
#
# -D BOOST_ROOT=/opt/android/boost_1_58_0
set -e
orig_path=$PATH
packages=(boost openssl monero)
archs=(arm arm64 x86 x86_64)
for arch in ${archs[@]}; do
case ${arch} in
"arm")
xarch="armeabi-v7a"
;;
"arm64")
xarch="arm64-v8a"
;;
"x86")
xarch="x86"
;;
"x86_64")
xarch="x86_64"
;;
*)
exit 16
;;
esac
for package in ${packages[@]}; do
OUTPUT_DIR=`pwd`/$package/lib/$xarch
mkdir -p $OUTPUT_DIR
rm -f $OUTPUT_DIR/*.a
cp -a /opt/android/build/$package/$arch/lib/*.a $OUTPUT_DIR
if [ $package = "monero" -a -d "/opt/android/build/$package/include" ]; then
rm -rf $OUTPUT_DIR/../../include
cp -a /opt/android/build/$package/include $OUTPUT_DIR/../..
fi
done
done
exit 0

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project
// Copyright (c) 2014-2018, The Monero Project
//
// All rights reserved.
//
@ -33,14 +33,23 @@
#include <string>
#include <vector>
#include <list>
#include <set>
#include <ctime>
#include <iostream>
// Public interface for libwallet library
namespace Monero {
enum NetworkType : uint8_t {
MAINNET = 0,
TESTNET,
STAGENET
};
namespace Utils {
bool isAddressLocal(const std::string &hostaddr);
void onStartup();
}
template<typename T>
@ -68,6 +77,7 @@ struct PendingTransaction
};
enum Priority {
Priority_Default = 0,
Priority_Low = 1,
Priority_Medium = 2,
Priority_High = 3,
@ -88,6 +98,8 @@ struct PendingTransaction
* \return
*/
virtual uint64_t txCount() const = 0;
virtual std::vector<uint32_t> subaddrAccount() const = 0;
virtual std::vector<std::set<uint32_t>> subaddrIndices() const = 0;
};
/**
@ -101,13 +113,6 @@ struct UnsignedTransaction
Status_Critical
};
enum Priority {
Priority_Low = 1,
Priority_Medium = 2,
Priority_High = 3,
Priority_Last
};
virtual ~UnsignedTransaction() = 0;
virtual int status() const = 0;
virtual std::string errorString() const = 0;
@ -155,6 +160,9 @@ struct TransactionInfo
virtual uint64_t amount() const = 0;
virtual uint64_t fee() const = 0;
virtual uint64_t blockHeight() const = 0;
virtual std::set<uint32_t> subaddrIndex() const = 0;
virtual uint32_t subaddrAccount() const = 0;
virtual std::string label() const = 0;
virtual uint64_t confirmations() const = 0;
virtual uint64_t unlockTime() const = 0;
//! transaction_id
@ -223,6 +231,66 @@ struct AddressBook
virtual int lookupPaymentID(const std::string &payment_id) const = 0;
};
struct SubaddressRow {
public:
SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label):
m_rowId(_rowId),
m_address(_address),
m_label(_label) {}
private:
std::size_t m_rowId;
std::string m_address;
std::string m_label;
public:
std::string extra;
std::string getAddress() const {return m_address;}
std::string getLabel() const {return m_label;}
std::size_t getRowId() const {return m_rowId;}
};
struct Subaddress
{
virtual ~Subaddress() = 0;
virtual std::vector<SubaddressRow*> getAll() const = 0;
virtual void addRow(uint32_t accountIndex, const std::string &label) = 0;
virtual void setLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label) = 0;
virtual void refresh(uint32_t accountIndex) = 0;
};
struct SubaddressAccountRow {
public:
SubaddressAccountRow(std::size_t _rowId, const std::string &_address, const std::string &_label, const std::string &_balance, const std::string &_unlockedBalance):
m_rowId(_rowId),
m_address(_address),
m_label(_label),
m_balance(_balance),
m_unlockedBalance(_unlockedBalance) {}
private:
std::size_t m_rowId;
std::string m_address;
std::string m_label;
std::string m_balance;
std::string m_unlockedBalance;
public:
std::string extra;
std::string getAddress() const {return m_address;}
std::string getLabel() const {return m_label;}
std::string getBalance() const {return m_balance;}
std::string getUnlockedBalance() const {return m_unlockedBalance;}
std::size_t getRowId() const {return m_rowId;}
};
struct SubaddressAccount
{
virtual ~SubaddressAccount() = 0;
virtual std::vector<SubaddressAccountRow*> getAll() const = 0;
virtual void addRow(const std::string &label) = 0;
virtual void setLabel(uint32_t accountIndex, const std::string &label) = 0;
virtual void refresh() = 0;
};
struct WalletListener
{
virtual ~WalletListener() = 0;
@ -294,9 +362,13 @@ struct Wallet
//! in case error status, returns error string
virtual std::string errorString() const = 0;
virtual bool setPassword(const std::string &password) = 0;
virtual std::string address() const = 0;
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
std::string mainAddress() const { return address(0, 0); }
virtual std::string path() const = 0;
virtual bool testnet() const = 0;
virtual NetworkType nettype() const = 0;
bool mainnet() const { return nettype() == MAINNET; }
bool testnet() const { return nettype() == TESTNET; }
bool stagenet() const { return nettype() == STAGENET; }
//! returns current hard fork info
virtual void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const = 0;
//! check if hard fork rules should be used
@ -360,9 +432,12 @@ struct Wallet
*
* \param daemon_address - daemon address in "hostname:port" format
* \param upper_transaction_size_limit
* \param daemon_username
* \param daemon_password
* \param lightWallet - start wallet in light mode, connect to a openmonero compatible server.
* \return - true on success
*/
virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username = "", const std::string &daemon_password = "") = 0;
virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false) = 0;
/*!
* \brief createWatchOnly - Creates a watch only wallet
@ -406,8 +481,20 @@ struct Wallet
virtual ConnectionStatus connected() const = 0;
virtual void setTrustedDaemon(bool arg) = 0;
virtual bool trustedDaemon() const = 0;
virtual uint64_t balance() const = 0;
virtual uint64_t unlockedBalance() const = 0;
virtual uint64_t balance(uint32_t accountIndex = 0) const = 0;
uint64_t balanceAll() const {
uint64_t result = 0;
for (uint32_t i = 0; i < numSubaddressAccounts(); ++i)
result += balance(i);
return result;
}
virtual uint64_t unlockedBalance(uint32_t accountIndex = 0) const = 0;
uint64_t unlockedBalanceAll() const {
uint64_t result = 0;
for (uint32_t i = 0; i < numSubaddressAccounts(); ++i)
result += unlockedBalance(i);
return result;
}
/**
* @brief watchOnly - checks if wallet is watch only
@ -452,13 +539,28 @@ struct Wallet
static uint64_t amountFromDouble(double amount);
static std::string genPaymentId();
static bool paymentIdValid(const std::string &paiment_id);
static bool addressValid(const std::string &str, bool testnet);
static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
static std::string paymentIdFromAddress(const std::string &str, bool testnet);
static bool addressValid(const std::string &str, NetworkType nettype);
static bool addressValid(const std::string &str, bool testnet) // deprecated
{
return addressValid(str, testnet ? TESTNET : MAINNET);
}
static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, NetworkType nettype, std::string &error);
static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error) // deprecated
{
return keyValid(secret_key_string, address_string, isViewKey, testnet ? TESTNET : MAINNET, error);
}
static std::string paymentIdFromAddress(const std::string &str, NetworkType nettype);
static std::string paymentIdFromAddress(const std::string &str, bool testnet) // deprecated
{
return paymentIdFromAddress(str, testnet ? TESTNET : MAINNET);
}
static uint64_t maximumAllowedAmount();
// Easylogger wrapper
static void init(const char *argv0, const char *default_log_base_name);
static void debug(const std::string &str);
static void debug(const std::string &category, const std::string &str);
static void info(const std::string &category, const std::string &str);
static void warning(const std::string &category, const std::string &str);
static void error(const std::string &category, const std::string &str);
/**
* @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds)
@ -492,6 +594,39 @@ struct Wallet
*/
virtual int autoRefreshInterval() const = 0;
/**
* @brief addSubaddressAccount - appends a new subaddress account at the end of the last major index of existing subaddress accounts
* @param label - the label for the new account (which is the as the label of the primary address (accountIndex,0))
*/
virtual void addSubaddressAccount(const std::string& label) = 0;
/**
* @brief numSubaddressAccounts - returns the number of existing subaddress accounts
*/
virtual size_t numSubaddressAccounts() const = 0;
/**
* @brief numSubaddresses - returns the number of existing subaddresses associated with the specified subaddress account
* @param accountIndex - the major index specifying the subaddress account
*/
virtual size_t numSubaddresses(uint32_t accountIndex) const = 0;
/**
* @brief addSubaddress - appends a new subaddress at the end of the last minor index of the specified subaddress account
* @param accountIndex - the major index specifying the subaddress account
* @param label - the label for the new subaddress
*/
virtual void addSubaddress(uint32_t accountIndex, const std::string& label) = 0;
/**
* @brief getSubaddressLabel - gets the label of the specified subaddress
* @param accountIndex - the major index specifying the subaddress account
* @param addressIndex - the minor index specifying the subaddress
*/
virtual std::string getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const = 0;
/**
* @brief setSubaddressLabel - sets the label of the specified subaddress
* @param accountIndex - the major index specifying the subaddress account
* @param addressIndex - the minor index specifying the subaddress
* @param label - the new label for the specified subaddress
*/
virtual void setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label) = 0;
/*!
* \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
@ -499,6 +634,8 @@ struct Wallet
* \param payment_id optional payment_id, can be empty string
* \param amount amount
* \param mixin_count mixin count. if 0 passed, wallet will use default value
* \param subaddr_account subaddress account from which the input funds are taken
* \param subaddr_indices set of subaddress indices to use for transfer or sweeping. if set empty, all are chosen when sweeping, and one or more are automatically chosen when transferring. after execution, returns the set of actually used indices
* \param priority
* \return PendingTransaction object. caller is responsible to check PendingTransaction::status()
* after object returned
@ -506,7 +643,9 @@ struct Wallet
virtual PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
optional<uint64_t> amount, uint32_t mixin_count,
PendingTransaction::Priority = PendingTransaction::Priority_Low) = 0;
PendingTransaction::Priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0,
std::set<uint32_t> subaddr_indices = {}) = 0;
/*!
* \brief createSweepUnmixableTransaction creates transaction with unmixable outputs.
@ -551,8 +690,10 @@ struct Wallet
virtual bool importKeyImages(const std::string &filename) = 0;
virtual TransactionHistory * history() const = 0;
virtual AddressBook * addressBook() const = 0;
virtual TransactionHistory * history() = 0;
virtual AddressBook * addressBook() = 0;
virtual Subaddress * subaddress() = 0;
virtual SubaddressAccount * subaddressAccount() = 0;
virtual void setListener(WalletListener *) = 0;
/*!
* \brief defaultMixin - returns number of mixins used in transactions
@ -569,7 +710,7 @@ struct Wallet
* \brief setUserNote - attach an arbitrary string note to a txid
* \param txid - the transaction id to attach the note to
* \param note - the note
* \return true if succesful, false otherwise
* \return true if successful, false otherwise
*/
virtual bool setUserNote(const std::string &txid, const std::string &note) = 0;
/*!
@ -579,6 +720,17 @@ struct Wallet
*/
virtual std::string getUserNote(const std::string &txid) const = 0;
virtual std::string getTxKey(const std::string &txid) const = 0;
virtual bool checkTxKey(const std::string &txid, std::string tx_key, const std::string &address, uint64_t &received, bool &in_pool, uint64_t &confirmations) = 0;
virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const = 0;
virtual bool checkTxProof(const std::string &txid, const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations) = 0;
virtual std::string getSpendProof(const std::string &txid, const std::string &message) const = 0;
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const = 0;
/*!
* \brief getReserveProof - Generates a proof that proves the reserve of unspent funds
* Parameters `account_index` and `amount` are ignored when `all` is true
*/
virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const = 0;
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const = 0;
/*
* \brief signMessage - sign a message with the spend private key
@ -604,6 +756,36 @@ struct Wallet
* \return true on success
*/
virtual bool rescanSpent() = 0;
//! blackballs a set of outputs
virtual bool blackballOutputs(const std::vector<std::string> &pubkeys, bool add) = 0;
//! unblackballs an output
virtual bool unblackballOutput(const std::string &pubkey) = 0;
//! gets the ring used for a key image, if any
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const = 0;
//! gets the rings used for a txid, if any
virtual bool getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const = 0;
//! sets the ring used for a key image
virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative) = 0;
//! sets whether pre-fork outs are to be segregated
virtual void segregatePreForkOutputs(bool segregate) = 0;
//! sets the height where segregation should occur
virtual void segregationHeight(uint64_t height) = 0;
//! secondary key reuse mitigation
virtual void keyReuseMitigation2(bool mitigation) = 0;
//! Light wallet authenticate and login
virtual bool lightWalletLogin(bool &isNewWallet) const = 0;
//! Initiates a light wallet import wallet request
virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) = 0;
};
/**
@ -616,84 +798,125 @@ struct WalletManager
* \brief Creates new wallet
* \param path Name of wallet file
* \param password Password of wallet file
* \param language Language to be used to generate electrum seed memo
* \param language Language to be used to generate electrum seed mnemonic
* \param nettype Network type
* \return Wallet instance (Wallet::status() needs to be called to check if created successfully)
*/
virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) = 0;
virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, NetworkType nettype) = 0;
Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet = false) // deprecated
{
return createWallet(path, password, language, testnet ? TESTNET : MAINNET);
}
/*!
* \brief Opens existing wallet
* \param path Name of wallet file
* \param password Password of wallet file
* \param nettype Network type
* \return Wallet instance (Wallet::status() needs to be called to check if opened successfully)
*/
virtual Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) = 0;
virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype) = 0;
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
{
return openWallet(path, password, testnet ? TESTNET : MAINNET);
}
/*!
* \brief recovers existing wallet using memo (electrum seed)
* \brief recovers existing wallet using mnemonic (electrum seed)
* \param path Name of wallet file to be created
* \param password Password of wallet file
* \param memo memo (25 words electrum seed)
* \param testnet testnet
* \param mnemonic mnemonic (25 words electrum seed)
* \param nettype Network type
* \param restoreHeight restore from start height
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &memo, bool testnet = false, uint64_t restoreHeight = 0) = 0;
virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
NetworkType nettype = MAINNET, uint64_t restoreHeight = 0) = 0;
Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic,
bool testnet = false, uint64_t restoreHeight = 0) // deprecated
{
return recoveryWallet(path, password, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight);
}
/*!
* \deprecated this method creates a wallet WITHOUT a psssphrase, use the alternate recoverWallet() method
* \brief recovers existing wallet using memo (electrum seed)
* \deprecated this method creates a wallet WITHOUT a passphrase, use the alternate recoverWallet() method
* \brief recovers existing wallet using mnemonic (electrum seed)
* \param path Name of wallet file to be created
* \param memo memo (25 words electrum seed)
* \param testnet testnet
* \param mnemonic mnemonic (25 words electrum seed)
* \param nettype Network type
* \param restoreHeight restore from start height
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo, bool testnet = false, uint64_t restoreHeight = 0) = 0;
virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight = 0) = 0;
Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, bool testnet = false, uint64_t restoreHeight = 0) // deprecated
{
return recoveryWallet(path, mnemonic, testnet ? TESTNET : MAINNET, restoreHeight);
}
/*!
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
* \param path Name of wallet file to be created
* \param password Password of wallet file
* \param language language
* \param testnet testnet
* \param nettype Network type
* \param restoreHeight restore from start height
* \param addressString public address
* \param viewKeyString view key
* \param spendKeyString spend key (optional)
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * createWalletWithKeys(const std::string &path,
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
bool testnet,
NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") = 0;
Wallet * createWalletFromKeys(const std::string &path,
const std::string &password,
const std::string &language,
bool testnet,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") // deprecated
{
return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
}
/*!
* \deprecated this method creates a wallet WITHOUT a psssphrase, use createWalletWithKeys() instead
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
* \param path Name of wallet file to be created
* \param language language
* \param testnet testnet
* \param restoreHeight restore from start height
* \param addressString public address
* \param viewKeyString view key
* \param spendKeyString spend key (optional)
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * createWalletFromKeys(const std::string &path,
/*!
* \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
* \param path Name of wallet file to be created
* \param language language
* \param nettype Network type
* \param restoreHeight restore from start height
* \param addressString public address
* \param viewKeyString view key
* \param spendKeyString spend key (optional)
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * createWalletFromKeys(const std::string &path,
const std::string &language,
bool testnet,
NetworkType nettype,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") = 0;
Wallet * createWalletFromKeys(const std::string &path,
const std::string &language,
bool testnet,
uint64_t restoreHeight,
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") // deprecated
{
return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
}
/*!
* \brief Closes wallet. In case operation succeded, wallet object deleted. in case operation failed, wallet object not deleted
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
* \param wallet previously opened / created wallet instance
* \return None
*/
@ -714,10 +937,10 @@ struct WalletManager
* @brief verifyWalletPassword - check if the given filename is the wallet
* @param keys_file_name - location of keys file
* @param password - password to verify
* @param watch_only - verify only view keys?
* @param no_spend_key - verify only view keys?
* @return - true if password is correct
*/
virtual bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool watch_only) const = 0;
virtual bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const = 0;
/*!
* \brief findWallets - searches for the wallet files by given path name recursively
@ -726,19 +949,6 @@ struct WalletManager
*/
virtual std::vector<std::string> findWallets(const std::string &path) = 0;
/*!
* \brief checkPayment - checks a payment was made using a txkey
* \param address - the address the payment was sent to
* \param txid - the transaction id for that payment
* \param txkey - the transaction's secret key
* \param daemon_address - the address (host and port) to the daemon to request transaction data
* \param received - if succesful, will hold the amount of monero received
* \param height - if succesful, will hold the height of the transaction (0 if only in the pool)
* \param error - if unsuccesful, will hold an error string with more information about the error
* \return - true is succesful, false otherwise
*/
virtual bool checkPayment(const std::string &address, const std::string &txid, const std::string &txkey, const std::string &daemon_address, uint64_t &received, uint64_t &height, std::string &error) const = 0;
//! returns verbose error string regarding last error;
virtual std::string errorString() const = 0;
@ -776,7 +986,7 @@ struct WalletManager
virtual std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const = 0;
//! checks for an update and returns version, hash and url
static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, const std::string &subdir);
static std::tuple<bool, std::string, std::string, std::string, std::string> checkUpdates(const std::string &software, std::string subdir);
};

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

Some files were not shown because too many files have changed in this diff Show More