1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-06 02:27:11 +02:00

Compare commits

..

44 Commits

Author SHA1 Message Date
m2049r
df2ff8b3b7 correct toolbar colour for testnet (#218) 2018-04-02 13:02:00 +02:00
m2049r
da8c8f80f1 new version for m2049r/monero 7e97e11 (#217) 2018-04-02 12:14:55 +02:00
m2049r
eda3de11fe added zxcvbn4j license (#216) 2018-04-01 13:23:03 +02:00
m2049r
7d7de14827 new version id for monero PR#3526 (#215) 2018-03-30 14:12:17 +02:00
m2049r
1c709da92c Update FAQ.md 2018-03-29 23:00:39 +02:00
m2049r
a9092497b2 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)
2018-03-29 22:35:31 +02:00
m2049r
b1f530e64a new version number (#208) 2018-03-13 22:31:32 +01:00
m2049r
8c086b77d3 Minor Bugfixes (#207)
* corrected spanish

* removed testcode

* fix issue #206
2018-03-06 18:15:23 +01:00
m2049r
c0fdfe87be build for x86 & arm in both 32 & 64 bits (#204) 2018-02-27 07:22:11 +01:00
m2049r
6cfd840283 fixed some bugs & reverted to boost 1.58 2018-02-26 09:46:20 +01:00
Miguel Botón
d80cde1136 Added build instructions for 64-bit (aarch64). (#172) 2018-02-26 08:42:22 +01:00
m2049r
bea4b06675 new version 2018-02-23 19:47:20 +01:00
m2049r
88bc33b5a4 added zxcvbn password score (#199)
* added zxcvbn password score

* changes messages & thresholds

change password label to passphrase
2018-02-23 19:32:21 +01:00
m2049r
2db36bb824 Enable Restore with Date instead of Height Only (#198)
* restore height class

* exact heights

* tweaks with DST

* some more spanish
2018-02-23 19:31:55 +01:00
m2049r
dd689b1883 fix for 2N9fzq66uZYQXp7uqrPBH6jKBhjrgTzpGCy (#190) 2018-01-24 19:59:13 +01:00
m2049r
641abd13f5 split apk (#191) 2018-01-23 21:35:26 +01:00
Stephan Hagios
a0b3a7fe5d used background borderless for nicer ripple effect (#189) 2018-01-22 21:36:13 +01:00
Stephan Hagios
a0486f581f Added circleci yml (#188)
* Adjusted layout files with correct sizes.

* Added password visibility toggle

* PR suggestions

* circle ci yml added

* different container with ndk
2018-01-21 18:53:45 +01:00
m2049r
36161137ec correct spanish (#187) 2018-01-18 17:45:46 +01:00
m2049r
c9927edbd1 save on exit only with connected wallet (#186) 2018-01-18 17:23:35 +01:00
m2049r
f0a3c05a9a v1.3.8 (#185) 2018-01-18 00:16:02 +01:00
m2049r
d6eb82c457 new wallet password fix (#184)
* revert to old (in-place) wallet creation method

* recover with password
2018-01-18 00:14:07 +01:00
m2049r
7f47307307 Revert "APK Split" (#183) 2018-01-16 22:23:10 +01:00
m2049r
165dd3dfd1 more spanish (#182) 2018-01-16 22:09:35 +01:00
m2049r
171727c9db new debug icon (#181) 2018-01-16 19:29:42 +01:00
m2049r
1492814ec9 new version 1.3.7 2018-01-16 19:28:30 +01:00
Stephan Hagios
9b1225fe4b Added an application suffix to distinguish between release and debug ver (#177)
* Added an application suffix to distinguish between release and debug ver

* Added icon for debug version.

* Added icon from mattermost assets channel.
2018-01-16 18:55:36 +01:00
m2049r
595d88e42e fixes & touchups (#178) 2018-01-15 23:31:14 +01:00
Stephan Hagios
0e207d7401 Merge pull request #174 from m2049r/feature/apk-split
APK Split
2018-01-04 17:07:52 +01:00
Stephan
5920d6c9e8 added apk split for different abis 2018-01-03 15:18:34 +01:00
m2049r
44fd3c10fa added info about xmr..to 2017-12-24 14:48:04 +01:00
anhdres
91ab8a681c Update spanish help.xml (#166)
* Update help.xml
2017-12-24 14:33:58 +01:00
m2049r
d843bdb451 Tweaks (#167)
* update privacy policy

* fix height

* send confirm scrollable

* use clickable instead of enabled

* rename
2017-12-24 14:18:32 +01:00
m2049r
2884fc711c UI Tweaks & spend help (#165)
* green send

* add xmrto to send help
2017-12-23 15:41:52 +01:00
m2049r
8ea2081270 Update README.md 2017-12-22 22:37:02 +01:00
m2049r
2296329962 Merge branch 'master' of https://github.com/m2049r/xmrwallet 2017-12-22 21:45:35 +01:00
Miguel Botón
fc1bff2160 Remove the gap at the bottom in the wallet fragment. (#162) 2017-12-22 21:43:46 +01:00
m2049r
e61c2b616e new version 2017-12-22 21:43:24 +01:00
m2049r
ea1e8ac2c3 UI tweaks, fix crash (#164) 2017-12-22 21:41:47 +01:00
m2049r
1082175089 spanish tweaked (#163) 2017-12-22 08:47:12 +01:00
m2049r
90d64089a6 new version id 2017-12-21 08:00:09 +01:00
m2049r
b689628975 fix some strings and remove debugging code (#160) 2017-12-21 07:58:50 +01:00
m2049r
f8e701aa07 Satoshis Dream (#159)
xmr.to integration
2017-12-21 00:46:34 +01:00
Miguel Botón
d855328c52 Translate strings and privacy policy to Spanish. (#155)
* Translate strings and privacy policy to Spanish.

* Translate help to Spanish.

* Improved translation of a couple of strings.

* The pirates are back.
2017-12-17 10:43:38 +01:00
166 changed files with 7831 additions and 1584 deletions

27
.circleci/config.yml Normal file
View File

@@ -0,0 +1,27 @@
version: 2
jobs:
build:
working_directory: ~/code
docker:
- image: bitriseio/android-ndk
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Run Tests
command: ./gradlew test
- store_artifacts:
path: app/build/reports
destination: reports
- store_test_results:
path: app/build/test-results

View File

@@ -11,22 +11,19 @@ Another Android Monero Wallet
You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet. You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet.
### Random Notes ### Random Notes
- Based off monero v0.11.0.0 with PR #2289 applied - Based off monero v0.11.1.0
- currently only android32 (runs on 64-bit as well) - currently only android32 (runs on 64-bit as well)
- works on the testnet & mainnet - works on the testnet & mainnet
- sync is slow due to 32-bit architecture - sync is slow due to 32-bit architecture
- use your own daemon - it's easy - use your own daemon - it's easy
- screen stays on until first sync is complete - screen stays on until first sync is complete
- saves wallet only on first sync and when sending transactions or editing notes
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/ - Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
### TODO ### TODO
- more sensible error dialogs - see taiga.getmonero.org & issues on github
### Issues / Pitfalls ### Issues / Pitfalls
- The backups folder is now called "backups" and not ".backups" - which in most file explorers was a hidden folder - You should backup your wallet files in the "monerujo" folder periodically.
- Wallets are now created directly in the "monerujo" folder, and not in the ".new" folder as before
- You may want to check the old folders with a file browsing app and delete the ".new" and ".backups" folders AFTER moving neccessary wallet files to the new locations. Or simply make new backups from within Monerujo.
- Also note, that on some devices the backups will only be visible on a PC over USB after a reboot of the device (it's an Android bug/feature) - Also note, that on some devices the backups will only be visible on a PC over USB after a reboot of the device (it's an Android bug/feature)
- Created wallets on a private testnet are unusable because the restore height is set to that - Created wallets on a private testnet are unusable because the restore height is set to that
of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed. of the "real" testnet. After creating a new wallet, make a **new** one by recovering from the seed.
@@ -36,7 +33,7 @@ The official monero client shows the same behaviour.
No need to build. Binaries are included: No need to build. Binaries are included:
- openssl-1.0.2l - openssl-1.0.2l
- monero-v0.11.0.0 + pull requests #2289 - monero-v0.11.1.0
- boost_1_64_0 - boost_1_64_0
If you want to build them yourself (recommended) check out [the instructions](doc/BUILDING-external-libs.md) If you want to build them yourself (recommended) check out [the instructions](doc/BUILDING-external-libs.md)

View File

@@ -60,9 +60,13 @@ set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/boost/lib/${ANDROID_ABI}/libboost_wserialization.a) ${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) add_library(wallet STATIC IMPORTED)
set_target_properties(wallet PROPERTIES IMPORTED_LOCATION set_target_properties(wallet PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libwallet.a) ${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 set_target_properties(ringct PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct.a) ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct.a)
##### add_library(ringct_basic STATIC IMPORTED)
set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION
add_library(p2p STATIC IMPORTED) ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libringct_basic.a)
set_target_properties(p2p PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libp2p.a)
add_library(blockchain_db STATIC IMPORTED) add_library(blockchain_db STATIC IMPORTED)
set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION
@@ -113,7 +115,6 @@ add_library(unbound STATIC IMPORTED)
set_target_properties(unbound PROPERTIES IMPORTED_LOCATION set_target_properties(unbound PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libunbound.a) ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libunbound.a)
####
add_library(epee STATIC IMPORTED) add_library(epee STATIC IMPORTED)
set_target_properties(epee PROPERTIES IMPORTED_LOCATION set_target_properties(epee PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libepee.a) ${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 set_target_properties(blocks PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libblocks.a) ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libblocks.a)
add_library(miniupnpc STATIC IMPORTED) add_library(checkpoints STATIC IMPORTED)
set_target_properties(miniupnpc PROPERTIES IMPORTED_LOCATION set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libminiupnpc.a) ${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 # System
@@ -137,23 +150,26 @@ include_directories( ${EXTERNAL_LIBS_DIR}/monero/include )
message(STATUS EXTERNAL_LIBS_DIR : ${EXTERNAL_LIBS_DIR}) message(STATUS EXTERNAL_LIBS_DIR : ${EXTERNAL_LIBS_DIR})
target_link_libraries( monerujo target_link_libraries( monerujo
wallet_api
wallet wallet
cryptonote_core cryptonote_core
cryptonote_basic cryptonote_basic
mnemonics mnemonics
ringct ringct
ringct_basic
common common
cncrypto cncrypto
blockchain_db blockchain_db
lmdb lmdb
easylogging easylogging
unbound unbound
p2p
epee epee
blocks blocks
miniupnpc checkpoints
device
multisig
version
boost_chrono boost_chrono
boost_date_time boost_date_time

View File

@@ -8,8 +8,8 @@ android {
applicationId "com.m2049r.xmrwallet" applicationId "com.m2049r.xmrwallet"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 25 targetSdkVersion 25
versionCode 51 versionCode 85
versionName "1.2.11" versionName "1.4.5 'Monero Spedner'"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild { externalNativeBuild {
cmake { cmake {
@@ -18,7 +18,7 @@ android {
} }
} }
ndk { ndk {
abiFilters 'armeabi-v7a' abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
} }
} }
@@ -27,12 +27,37 @@ android {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
debug {
applicationIdSuffix ".debug"
}
} }
externalNativeBuild { externalNativeBuild {
cmake { cmake {
path "CMakeLists.txt" path "CMakeLists.txt"
} }
} }
splits {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
universalApk true
}
}
// Map for the version code that gives each ABI a value.
def abiCodes = ['armeabi-v7a': 1, 'arm64-v8a': 2, 'x86': 3, 'x86_64': 4]
// APKs for the same app that all have the same version information.
android.applicationVariants.all { variant ->
// Assigns a different version code for each output APK.
variant.outputs.each {
output ->
def abiName = output.getFilter(com.android.build.OutputFile.ABI)
output.versionCodeOverride = abiCodes.get(abiName, 0) + 10 * variant.versionCode
}
}
} }
dependencies { dependencies {
@@ -47,6 +72,8 @@ dependencies {
compile "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion" compile "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion"
compile "com.jakewharton.timber:timber:$rootProject.ext.timberVersion" compile "com.jakewharton.timber:timber:$rootProject.ext.timberVersion"
compile 'com.nulab-inc:zxcvbn:1.2.3'
testCompile "junit:junit:$rootProject.ext.junitVersion" testCompile "junit:junit:$rootProject.ext.junitVersion"
testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion" testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
testCompile "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion" testCompile "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion"
@@ -77,5 +104,7 @@ dependencyVerification {
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d', 'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850', 'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4', 'com.squareup.okhttp3:okhttp:7265adbd6f028aade307f58569d814835cd02bc9beffb70c25f72c9de50d61c4',
'com.jakewharton.timber:timber:35c22867f2673132e97e17857d36bb2fc25f5790f0425406833ed0254d62fc66',
'com.nulab-inc:zxcvbn:18d7862a6abd2705defec478d77dedadf8f3bb7cf811df22995494f05485785f',
] ]
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">monerujo - Debug</string>
</resources>

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,9 @@ import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@@ -32,12 +34,18 @@ import android.view.inputmethod.EditorInfo;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import com.m2049r.xmrwallet.util.RestoreHeight;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.nulabinc.zxcvbn.Strength;
import com.nulabinc.zxcvbn.Zxcvbn;
import java.io.File; import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import timber.log.Timber; import timber.log.Timber;
@@ -125,7 +133,7 @@ public class GenerateFragment extends Fragment {
}); });
Helper.showKeyboard(getActivity()); Helper.showKeyboard(getActivity());
//##############
etWalletName.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() { etWalletName.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) { if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) {
@@ -231,9 +239,7 @@ public class GenerateFragment extends Fragment {
} }
if (!type.equals(TYPE_NEW)) { if (!type.equals(TYPE_NEW)) {
etWalletRestoreHeight.setVisibility(View.VISIBLE); etWalletRestoreHeight.setVisibility(View.VISIBLE);
etWalletRestoreHeight.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() etWalletRestoreHeight.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
{
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) { if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
Helper.hideKeyboard(getActivity()); Helper.hideKeyboard(getActivity());
@@ -254,11 +260,61 @@ public class GenerateFragment extends Fragment {
} }
}); });
etWalletPassword.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
checkPassword();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
etWalletName.requestFocus(); etWalletName.requestFocus();
initZxcvbn();
return view; return view;
} }
Zxcvbn zxcvbn = new Zxcvbn();
// initialize zxcvbn engine in background thread
private void initZxcvbn() {
new Thread(new Runnable() {
@Override
public void run() {
zxcvbn.measure("");
}
}).start();
}
private void checkPassword() {
String password = etWalletPassword.getEditText().getText().toString();
if (!password.isEmpty()) {
Strength strength = zxcvbn.measure(password);
int msg;
double guessesLog10 = strength.getGuessesLog10();
if (guessesLog10 < 10)
msg = R.string.password_weak;
else if (guessesLog10 < 11)
msg = R.string.password_fair;
else if (guessesLog10 < 12)
msg = R.string.password_good;
else if (guessesLog10 < 13)
msg = R.string.password_strong;
else
msg = R.string.password_very_strong;
etWalletPassword.setError(getResources().getString(msg));
} else {
etWalletPassword.setError(null);
}
}
private boolean checkName() { private boolean checkName() {
String name = etWalletName.getEditText().getText().toString(); String name = etWalletName.getEditText().getText().toString();
boolean ok = true; boolean ok = true;
@@ -281,6 +337,42 @@ public class GenerateFragment extends Fragment {
return ok; return ok;
} }
private boolean checkHeight() {
long height = !type.equals(TYPE_NEW) ? getHeight() : 0;
boolean ok = true;
if (height < 0) {
etWalletRestoreHeight.setError(getString(R.string.generate_restoreheight_error));
ok = false;
}
if (ok) {
etWalletRestoreHeight.setError(null);
}
return ok;
}
private long getHeight() {
long height = 0;
String restoreHeight = etWalletRestoreHeight.getEditText().getText().toString().trim();
if (restoreHeight.isEmpty()) return -1;
try {
// is it a date?
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd");
parser.setLenient(false);
parser.parse(restoreHeight);
height = RestoreHeight.getInstance().getHeight(restoreHeight);
} catch (ParseException exPE) {
try {
// or is it a height?
height = Long.parseLong(restoreHeight);
} catch (NumberFormatException exNFE) {
return -1;
}
}
Timber.d("Using Restore Height = %d", height);
return height;
}
private boolean checkMnemonic() { private boolean checkMnemonic() {
String seed = etWalletMnemonic.getEditText().getText().toString(); String seed = etWalletMnemonic.getEditText().getText().toString();
boolean ok = (seed.split("\\s").length == 25); // 25 words boolean ok = (seed.split("\\s").length == 25); // 25 words
@@ -294,7 +386,7 @@ public class GenerateFragment extends Fragment {
private boolean checkAddress() { private boolean checkAddress() {
String address = etWalletAddress.getEditText().getText().toString(); String address = etWalletAddress.getEditText().getText().toString();
boolean ok = Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet()); boolean ok = Wallet.isAddressValid(address);
if (!ok) { if (!ok) {
etWalletAddress.setError(getString(R.string.generate_check_address)); etWalletAddress.setError(getString(R.string.generate_check_address));
} else { } else {
@@ -327,15 +419,13 @@ public class GenerateFragment extends Fragment {
private void generateWallet() { private void generateWallet() {
if (!checkName()) return; if (!checkName()) return;
if (!checkHeight()) return;
String name = etWalletName.getEditText().getText().toString(); String name = etWalletName.getEditText().getText().toString();
String password = etWalletPassword.getEditText().getText().toString(); String password = etWalletPassword.getEditText().getText().toString();
long height; long height = getHeight();
try { if (height < 0) height = 0;
height = Long.parseLong(etWalletRestoreHeight.getEditText().getText().toString());
} catch (NumberFormatException ex) {
height = 0; // Keep calm and carry on!
}
if (type.equals(TYPE_NEW)) { if (type.equals(TYPE_NEW)) {
bGenerate.setEnabled(false); bGenerate.setEnabled(false);

View File

@@ -34,6 +34,7 @@ import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
@@ -81,7 +82,7 @@ public class GenerateReviewFragment extends Fragment {
bAccept = (Button) view.findViewById(R.id.bAccept); bAccept = (Button) view.findViewById(R.id.bAccept);
boolean testnet = WalletManager.getInstance().isTestNet(); boolean testnet = WalletManager.getInstance().getNetworkType() != NetworkType.NetworkType_Mainnet;
tvWalletMnemonic.setTextIsSelectable(testnet); tvWalletMnemonic.setTextIsSelectable(testnet);
tvWalletSpendKey.setTextIsSelectable(testnet); tvWalletSpendKey.setTextIsSelectable(testnet);
@@ -103,6 +104,7 @@ public class GenerateReviewFragment extends Fragment {
copyAddress(); copyAddress();
} }
}); });
bCopyAddress.setClickable(false);
view.findViewById(R.id.bAdvancedInfo).setOnClickListener(new View.OnClickListener() { view.findViewById(R.id.bAdvancedInfo).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@@ -184,6 +186,7 @@ public class GenerateReviewFragment extends Fragment {
name = wallet.getName(); name = wallet.getName();
status = wallet.getStatus(); status = wallet.getStatus();
if (status != Wallet.Status.Status_Ok) { if (status != Wallet.Status.Status_Ok) {
Timber.e(wallet.getErrorString());
if (closeWallet) wallet.close(); if (closeWallet) wallet.close();
return false; return false;
} }
@@ -213,7 +216,7 @@ public class GenerateReviewFragment extends Fragment {
tvWalletViewKey.setText(viewKey); tvWalletViewKey.setText(viewKey);
tvWalletSpendKey.setText(spendKey); tvWalletSpendKey.setText(spendKey);
bAdvancedInfo.setVisibility(View.VISIBLE); bAdvancedInfo.setVisibility(View.VISIBLE);
bCopyAddress.setEnabled(true); bCopyAddress.setClickable(true);
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp); bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
activityCallback.setTitle(name, getString(R.string.details_title)); activityCallback.setTitle(name, getString(R.string.details_title));
activityCallback.setToolbarButton( activityCallback.setToolbarButton(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,7 @@ import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix; import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.m2049r.xmrwallet.data.BarcodeData;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
@@ -105,6 +106,7 @@ public class ReceiveFragment extends Fragment {
copyAddress(); copyAddress();
} }
}); });
bCopyAddress.setClickable(false);
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() { evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() {
@Override @Override
@@ -239,7 +241,7 @@ public class ReceiveFragment extends Fragment {
tvAddress.setText(address); tvAddress.setText(address);
etPaymentId.setEnabled(true); etPaymentId.setEnabled(true);
bPaymentId.setEnabled(true); bPaymentId.setEnabled(true);
bCopyAddress.setEnabled(true); bCopyAddress.setClickable(true);
bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp); bCopyAddress.setImageResource(R.drawable.ic_content_copy_black_24dp);
hideProgress(); hideProgress();
generateQr(); generateQr();
@@ -298,20 +300,20 @@ public class ReceiveFragment extends Fragment {
String paymentId = etPaymentId.getEditText().getText().toString(); String paymentId = etPaymentId.getEditText().getText().toString();
String xmrAmount = evAmount.getAmount(); String xmrAmount = evAmount.getAmount();
Timber.d("%s/%s/%s", xmrAmount, paymentId, address); Timber.d("%s/%s/%s", xmrAmount, paymentId, address);
if ((xmrAmount == null) || !Wallet.isAddressValid(address, WalletManager.getInstance().isTestNet())) { if ((xmrAmount == null) || !Wallet.isAddressValid(address)) {
clearQR(); clearQR();
Timber.d("CLEARQR"); Timber.d("CLEARQR");
return; return;
} }
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append(ScannerFragment.QR_SCHEME).append(address); sb.append(BarcodeData.XMR_SCHEME).append(address);
boolean first = true; boolean first = true;
if (!paymentId.isEmpty()) { if (!paymentId.isEmpty()) {
if (first) { if (first) {
sb.append("?"); sb.append("?");
first = false; first = false;
} }
sb.append(ScannerFragment.QR_PAYMENTID).append('=').append(paymentId); sb.append(BarcodeData.XMR_PAYMENTID).append('=').append(paymentId);
} }
if (!xmrAmount.isEmpty()) { if (!xmrAmount.isEmpty()) {
if (first) { if (first) {
@@ -319,7 +321,7 @@ public class ReceiveFragment extends Fragment {
} else { } else {
sb.append("&"); sb.append("&");
} }
sb.append(ScannerFragment.QR_AMOUNT).append('=').append(xmrAmount); sb.append(BarcodeData.XMR_AMOUNT).append('=').append(xmrAmount);
} }
String text = sb.toString(); String text = sb.toString();
int size = Math.min(qrCode.getHeight(), qrCode.getWidth()); int size = Math.min(qrCode.getHeight(), qrCode.getWidth());

View File

@@ -36,7 +36,7 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
private OnScannedListener onScannedListener; private OnScannedListener onScannedListener;
public interface OnScannedListener { public interface OnScannedListener {
boolean onScanned(String uri); boolean onScanned(String qrCode);
} }
private ZXingScannerView mScannerView; private ZXingScannerView mScannerView;
@@ -56,10 +56,6 @@ public class ScannerFragment extends Fragment implements ZXingScannerView.Result
mScannerView.startCamera(); mScannerView.startCamera();
} }
static final String QR_SCHEME = "monero:";
static final String QR_PAYMENTID = "tx_payment_id";
static final String QR_AMOUNT = "tx_amount";
@Override @Override
public void handleResult(Result rawResult) { public void handleResult(Result rawResult) {
if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE)) { if ((rawResult.getBarcodeFormat() == BarcodeFormat.QR_CODE)) {

View File

@@ -20,6 +20,10 @@ import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import com.m2049r.xmrwallet.util.Helper;
import java.io.File;
import static android.view.WindowManager.LayoutParams; import static android.view.WindowManager.LayoutParams;
public abstract class SecureActivity extends AppCompatActivity { public abstract class SecureActivity extends AppCompatActivity {

View File

@@ -30,10 +30,13 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.m2049r.xmrwallet.model.TransactionInfo; import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Transfer; import com.m2049r.xmrwallet.model.Transfer;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.UserNotes;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@@ -68,12 +71,23 @@ public class TxFragment extends Fragment {
private TextView etTxNotes; private TextView etTxNotes;
private Button bTxNotes; private Button bTxNotes;
// XMRTO stuff
private View cvXmrTo;
private TextView tvTxXmrToKey;
private TextView tvDestinationBtc;
private TextView tvTxAmountBtc;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tx_info, container, false); View view = inflater.inflate(R.layout.fragment_tx_info, container, false);
cvXmrTo = view.findViewById(R.id.cvXmrTo);
tvTxXmrToKey = (TextView) view.findViewById(R.id.tvTxXmrToKey);
tvDestinationBtc = (TextView) view.findViewById(R.id.tvDestinationBtc);
tvTxAmountBtc = (TextView) view.findViewById(R.id.tvTxAmountBtc);
tvTxTimestamp = (TextView) view.findViewById(R.id.tvTxTimestamp); tvTxTimestamp = (TextView) view.findViewById(R.id.tvTxTimestamp);
tvTxId = (TextView) view.findViewById(R.id.tvTxId); tvTxId = (TextView) view.findViewById(R.id.tvTxId);
tvTxKey = (TextView) view.findViewById(R.id.tvTxKey); tvTxKey = (TextView) view.findViewById(R.id.tvTxKey);
@@ -94,7 +108,16 @@ public class TxFragment extends Fragment {
info.notes = null; // force reload on next view info.notes = null; // force reload on next view
bTxNotes.setEnabled(false); bTxNotes.setEnabled(false);
etTxNotes.setEnabled(false); etTxNotes.setEnabled(false);
activityCallback.onSetNote(info.hash, etTxNotes.getText().toString()); userNotes.setNote(etTxNotes.getText().toString());
activityCallback.onSetNote(info.hash, userNotes.txNotes);
}
});
tvTxXmrToKey.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_xmrtokey), tvTxXmrToKey.getText().toString());
Toast.makeText(getActivity(), getString(R.string.message_copy_xmrtokey), Toast.LENGTH_SHORT).show();
} }
}); });
@@ -175,12 +198,14 @@ public class TxFragment extends Fragment {
} }
TransactionInfo info = null; TransactionInfo info = null;
UserNotes userNotes = null;
void loadNotes(TransactionInfo info) { void loadNotes(TransactionInfo info) {
if (info.notes == null) { if ((userNotes == null) || (info.notes == null)) {
info.notes = activityCallback.getTxNotes(info.hash); info.notes = activityCallback.getTxNotes(info.hash);
} }
etTxNotes.setText(info.notes); userNotes = new UserNotes(info.notes);
etTxNotes.setText(userNotes.note);
} }
private void setTxColour(int clr) { private void setTxColour(int clr) {
@@ -266,8 +291,21 @@ public class TxFragment extends Fragment {
tvTxTransfers.setText(sb.toString()); tvTxTransfers.setText(sb.toString());
tvDestination.setText(dstSb.toString()); tvDestination.setText(dstSb.toString());
this.info = info; this.info = info;
showBtcInfo();
} }
void showBtcInfo() {
if (userNotes.xmrtoKey != null) {
cvXmrTo.setVisibility(View.VISIBLE);
tvTxXmrToKey.setText(userNotes.xmrtoKey);
tvDestinationBtc.setText(userNotes.xmrtoDestination);
tvTxAmountBtc.setText(userNotes.xmrtoAmount + " BTC");
} else {
cvXmrTo.setVisibility(View.GONE);
}
}
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);

View File

@@ -22,8 +22,8 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
@@ -36,19 +36,20 @@ import android.widget.Toast;
import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.BarcodeData;
import com.m2049r.xmrwallet.data.TxData; 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.dialog.HelpFragment;
import com.m2049r.xmrwallet.fragment.send.SendAddressWizardFragment;
import com.m2049r.xmrwallet.fragment.send.SendFragment;
import com.m2049r.xmrwallet.model.PendingTransaction; import com.m2049r.xmrwallet.model.PendingTransaction;
import com.m2049r.xmrwallet.model.TransactionInfo; import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.WalletService; import com.m2049r.xmrwallet.service.WalletService;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.UserNotes;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import java.io.File; import java.io.File;
import java.util.HashMap;
import java.util.Map;
import timber.log.Timber; import timber.log.Timber;
@@ -140,6 +141,9 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
@Override @Override
protected void onDestroy() { protected void onDestroy() {
Timber.d("onDestroy()"); Timber.d("onDestroy()");
if ((mBoundService != null) && !isSynced() && (getWallet() != null)) {
saveWallet();
}
stopWalletService(); stopWalletService();
super.onDestroy(); super.onDestroy();
} }
@@ -155,8 +159,8 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
case R.id.action_info: case R.id.action_info:
onWalletDetails(); onWalletDetails();
return true; return true;
case R.id.action_donate: case R.id.action_credits:
DonationFragment.display(getSupportFragmentManager()); CreditsFragment.display(getSupportFragmentManager());
return true; return true;
case R.id.action_share: case R.id.action_share:
onShareTxInfo(); onShareTxInfo();
@@ -209,8 +213,8 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
case Toolbar.BUTTON_CLOSE: case Toolbar.BUTTON_CLOSE:
finish(); finish();
break; break;
case Toolbar.BUTTON_DONATE: case Toolbar.BUTTON_CREDITS:
Toast.makeText(WalletActivity.this, getString(R.string.label_donate), Toast.LENGTH_SHORT).show(); Toast.makeText(WalletActivity.this, getString(R.string.label_credits), Toast.LENGTH_SHORT).show();
case Toolbar.BUTTON_NONE: case Toolbar.BUTTON_NONE:
default: default:
Timber.e("Button " + type + "pressed - how can this be?"); Timber.e("Button " + type + "pressed - how can this be?");
@@ -218,12 +222,7 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
} }
}); });
boolean testnet = WalletManager.getInstance().isTestNet(); showNet();
if (testnet) {
toolbar.setBackgroundResource(R.color.colorPrimaryDark);
} else {
toolbar.setBackgroundResource(R.drawable.backgound_toolbar_mainnet);
}
Fragment walletFragment = new WalletFragment(); Fragment walletFragment = new WalletFragment();
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
@@ -234,6 +233,23 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
Timber.d("onCreate() done."); 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() { public Wallet getWallet() {
if (mBoundService == null) throw new IllegalStateException("WalletService not bound."); if (mBoundService == null) throw new IllegalStateException("WalletService not bound.");
return mBoundService.getWallet(); return mBoundService.getWallet();
@@ -465,7 +481,7 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
} }
@Override @Override
public void onTransactionCreated(final PendingTransaction pendingTransaction) { public void onTransactionCreated(final String txTag, final PendingTransaction pendingTransaction) {
try { try {
final SendFragment sendFragment = (SendFragment) final SendFragment sendFragment = (SendFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
@@ -477,7 +493,7 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
getWallet().disposePendingTransaction(); getWallet().disposePendingTransaction();
sendFragment.onCreateTransactionFailed(errorText); sendFragment.onCreateTransactionFailed(errorText);
} else { } else {
sendFragment.onTransactionCreated(pendingTransaction); sendFragment.onTransactionCreated(txTag, pendingTransaction);
} }
} }
}); });
@@ -560,19 +576,20 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
@Override @Override
public void onProgress(final int n) { public void onProgress(final int n) {
try { runOnUiThread(new Runnable() {
final WalletFragment walletFragment = (WalletFragment) public void run() {
getSupportFragmentManager().findFragmentByTag(WalletFragment.class.getName()); try {
runOnUiThread(new Runnable() { WalletFragment walletFragment = (WalletFragment)
public void run() { getSupportFragmentManager().findFragmentByTag(WalletFragment.class.getName());
walletFragment.setProgress(n); if (walletFragment != null)
walletFragment.setProgress(n);
} catch (ClassCastException ex) {
// not in wallet fragment (probably send monero)
Timber.d(ex.getLocalizedMessage());
// keep calm and carry on
} }
}); }
} catch (ClassCastException ex) { });
// not in wallet fragment (probably send monero)
Timber.d(ex.getLocalizedMessage());
// keep calm and carry on
}
} }
private void updateProgress() { private void updateProgress() {
@@ -588,11 +605,11 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
/////////////////////////// ///////////////////////////
@Override @Override
public void onSend(String notes) { public void onSend(UserNotes notes) {
if (mIsBound) { // no point in talking to unbound service if (mIsBound) { // no point in talking to unbound service
Intent intent = new Intent(getApplicationContext(), WalletService.class); Intent intent = new Intent(getApplicationContext(), WalletService.class);
intent.putExtra(WalletService.REQUEST, WalletService.REQUEST_CMD_SEND); intent.putExtra(WalletService.REQUEST, WalletService.REQUEST_CMD_SEND);
intent.putExtra(WalletService.REQUEST_CMD_SEND_NOTES, notes); intent.putExtra(WalletService.REQUEST_CMD_SEND_NOTES, notes.txNotes);
startService(intent); startService(intent);
Timber.d("SEND TX request sent"); Timber.d("SEND TX request sent");
} else { } else {
@@ -617,11 +634,12 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
} }
@Override @Override
public void onPrepareSend(TxData txData) { public void onPrepareSend(final String tag, final TxData txData) {
if (mIsBound) { // no point in talking to unbound service if (mIsBound) { // no point in talking to unbound service
Intent intent = new Intent(getApplicationContext(), WalletService.class); Intent intent = new Intent(getApplicationContext(), WalletService.class);
intent.putExtra(WalletService.REQUEST, WalletService.REQUEST_CMD_TX); intent.putExtra(WalletService.REQUEST, WalletService.REQUEST_CMD_TX);
intent.putExtra(WalletService.REQUEST_CMD_TX_DATA, txData); intent.putExtra(WalletService.REQUEST_CMD_TX_DATA, txData);
intent.putExtra(WalletService.REQUEST_CMD_TX_TAG, tag);
startService(intent); startService(intent);
Timber.d("CREATE TX request sent"); Timber.d("CREATE TX request sent");
} else { } else {
@@ -694,6 +712,7 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
@Override @Override
public void onDisposeRequest() { public void onDisposeRequest() {
//TODO consider doing this through the WalletService to avoid concurrency issues
getWallet().disposePendingTransaction(); getWallet().disposePendingTransaction();
} }
@@ -791,7 +810,7 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
@Override @Override
public boolean verifyWalletPassword(String password) { public boolean verifyWalletPassword(String password) {
String walletPath = new File(Helper.getStorageRoot(this), String walletPath = new File(Helper.getWalletRoot(this),
getWalletName() + ".keys").getAbsolutePath(); getWalletName() + ".keys").getAbsolutePath();
return WalletManager.getInstance().verifyWalletPassword(walletPath, password, true); return WalletManager.getInstance().verifyWalletPassword(walletPath, password, true);
} }
@@ -804,9 +823,6 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
super.onBackPressed(); super.onBackPressed();
} }
} else { } else {
if (!isSynced()) {
saveWallet();
}
super.onBackPressed(); super.onBackPressed();
} }
} }
@@ -815,4 +831,10 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
public void onFragmentDone() { public void onFragmentDone() {
popFragmentStack(null); popFragmentStack(null);
} }
@Override
public SharedPreferences getPrefs() {
return getPreferences(Context.MODE_PRIVATE);
}
} }

View File

@@ -313,7 +313,7 @@ public class WalletFragment extends Fragment
if (wallet == null) return; if (wallet == null) return;
walletTitle = wallet.getName(); walletTitle = wallet.getName();
String watchOnly = (wallet.isWatchOnly() ? getString(R.string.label_watchonly) : ""); String watchOnly = (wallet.isWatchOnly() ? getString(R.string.label_watchonly) : "");
walletSubtitle = wallet.getAddress().substring(0, 16) + "…" + watchOnly; walletSubtitle = wallet.getAddress().substring(0, 10) + "…" + watchOnly;
activityCallback.setTitle(walletTitle, walletSubtitle); activityCallback.setTitle(walletTitle, walletSubtitle);
Timber.d("wallet title is %s", walletTitle); Timber.d("wallet title is %s", walletTitle);
} }

View File

@@ -19,13 +19,15 @@ package com.m2049r.xmrwallet;
import android.app.Application; import android.app.Application;
import com.m2049r.xmrwallet.util.Helper;
import timber.log.Timber; import timber.log.Timber;
public class XmrWalletApplication extends Application { public class XmrWalletApplication extends Application {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree()); Timber.plant(new Timber.DebugTree());
} }

View File

@@ -18,7 +18,10 @@ package com.m2049r.xmrwallet.data;
import android.net.Uri; import android.net.Uri;
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.BitcoinAddressValidator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -34,7 +37,7 @@ public class BarcodeData {
static final String BTC_AMOUNT = "amount"; static final String BTC_AMOUNT = "amount";
public enum Asset { public enum Asset {
XMR XMR, BTC
} }
public Asset asset = null; public Asset asset = null;
@@ -67,6 +70,14 @@ public class BarcodeData {
if (bcData == null) { if (bcData == null) {
bcData = parseMoneroNaked(qrCode); bcData = parseMoneroNaked(qrCode);
} }
// check for btc uri
if (bcData == null) {
bcData = parseBitcoinUri(qrCode);
}
// check for naked btc addres
if (bcData == null) {
bcData = parseBitcoinNaked(qrCode);
}
return bcData; return bcData;
} }
@@ -134,4 +145,57 @@ public class BarcodeData {
return new BarcodeData(Asset.XMR, address); return new BarcodeData(Asset.XMR, address);
} }
// bitcoin:mpQ84J43EURZHkCnXbyQ4PpNDLLBqdsMW2?amount=0.01
static public BarcodeData parseBitcoinUri(String uri) {
Timber.d("parseBitcoinUri=%s", uri);
if (uri == null) return null;
if (!uri.startsWith(BTC_SCHEME)) return null;
String noScheme = uri.substring(BTC_SCHEME.length());
Uri bitcoin = Uri.parse(noScheme);
Map<String, String> parms = new HashMap<>();
String query = bitcoin.getQuery();
if (query != null) {
String[] args = query.split("&");
for (String arg : args) {
String[] namevalue = arg.split("=");
if (namevalue.length == 0) {
continue;
}
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
namevalue.length > 1 ? Uri.decode(namevalue[1]) : "");
}
}
String address = bitcoin.getPath();
String amount = parms.get(BTC_AMOUNT);
if (amount != null) {
try {
Double.parseDouble(amount);
} catch (NumberFormatException ex) {
Timber.d(ex.getLocalizedMessage());
return null; // we have an amount but its not a number!
}
}
if (!BitcoinAddressValidator.validate(address)) {
Timber.d("address invalid");
return null;
}
return new BarcodeData(BarcodeData.Asset.BTC, address, amount);
}
static public BarcodeData parseBitcoinNaked(String address) {
Timber.d("parseBitcoinNaked=%s", address);
if (address == null) return null;
if (!BitcoinAddressValidator.validate(address)) {
Timber.d("address invalid");
return null;
}
return new BarcodeData(BarcodeData.Asset.BTC, address);
}
} }

View File

@@ -20,36 +20,38 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import com.m2049r.xmrwallet.model.PendingTransaction; import com.m2049r.xmrwallet.model.PendingTransaction;
import com.m2049r.xmrwallet.util.UserNotes;
import timber.log.Timber;
// https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents // https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents
public class TxData implements Parcelable { public class TxData implements Parcelable {
public TxData() {
}
public TxData(TxData txData) { public TxData(TxData txData) {
this.dst_addr = txData.dst_addr; this.dstAddr = txData.dstAddr;
this.paymentId = txData.paymentId; this.paymentId = txData.paymentId;
this.amount = txData.amount; this.amount = txData.amount;
this.mixin = txData.mixin; this.mixin = txData.mixin;
this.priority = txData.priority; this.priority = txData.priority;
} }
public TxData(String dst_addr, public TxData(String dstAddr,
String paymentId, String paymentId,
long amount, long amount,
int mixin, int mixin,
PendingTransaction.Priority priority) { PendingTransaction.Priority priority) {
this.dst_addr = dst_addr; this.dstAddr = dstAddr;
this.paymentId = paymentId; this.paymentId = paymentId;
this.amount = amount; this.amount = amount;
this.mixin = mixin; this.mixin = mixin;
this.priority = priority; this.priority = priority;
} }
public long getFee() {
return 0L;
}
public String getDestinationAddress() { public String getDestinationAddress() {
return dst_addr; return dstAddr;
} }
public String getPaymentId() { public String getPaymentId() {
@@ -68,15 +70,45 @@ public class TxData implements Parcelable {
return priority; return priority;
} }
final private String dst_addr; public void setDestinationAddress(String dstAddr) {
final private String paymentId; this.dstAddr = dstAddr;
final private long amount; }
final private int mixin;
final private PendingTransaction.Priority priority; public void setPaymentId(String paymentId) {
this.paymentId = paymentId;
}
public void setAmount(long amount) {
this.amount = amount;
}
public void setMixin(int mixin) {
this.mixin = mixin;
}
public void setPriority(PendingTransaction.Priority priority) {
this.priority = priority;
}
public UserNotes getUserNotes() {
return userNotes;
}
public void setUserNotes(UserNotes userNotes) {
this.userNotes = userNotes;
}
private String dstAddr;
private String paymentId;
private long amount;
private int mixin;
private PendingTransaction.Priority priority;
private UserNotes userNotes;
@Override @Override
public void writeToParcel(Parcel out, int flags) { public void writeToParcel(Parcel out, int flags) {
out.writeString(dst_addr); out.writeString(dstAddr);
out.writeString(paymentId); out.writeString(paymentId);
out.writeLong(amount); out.writeLong(amount);
out.writeInt(mixin); out.writeInt(mixin);
@@ -94,8 +126,8 @@ public class TxData implements Parcelable {
} }
}; };
private TxData(Parcel in) { protected TxData(Parcel in) {
dst_addr = in.readString(); dstAddr = in.readString();
paymentId = in.readString(); paymentId = in.readString();
amount = in.readLong(); amount = in.readLong();
mixin = in.readInt(); mixin = in.readInt();
@@ -111,8 +143,8 @@ public class TxData implements Parcelable {
@Override @Override
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append("dst_addr:"); sb.append("dstAddr:");
sb.append(dst_addr); sb.append(dstAddr);
sb.append(",paymentId:"); sb.append(",paymentId:");
sb.append(paymentId); sb.append(paymentId);
sb.append(",amount:"); sb.append(",amount:");

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2017 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 android.os.Parcel;
import com.m2049r.xmrwallet.model.PendingTransaction;
public class TxDataBtc extends TxData {
private String xmrtoUuid;
private String btcAddress;
private double btcAmount;
public TxDataBtc() {
super();
}
public TxDataBtc(TxDataBtc txDataBtc) {
super(txDataBtc);
}
public String getXmrtoUuid() {
return xmrtoUuid;
}
public void setXmrtoUuid(String xmrtoUuid) {
this.xmrtoUuid = xmrtoUuid;
}
public String getBtcAddress() {
return btcAddress;
}
public void setBtcAddress(String btcAddress) {
this.btcAddress = btcAddress;
}
public double getBtcAmount() {
return btcAmount;
}
public void setBtcAmount(double btcAmount) {
this.btcAmount = btcAmount;
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeString(xmrtoUuid);
out.writeString(btcAddress);
out.writeDouble(btcAmount);
}
// this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
public static final Creator<TxDataBtc> CREATOR = new Creator<TxDataBtc>() {
public TxDataBtc createFromParcel(Parcel in) {
return new TxDataBtc(in);
}
public TxDataBtc[] newArray(int size) {
return new TxDataBtc[size];
}
};
protected TxDataBtc(Parcel in) {
super(in);
xmrtoUuid = in.readString();
btcAddress = in.readString();
btcAmount = in.readDouble();
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(",xmrtoUuid:");
sb.append(xmrtoUuid);
sb.append(",btcAddress:");
sb.append(btcAddress);
sb.append(",btcAmount:");
sb.append(btcAmount);
return sb.toString();
}
}

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.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.m2049r.xmrwallet.R; 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"; static final String TAG = "DonationFragment";
public static DonationFragment newInstance() { public static CreditsFragment newInstance() {
return new DonationFragment(); return new CreditsFragment();
} }
public static void display(FragmentManager fm) { public static void display(FragmentManager fm) {
@@ -47,24 +45,14 @@ public class DonationFragment extends DialogFragment {
ft.remove(prev); ft.remove(prev);
} }
DonationFragment.newInstance().show(ft, TAG); CreditsFragment.newInstance().show(ft, TAG);
} }
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { 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))); ((TextView) view.findViewById(R.id.tvCredits)).setText(Html.fromHtml(getString(R.string.credits_text)));
(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();
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view); builder.setView(view);

View File

@@ -14,13 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet.fragment.send;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.TextInputLayout; import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.CardView; import android.support.v7.widget.CardView;
import android.text.Editable; import android.text.Editable;
import android.text.Html;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
@@ -32,9 +33,13 @@ import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.BarcodeData;
import com.m2049r.xmrwallet.data.TxData;
import com.m2049r.xmrwallet.data.TxDataBtc;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.BitcoinAddressValidator;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import timber.log.Timber; import timber.log.Timber;
@@ -56,12 +61,12 @@ public class SendAddressWizardFragment extends SendWizardFragment {
return this; return this;
} }
interface Listener { public interface Listener {
void setAddress(final String address);
void setPaymentId(final String paymentId);
void setBarcodeData(BarcodeData data); void setBarcodeData(BarcodeData data);
void setMode(SendFragment.Mode mode);
TxData getTxData();
} }
private EditText etDummy; private EditText etDummy;
@@ -71,6 +76,8 @@ public class SendAddressWizardFragment extends SendWizardFragment {
private CardView cvScan; private CardView cvScan;
private View tvPaymentIdIntegrated; private View tvPaymentIdIntegrated;
private View llPaymentId; private View llPaymentId;
private TextView tvXmrTo;
private View llXmrTo;
OnScanListener onScanListener; OnScanListener onScanListener;
@@ -89,6 +96,9 @@ public class SendAddressWizardFragment extends SendWizardFragment {
tvPaymentIdIntegrated = view.findViewById(R.id.tvPaymentIdIntegrated); tvPaymentIdIntegrated = view.findViewById(R.id.tvPaymentIdIntegrated);
llPaymentId = view.findViewById(R.id.llPaymentId); llPaymentId = view.findViewById(R.id.llPaymentId);
llXmrTo = view.findViewById(R.id.llXmrTo);
tvXmrTo = (TextView) view.findViewById(R.id.tvXmrTo);
tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto)));
etAddress = (TextInputLayout) view.findViewById(R.id.etAddress); etAddress = (TextInputLayout) view.findViewById(R.id.etAddress);
etAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); etAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
@@ -113,12 +123,25 @@ public class SendAddressWizardFragment extends SendWizardFragment {
public void afterTextChanged(Editable editable) { public void afterTextChanged(Editable editable) {
etAddress.setError(null); etAddress.setError(null);
if (isIntegratedAddress()) { if (isIntegratedAddress()) {
Timber.d("isIntegratedAddress");
etPaymentId.getEditText().getText().clear(); etPaymentId.getEditText().getText().clear();
llPaymentId.setVisibility(View.GONE); llPaymentId.setVisibility(View.INVISIBLE);
tvPaymentIdIntegrated.setVisibility(View.VISIBLE); tvPaymentIdIntegrated.setVisibility(View.VISIBLE);
} else { // we don't llXmrTo.setVisibility(View.INVISIBLE);
sendListener.setMode(SendFragment.Mode.XMR);
} else if (isBitcoinAddress()) {
Timber.d("isBitcoinAddress");
etPaymentId.getEditText().getText().clear();
llPaymentId.setVisibility(View.INVISIBLE);
tvPaymentIdIntegrated.setVisibility(View.INVISIBLE);
llXmrTo.setVisibility(View.VISIBLE);
sendListener.setMode(SendFragment.Mode.BTC);
} else {
Timber.d("isStandardAddress");
llPaymentId.setVisibility(View.VISIBLE); llPaymentId.setVisibility(View.VISIBLE);
tvPaymentIdIntegrated.setVisibility(View.GONE); tvPaymentIdIntegrated.setVisibility(View.INVISIBLE);
llXmrTo.setVisibility(View.INVISIBLE);
sendListener.setMode(SendFragment.Mode.XMR);
} }
} }
@@ -188,13 +211,14 @@ public class SendAddressWizardFragment extends SendWizardFragment {
private boolean checkAddressNoError() { private boolean checkAddressNoError() {
String address = etAddress.getEditText().getText().toString(); String address = etAddress.getEditText().getText().toString();
return Wallet.isAddressValid(address); return Wallet.isAddressValid(address)
|| BitcoinAddressValidator.validate(address);
} }
private boolean checkAddress() { private boolean checkAddress() {
boolean ok = checkAddressNoError(); boolean ok = checkAddressNoError();
if (!ok) { if (!ok) {
etAddress.setError(getString(R.string.send_qr_address_invalid)); etAddress.setError(getString(R.string.send_address_invalid));
} else { } else {
etAddress.setError(null); etAddress.setError(null);
} }
@@ -203,7 +227,16 @@ public class SendAddressWizardFragment extends SendWizardFragment {
private boolean isIntegratedAddress() { private boolean isIntegratedAddress() {
String address = etAddress.getEditText().getText().toString(); String address = etAddress.getEditText().getText().toString();
return (address.length() == INTEGRATED_ADDRESS_LENGTH) && Wallet.isAddressValid(address); return (address.length() == INTEGRATED_ADDRESS_LENGTH)
&& Wallet.isAddressValid(address);
}
private boolean isBitcoinAddress() {
String address = etAddress.getEditText().getText().toString();
if ((address.length() >= 27) && (address.length() <= 34))
return BitcoinAddressValidator.validate(address);
else
return false;
} }
private boolean checkPaymentId() { private boolean checkPaymentId() {
@@ -235,8 +268,15 @@ public class SendAddressWizardFragment extends SendWizardFragment {
} }
if (!ok) return false; if (!ok) return false;
if (sendListener != null) { if (sendListener != null) {
sendListener.setAddress(etAddress.getEditText().getText().toString()); TxData txData = sendListener.getTxData();
sendListener.setPaymentId(etPaymentId.getEditText().getText().toString()); if (isBitcoinAddress()) {
((TxDataBtc) txData).setBtcAddress(etAddress.getEditText().getText().toString());
txData.setDestinationAddress(null);
txData.setPaymentId("");
} else {
txData.setDestinationAddress(etAddress.getEditText().getText().toString());
txData.setPaymentId(etPaymentId.getEditText().getText().toString());
}
} }
return true; return true;
} }

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet.fragment.send;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -22,10 +22,12 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.BarcodeData;
import com.m2049r.xmrwallet.widget.ExchangeTextView; import com.m2049r.xmrwallet.data.TxData;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.widget.ExchangeTextView;
import com.m2049r.xmrwallet.widget.NumberPadView; import com.m2049r.xmrwallet.widget.NumberPadView;
import timber.log.Timber; import timber.log.Timber;
@@ -48,7 +50,7 @@ public class SendAmountWizardFragment extends SendWizardFragment {
interface Listener { interface Listener {
SendFragment.Listener getActivityCallback(); SendFragment.Listener getActivityCallback();
void setAmount(final long amount); TxData getTxData();
BarcodeData popBarcodeData(); BarcodeData popBarcodeData();
} }
@@ -99,9 +101,9 @@ public class SendAmountWizardFragment extends SendWizardFragment {
if (sendListener != null) { if (sendListener != null) {
String xmr = evAmount.getAmount(); String xmr = evAmount.getAmount();
if (xmr != null) { if (xmr != null) {
sendListener.setAmount(Wallet.getAmountFromString(xmr)); sendListener.getTxData().setAmount(Wallet.getAmountFromString(xmr));
} else { } else {
sendListener.setAmount(0L); sendListener.getTxData().setAmount(0L);
} }
} }
return true; return true;

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