1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-03 08:23:04 +02:00

Compare commits

...

129 Commits

Author SHA1 Message Date
m2049r
97fb0a5483 bump version 1.14.6 2020-09-21 22:11:35 +02:00
m2049r
fc950c6772 fix onboarding layout (#683) 2020-09-21 22:10:51 +02:00
m2049r
46add5e927 bump version v1.14.5 2020-09-21 14:37:51 +02:00
m2049r
fa0692ceab force agree for fingerprint send (#682) 2020-09-21 14:36:17 +02:00
m2049r
ff4f4a1c2c remove notices covered by onboarding (#681) 2020-09-21 14:35:50 +02:00
m2049r
79abb89725 disable button on finish onbaording (#680) 2020-09-21 14:35:25 +02:00
m2049r
ef8301fd6f bump version v1.14.4 2020-09-18 22:09:32 +02:00
hiddener
3a15c842ff updated Romanian translation 2020-09-18 22:01:41 +02:00
m2049r
1697da55b5 only update if we still have a wallet 2020-09-18 22:00:14 +02:00
m2049r
454f3e412a don't do stuff if the wallet is already closed 2020-09-18 22:00:14 +02:00
m2049r
d803a1e220 remove unused resources (#678) 2020-09-18 21:59:38 +02:00
m2049r
f2fe781cb5 update restore heights 2020-09-17 10:18:58 +02:00
m2049r
dcf60ae193 bump version v1.14.3 2020-09-17 09:35:28 +02:00
m2049r
ffdf54c2e1 Merge pull request #677 from m2049r/fix_various
Various fixes & tweaks
2020-09-17 09:34:04 +02:00
m2049r
c060a2ab88 don't show onboarding every time 2020-09-16 19:59:58 +02:00
m2049r
05fc654f3a clean up code 2020-09-16 18:56:27 +02:00
m2049r
c32d157150 monero addresses are 95 characters 2020-09-16 17:51:47 +02:00
m2049r
74e9278baa MainActivity must be singleTop 2020-09-16 17:45:07 +02:00
m2049r
e41e344d63 bump version v1.14.2 2020-09-14 18:16:35 +02:00
m2049r
e66875437d always show onboarding 2020-09-14 18:14:38 +02:00
m2049r
c1d2db3d7d onboarding tweaks & version bump (#676) 2020-09-14 00:24:57 +02:00
m2049r
0c9a2f5e01 fixups 2020-09-13 18:52:26 +02:00
m2049r
64616e3921 onboarding (#675)
Co-authored-by: Stephan <stephan.hagios@gmail.com>
2020-09-13 18:34:22 +02:00
m2049r
82b4d66987 allow spend with fingerprint only (#674) 2020-09-13 18:26:36 +02:00
m2049r
10f2bc6561 upgrade monero core (#673) 2020-09-05 11:01:34 +02:00
m2049r
2ed9a78d9e upgrade gradle 2020-07-16 14:14:26 +02:00
m2049r
ca19f32f8f bump version 2020-07-06 15:00:10 +02:00
m2049r
4431d74051 Fix for Ledger protocol v3 (#670)
* update protocol to V3 for Monero App v1.6.0
2020-07-06 14:59:38 +02:00
TheFuzzStone
f00da6ecda Renamed folder to '*-uk' and files to *-uk. (#666)
* Renamed folder to '*-uk' and files to `*-uk`. 
Changed '&apos;' to '\''

* Renamed file names
2020-06-20 18:07:43 +02:00
m2049r
1cecd0b718 xmr.to v3 API (#667) 2020-06-19 19:17:38 +02:00
m2049r
a0d6117bbb don't keepTimestampsInApk 2020-06-06 09:46:28 +02:00
m2049r
0b0648a172 upgrade dev env 2020-06-05 08:56:02 +02:00
m2049r
775dcf01ae bump version 2020-06-01 20:14:03 +02:00
m2049r
aed4051d44 Merge branch 'TheFuzzStone-master' 2020-06-01 20:09:51 +02:00
m2049r
a586c0781a renamed directory to match locale 2020-06-01 20:08:22 +02:00
m2049r
616d93cb18 replace &apos; 2020-06-01 20:04:55 +02:00
v1docq47
73d9cb6d58 Update for Russian translation (#649)
Update:
 - strings.xml

Co-authored-by: m2049r <m2049r@monerujo.io>
2020-06-01 19:57:33 +02:00
m2049r
9846e8b5cf fix progress bar (#665) 2020-06-01 19:56:24 +02:00
m2049r
aa66a12dac Merge branch 'master' into master 2020-06-01 13:43:16 +02:00
m2049r
65ce9b0889 Update blockheight (#664)
* update through june
2020-06-01 10:04:09 +02:00
m2049r
291e311b8a Enable rescan on wallet (from menu) (#663)
* rescan
2020-06-01 10:03:36 +02:00
m2049r
41290f51fd Upgrade to monero v0.16.0.0 (#662)
* upgrade to monero core v0.16.0.0

* hearts for node favs
2020-06-01 10:02:22 +02:00
m2049r
a11c898e2c bump version 2020-03-09 07:17:46 +01:00
m2049r
9c921183ab catch NPE (#655) 2020-03-08 22:29:02 +01:00
m2049r
b978396a38 fix versionCode 2020-03-08 20:46:23 +01:00
m2049r
c6aa04e986 update heights & fix date parsing bug (#654) 2020-03-08 20:33:34 +01:00
m2049r
6c17b8bd87 update gradle 2020-02-29 10:43:13 +01:00
TheFuzzStone
835a35c6a8 Updating Ukranian language 2020-02-13 13:49:52 +02:00
m2049r
cac32f660c v1.12.11 (monero v0.15.0.1) 2019-11-25 23:30:28 +01:00
m2049r
8e70004bf2 v1.12.10 2019-11-24 17:17:54 +01:00
m2049r
c3a466c392 remove payment id everywhere (#646) 2019-11-24 17:17:25 +01:00
m2049r
e076c19e3e v1.12.9 2019-11-21 10:42:45 +01:00
m2049r
35b717756d Fix amount bugs (#645)
* fix rounding error on send

* fix check funds bug
2019-11-21 10:42:16 +01:00
m2049r
c14486306e v1.12.8 2019-11-20 07:34:25 +01:00
m2049r
c2ef25c377 change error message to 16 for payment ids (#643) 2019-11-20 07:33:29 +01:00
m2049r
b7164ef200 fix XMR missing in open wallet (#642) 2019-11-20 07:33:07 +01:00
m2049r
f94a366d51 v1.12.7 2019-11-19 22:57:43 +01:00
m2049r
286a04b5ef add XMR to receive spinners (again) (#640) 2019-11-19 22:56:28 +01:00
m2049r
1209295a8c v1.12.6 2019-11-18 12:01:49 +01:00
m2049r
037b019d4d xmrto payment through subaddress (#639)
* use subaddress for xmrto only

* fix exchange rate
2019-11-18 12:00:39 +01:00
m2049r
7a1d788f2a UI tweaks (#638)
* fix amount entry field

* password entry on own line

* remove errors when typing; field spacing
2019-11-17 10:31:19 +01:00
m2049r
87d9a8cd95 use kraken for EURXMR exchange rate (#637)
combine with ECB rates for other fiat conversions
2019-11-17 00:42:57 +01:00
m2049r
f637d7f617 update block heights (#636) 2019-11-10 23:54:40 +01:00
m2049r
a4b9a7c6fb fix spend amount & new version (#635) 2019-11-10 15:23:33 +01:00
m2049r
9f01155cb7 v1.12.1 2019-11-10 12:14:52 +01:00
m2049r
08e8a48138 scan only for 0.15 nodes (#634) 2019-11-10 12:13:06 +01:00
m2049r
551c3b9fb6 scan only for 0.15 nodes (#633) 2019-11-10 12:11:01 +01:00
m2049r
2258cb7096 v1.12.0 (#632) 2019-11-10 11:08:19 +01:00
m2049r
6d61841cf3 textfields are filled (#631) 2019-11-10 11:06:34 +01:00
m2049r
c65508d288 upgrade to monero v0.15 (#630) 2019-11-09 22:45:54 +01:00
m2049r
2c3f582672 paste bip70 (#621) 2019-09-22 10:09:18 +02:00
m2049r
f46ba75771 update gradle version (#614) 2019-08-16 19:07:12 +02:00
m2049r
0ce5f2b6ca create ExchangeEditText & use without numpad (#613) 2019-08-04 13:19:42 +02:00
m2049r
110057c294 bump version to 1.11.13 2019-07-14 13:18:27 +02:00
m2049r
7553d3c5f4 Merge pull request #611 from m2049r/fix_heightfix
reduce restore height some more for new wallets
2019-07-14 12:53:24 +02:00
m2049r
317976b34a decrease restore height on new wallet 2019-07-14 12:52:43 +02:00
m2049r
6ad423567f Merge pull request #610 from m2049r/feature_showheight
show restore height
2019-07-14 12:52:21 +02:00
m2049r
d497158856 show restore height 2019-07-14 12:35:00 +02:00
m2049r
f4cada5fa1 Merge pull request #608 from m2049r/feature_nanox
Support for Nano X
2019-07-13 18:56:23 +02:00
m2049r
352f0ad09c update height for 2019-07-01 (#609) 2019-07-13 18:55:35 +02:00
m2049r
ff1a9c1570 verify monero app is running on nano 2019-07-13 18:44:56 +02:00
m2049r
fa811a39a2 accept Nano X over USB 2019-07-13 13:00:24 +02:00
m2049r
cf5018be33 kick 'Hintergrunddienst' (#607) 2019-06-23 21:26:29 +02:00
m2049r
8ec027f9d4 bump version 2019-06-21 08:47:22 +02:00
m2049r
f28428e677 update june restore height (#606) 2019-06-21 08:45:09 +02:00
m2049r
294084bec5 double size of node bookmark icon (#605) 2019-06-21 08:17:08 +02:00
m2049r
4349907627 setNode blocks => call it async (#604) 2019-06-18 08:49:51 +02:00
m2049r
f7cef24a83 fix NPE (#603) 2019-06-18 08:48:28 +02:00
m2049r
2774f99b15 bump version v1.11.10 2019-06-16 23:39:24 +02:00
m2049r
bc630fc445 Refactor secureflag (#600)
* one place to decide if screenshots enabled

* allow screenshots on alpha or debug
2019-06-16 23:28:52 +02:00
m2049r
895cf16d33 don't setDaemon when null (#601) 2019-06-16 23:28:34 +02:00
m2049r
7f1796b12e bump version v1.11.9 2019-06-16 21:49:11 +02:00
erciccione
abe5c8afab readme: update contact info of the localization workgroup (#593) 2019-06-16 21:48:32 +02:00
WiserB
47f79b5269 Serbian translation of strings.xml (sr - made by WiserB) (#595)
helps.xml and about.xml included but not translated
2019-06-16 21:33:52 +02:00
erciccione
c9c07eaa15 Catalan translation (by ambystomamex) (#596) 2019-06-16 21:28:42 +02:00
m2049r
a490e3af0c better status & error message handling (#599) 2019-06-16 21:22:56 +02:00
m2049r
64d5b3bdea tweaks for monero v0.14.1.0 (#598) 2019-06-16 21:13:01 +02:00
m2049r
bf91eaf22f deal with not finding any text on clipboard (#594) 2019-05-24 23:44:54 +02:00
m2049r
2c3e73b540 bump version v1.11.7 2019-05-22 08:30:11 +02:00
m2049r
830d9dadb9 paste receiver address (#592) 2019-05-20 17:17:46 +02:00
m2049r
331d88ebba use daemon height for new wallets if available (#591) 2019-05-20 17:17:27 +02:00
m2049r
7cc2f6fafb bump version v1.11.6 2019-05-19 21:34:26 +02:00
m2049r
9a3ee0eda8 fix update of account balances (#590) 2019-05-19 20:27:35 +02:00
m2049r
6e898939a3 show account balances (#589)
and refactor displayAmount
2019-05-19 17:33:19 +02:00
m2049r
40ae39d647 update studio 2019-05-19 10:28:18 +02:00
jindouyunz
ca81e652e5 Update strings.xml_Chinese (#575)
* Update strings.xml

updated on 4/22/2019 version 2, Jindouyunz.

* Update string.xml_Chinese 2019-5-12

Hi, I made several pieces of modification based on lafudoci's review, thanks.

* Update string.xml-zh-rCN 2019-5-13

removed all lines with "translatable=false", and currency array
2019-05-18 08:40:31 +02:00
jindouyunz
796048be4e Update about.xml (#574)
updated on 4/21/2019, Jindouyunz.
2019-05-18 08:39:49 +02:00
jindouyunz
441bf995c8 Update help.xml_Chinese (#573)
* Update help.xml

updated on 4/21/2019, version 2, Jindouyunz

* Update help.xml 2019-5-11

Hi, I add changes on line 200, based on lafudoci's review, thanks.
2019-05-18 08:39:28 +02:00
m2049r
e8860ab8eb focus on password if no fingerprint (#587) 2019-05-12 00:17:21 +02:00
m2049r
525b38ff53 remove save button for notes (#586) 2019-05-12 00:17:07 +02:00
m2049r
ba79bf87aa Update rpc checks (#585)
* check rpc version

* update protocol version check
2019-05-11 21:15:35 +02:00
m2049r
3fe6571e7d update restore heights for 4 & 5.2019 (#583) 2019-05-11 11:41:16 +02:00
erciccione
364e6a8137 update values-it/strings.xml (Italian translation) (#580) 2019-05-11 11:40:20 +02:00
vp11
cb69ce99d6 update pt-BR translation (#581)
* update pt-BR translation

* missing block
2019-05-11 11:40:01 +02:00
m2049r
1f976872fc increase sanity check size limit (#576) 2019-04-23 20:52:43 +02:00
kic0
27f266b6f7 PT-PT translations updated (#569) 2019-04-20 11:03:57 +02:00
m2049r
168928d54a Update studio (#572)
* gradle 5.1

* remove ref to @id/ibBookmark
2019-04-19 15:51:25 +02:00
Leza89
b3f61072aa V1.11.4 - german translations (#556)
* Corrections on the translation without translating

* Added missing commas, hyphens
* replaced diverging terminology with Monero GUI (i.e. Remote Node → Drittanbieter-Node, Saldo → Guthaben, Daemon/Dienst → Hintergrunddienst)
* grammatical adjustments
* unifying the gender of certain words (i.e. "die" Wallet)

* Translations - Draft for peer review

* Corrections according to rodolfo912's review

en-dash as a symbol vs. unicode ;#8211; is yet to be resolved

* Reverting case of "Wallet" from "die" to "das"

As requested by m2049r the article of "Wallet" was reverted back from "die Wallet" to "das Wallet" and corrected in places where it was inconsistent before.
2019-04-19 14:57:49 +02:00
Jack Rogers Lewis
ccb64aded0 SK update help.xml (#568) 2019-04-19 14:49:25 +02:00
Jack Rogers Lewis
e98fa089f2 update new strings (#567)
podadresa = subadresa
2019-04-19 14:48:47 +02:00
Scott Anecito
884878b7a7 Update Japanese localization, fix English typo (#564) 2019-04-19 14:43:56 +02:00
v1docq47
4e23f0ef3a Update for Russian translation #444 (#558)
* Update for Russian translation #444

* fix

added translation of missing lines (help.xml / strings.xml)
2019-03-19 20:12:37 +01:00
0140454
6ea4e3d998 Update zh-rTW translation (#557)
* Update zh-rTW translation

* Update translation for "Using a payment link"
2019-03-19 20:12:16 +01:00
m2049r
971c90f35b Merge pull request #559 from m2049r/feature_enable_ledger
Feature enable ledger
2019-03-19 20:06:17 +01:00
m2049r
f0523c403c bump version 2019-03-19 19:34:04 +01:00
m2049r
966ed23b87 enable ledger again 2019-03-19 19:32:38 +01:00
m2049r
95f2ca74a6 clean code (#555) 2019-03-10 22:00:57 +01:00
m2049r
81d94478f2 update wallet api (#554) 2019-03-10 21:49:57 +01:00
el00ruobuob
16ff779ebc New strings & help update to FR (#552) 2019-03-09 21:58:10 +01:00
165 changed files with 7359 additions and 4472 deletions

1
.gitignore vendored
View File

@@ -14,3 +14,4 @@
/app/prodMainnet /app/prodMainnet
/app/alphaStagenet /app/alphaStagenet
/app/prodStagenet /app/prodStagenet
/app/.cxx

File diff suppressed because one or more lines are too long

View File

@@ -137,7 +137,11 @@ set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION
add_library(device STATIC IMPORTED) add_library(device STATIC IMPORTED)
set_target_properties(device PROPERTIES IMPORTED_LOCATION set_target_properties(device PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice.a) ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice.a)
add_library(device_trezor STATIC IMPORTED)
set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice_trezor.a)
add_library(multisig STATIC IMPORTED) add_library(multisig STATIC IMPORTED)
set_target_properties(multisig PROPERTIES IMPORTED_LOCATION set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
@@ -147,6 +151,22 @@ add_library(version STATIC IMPORTED)
set_target_properties(version PROPERTIES IMPORTED_LOCATION set_target_properties(version PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libversion.a) ${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libversion.a)
add_library(net STATIC IMPORTED)
set_target_properties(net PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libnet.a)
add_library(hardforks STATIC IMPORTED)
set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libhardforks.a)
add_library(randomx STATIC IMPORTED)
set_target_properties(randomx PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/librandomx.a)
add_library(rpc_base STATIC IMPORTED)
set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/librpc_base.a)
############# #############
# System # System
############# #############
@@ -166,6 +186,7 @@ target_link_libraries( monerujo
mnemonics mnemonics
ringct ringct
ringct_basic ringct_basic
net
common common
cncrypto cncrypto
blockchain_db blockchain_db
@@ -176,8 +197,12 @@ target_link_libraries( monerujo
blocks blocks
checkpoints checkpoints
device device
device_trezor
multisig multisig
version version
randomx
hardforks
rpc_base
boost_chrono boost_chrono
boost_date_time boost_date_time

View File

@@ -2,14 +2,13 @@ apply plugin: 'com.android.application'
android { android {
compileSdkVersion 28 compileSdkVersion 28
buildToolsVersion '28.0.3' buildToolsVersion '29.0.2'
defaultConfig { defaultConfig {
applicationId "com.m2049r.xmrwallet" applicationId "com.m2049r.xmrwallet"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 28 targetSdkVersion 28
versionCode 173 versionCode 406
versionName "1.11.3 'Chernushka'" versionName "1.14.6 'On Board'"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild { externalNativeBuild {
cmake { cmake {
@@ -93,6 +92,11 @@ android {
outputFileName = "$rootProject.ext.apkName-" + v + "_" + abiName + ".apk" outputFileName = "$rootProject.ext.apkName-" + v + "_" + abiName + ".apk"
} }
} }
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
} }
dependencies { dependencies {
@@ -102,6 +106,7 @@ dependencies {
implementation "com.android.support:recyclerview-v7:$rootProject.ext.supportVersion" implementation "com.android.support:recyclerview-v7:$rootProject.ext.supportVersion"
implementation "com.android.support:cardview-v7:$rootProject.ext.supportVersion" implementation "com.android.support:cardview-v7:$rootProject.ext.supportVersion"
implementation "com.android.support:swiperefreshlayout:$rootProject.ext.supportVersion" implementation "com.android.support:swiperefreshlayout:$rootProject.ext.supportVersion"
implementation "com.android.support.constraint:constraint-layout:$rootProject.ext.constraintVersion"
implementation 'me.dm7.barcodescanner:zxing:1.9.8' implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion" implementation "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion"
@@ -124,5 +129,4 @@ dependencies {
testImplementation "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion" testImplementation "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion"
testImplementation 'org.json:json:20180813' testImplementation 'org.json:json:20180813'
testImplementation 'net.jodah:concurrentunit:0.4.4' testImplementation 'net.jodah:concurrentunit:0.4.4'
} }

View File

@@ -20,24 +20,27 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/MyMaterialTheme" android:theme="@style/MyMaterialTheme"
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true">
<activity android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTop"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity <activity
android:name=".WalletActivity" android:name=".WalletActivity"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
android:label="@string/wallet_activity_name" android:label="@string/wallet_activity_name"
android:launchMode="singleTask" android:launchMode="singleTask"
android:screenOrientation="behind" /> android:screenOrientation="behind" />
<activity <activity
android:name=".LoginActivity" android:name=".LoginActivity"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTop" android:launchMode="singleTop"
android:screenOrientation="locked"> android:screenOrientation="locked">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter> </intent-filter>
@@ -62,6 +65,10 @@
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/usb_device_filter" /> android:resource="@xml/usb_device_filter" />
</activity> </activity>
<activity android:name=".onboarding.OnBoardingActivity"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTask"
android:screenOrientation="portrait"/>
<service <service
android:name=".service.WalletService" android:name=".service.WalletService"
@@ -79,4 +86,4 @@
android:resource="@xml/filepaths" /> android:resource="@xml/filepaths" />
</provider> </provider>
</application> </application>
</manifest> </manifest>

View File

@@ -1,88 +0,0 @@
// Copyright (c) 2017-2018, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#if defined(HAVE_MONERUJO)
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief LedgerFind - find Ledger Device and return it's name
* @param buffer - buffer for name of found device
* @param len - length of buffer
* @return 0 - success
* -1 - no device connected / found
* -2 - JVM not found
*/
int LedgerFind(char *buffer, size_t len);
/**
* @brief LedgerExchange - exchange data with Ledger Device
* @param command - buffer for data to send
* @param cmd_len - length of send to send
* @param response - buffer for received data
* @param max_resp_len - size of receive buffer
*
* @return length of received data in response or -1 if error
*/
int LedgerExchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len);
#ifdef __cplusplus
}
#endif
#include "device_io.hpp"
#pragma once
namespace hw {
namespace io {
class device_io_monerujo: device_io {
public:
device_io_monerujo() {};
~device_io_monerujo() {};
void init() {};
void release() {};
void connect(void *params) {};
void disconnect() {};
bool connected() const {return true;}; // monerujo is always connected before it gets here
// returns number of bytes read or -1 on error
int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len) {
return LedgerExchange(command, cmd_len, response, max_resp_len);
}
};
};
};
#endif //#if defined(HAVE_MONERUJO)

File diff suppressed because it is too large Load Diff

View File

@@ -54,6 +54,8 @@ extern "C"
{ {
#endif #endif
extern const char* const MONERO_VERSION; // the actual monero core version
// from monero-core crypto/hash-ops.h - avoid #including monero code here // from monero-core crypto/hash-ops.h - avoid #including monero code here
enum { enum {
HASH_SIZE = 32, HASH_SIZE = 32,

View File

@@ -46,8 +46,12 @@ public class BTChipTransportAndroidHID implements BTChipTransport {
HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
for (UsbDevice device : deviceList.values()) { for (UsbDevice device : deviceList.values()) {
Timber.d("%04X:%04X %s, %s", device.getVendorId(), device.getProductId(), device.getManufacturerName(), device.getProductName()); Timber.d("%04X:%04X %s, %s", device.getVendorId(), device.getProductId(), device.getManufacturerName(), device.getProductName());
if ((device.getVendorId() == VID) && (device.getProductId() == PID_HID)) { if (device.getVendorId() == VID) {
return device; final int deviceProductId = device.getProductId();
for (int pid : PID_HIDS) {
if (deviceProductId == pid)
return device;
}
} }
} }
return null; return null;
@@ -74,7 +78,7 @@ public class BTChipTransportAndroidHID implements BTChipTransport {
} }
private static final int VID = 0x2C97; private static final int VID = 0x2C97;
private static final int PID_HID = 0x0001; private static final int[] PID_HIDS = {0x0001, 0x0004};
private UsbDeviceConnection connection; private UsbDeviceConnection connection;
private UsbInterface dongleInterface; private UsbInterface dongleInterface;

View File

@@ -79,6 +79,23 @@ public class GenerateFragment extends Fragment {
private String type = null; private String type = null;
private void clearErrorOnTextEntry(final TextInputLayout textInputLayout) {
textInputLayout.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
textInputLayout.setError(null);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@@ -110,6 +127,23 @@ public class GenerateFragment extends Fragment {
} }
} }
}); });
clearErrorOnTextEntry(etWalletName);
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) {
}
});
etWalletMnemonic.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() { etWalletMnemonic.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override @Override
public void onFocusChange(View v, boolean hasFocus) { public void onFocusChange(View v, boolean hasFocus) {
@@ -118,6 +152,8 @@ public class GenerateFragment extends Fragment {
} }
} }
}); });
clearErrorOnTextEntry(etWalletMnemonic);
etWalletAddress.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() { etWalletAddress.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override @Override
public void onFocusChange(View v, boolean hasFocus) { public void onFocusChange(View v, boolean hasFocus) {
@@ -126,6 +162,8 @@ public class GenerateFragment extends Fragment {
} }
} }
}); });
clearErrorOnTextEntry(etWalletAddress);
etWalletViewKey.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() { etWalletViewKey.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override @Override
public void onFocusChange(View v, boolean hasFocus) { public void onFocusChange(View v, boolean hasFocus) {
@@ -134,6 +172,8 @@ public class GenerateFragment extends Fragment {
} }
} }
}); });
clearErrorOnTextEntry(etWalletViewKey);
etWalletSpendKey.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() { etWalletSpendKey.getEditText().setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override @Override
public void onFocusChange(View v, boolean hasFocus) { public void onFocusChange(View v, boolean hasFocus) {
@@ -142,6 +182,7 @@ public class GenerateFragment extends Fragment {
} }
} }
}); });
clearErrorOnTextEntry(etWalletSpendKey);
Helper.showKeyboard(getActivity()); Helper.showKeyboard(getActivity());
@@ -310,21 +351,6 @@ 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(); initZxcvbn();
@@ -412,7 +438,7 @@ public class GenerateFragment extends Fragment {
height = RestoreHeight.getInstance().getHeight(parser.parse(restoreHeight)); height = RestoreHeight.getInstance().getHeight(parser.parse(restoreHeight));
} catch (ParseException ex) { } catch (ParseException ex) {
} }
if (height <= 0) if ((height <= 0) && (restoreHeight.length() == 8))
try { try {
// is it a date without dashes? // is it a date without dashes?
SimpleDateFormat parser = new SimpleDateFormat("yyyyMMdd"); SimpleDateFormat parser = new SimpleDateFormat("yyyyMMdd");
@@ -682,8 +708,7 @@ public class GenerateFragment extends Fragment {
} }
}); });
// set FLAG_SECURE to prevent screenshots in Release Mode if (Helper.preventScreenshot()) {
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
ledgerDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); ledgerDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} }

View File

@@ -55,6 +55,8 @@ import com.m2049r.xmrwallet.util.KeyStoreHelper;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor; import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import java.text.NumberFormat;
import timber.log.Timber; import timber.log.Timber;
public class GenerateReviewFragment extends Fragment { public class GenerateReviewFragment extends Fragment {
@@ -72,6 +74,7 @@ public class GenerateReviewFragment extends Fragment {
private TextView tvWalletPassword; private TextView tvWalletPassword;
private TextView tvWalletAddress; private TextView tvWalletAddress;
private TextView tvWalletMnemonic; private TextView tvWalletMnemonic;
private TextView tvWalletHeight;
private TextView tvWalletViewKey; private TextView tvWalletViewKey;
private TextView tvWalletSpendKey; private TextView tvWalletSpendKey;
private ImageButton bCopyAddress; private ImageButton bCopyAddress;
@@ -99,6 +102,7 @@ public class GenerateReviewFragment extends Fragment {
tvWalletViewKey = view.findViewById(R.id.tvWalletViewKey); tvWalletViewKey = view.findViewById(R.id.tvWalletViewKey);
tvWalletSpendKey = view.findViewById(R.id.tvWalletSpendKey); tvWalletSpendKey = view.findViewById(R.id.tvWalletSpendKey);
tvWalletMnemonic = view.findViewById(R.id.tvWalletMnemonic); tvWalletMnemonic = view.findViewById(R.id.tvWalletMnemonic);
tvWalletHeight = view.findViewById(R.id.tvWalletHeight);
bCopyAddress = view.findViewById(R.id.bCopyAddress); bCopyAddress = view.findViewById(R.id.bCopyAddress);
bAdvancedInfo = view.findViewById(R.id.bAdvancedInfo); bAdvancedInfo = view.findViewById(R.id.bAdvancedInfo);
llAdvancedInfo = view.findViewById(R.id.llAdvancedInfo); llAdvancedInfo = view.findViewById(R.id.llAdvancedInfo);
@@ -188,11 +192,12 @@ public class GenerateReviewFragment extends Fragment {
private class AsyncShow extends AsyncTask<String, Void, Boolean> { private class AsyncShow extends AsyncTask<String, Void, Boolean> {
String name; String name;
String address; String address;
long height;
String seed; String seed;
String viewKey; String viewKey;
String spendKey; String spendKey;
boolean isWatchOnly; boolean isWatchOnly;
Wallet.Status status; Wallet.Status walletStatus;
boolean dialogOpened = false; boolean dialogOpened = false;
@@ -224,14 +229,15 @@ public class GenerateReviewFragment extends Fragment {
closeWallet = true; closeWallet = true;
} }
name = wallet.getName(); name = wallet.getName();
status = wallet.getStatus(); walletStatus = wallet.getStatus();
if (status != Wallet.Status.Status_Ok) { if (!walletStatus.isOk()) {
Timber.e(wallet.getErrorString()); Timber.e(walletStatus.getErrorString());
if (closeWallet) wallet.close(); if (closeWallet) wallet.close();
return false; return false;
} }
address = wallet.getAddress(); address = wallet.getAddress();
height = wallet.getRestoreHeight();
seed = wallet.getSeed(); seed = wallet.getSeed();
switch (wallet.getDeviceType()) { switch (wallet.getDeviceType()) {
case Device_Ledger: case Device_Ledger:
@@ -264,6 +270,7 @@ public class GenerateReviewFragment extends Fragment {
llPassword.setVisibility(View.VISIBLE); llPassword.setVisibility(View.VISIBLE);
tvWalletPassword.setText(getPassword()); tvWalletPassword.setText(getPassword());
tvWalletAddress.setText(address); tvWalletAddress.setText(address);
tvWalletHeight.setText(NumberFormat.getInstance().format(height));
if (!seed.isEmpty()) { if (!seed.isEmpty()) {
llMnemonic.setVisibility(View.VISIBLE); llMnemonic.setVisibility(View.VISIBLE);
tvWalletMnemonic.setText(seed); tvWalletMnemonic.setText(seed);
@@ -287,10 +294,11 @@ public class GenerateReviewFragment extends Fragment {
GenerateReviewFragment.VIEW_TYPE_ACCEPT.equals(type) ? Toolbar.BUTTON_NONE : Toolbar.BUTTON_BACK); GenerateReviewFragment.VIEW_TYPE_ACCEPT.equals(type) ? Toolbar.BUTTON_NONE : Toolbar.BUTTON_BACK);
} else { } else {
// TODO show proper error message and/or end the fragment? // TODO show proper error message and/or end the fragment?
tvWalletAddress.setText(status.toString()); tvWalletAddress.setText(walletStatus.toString());
tvWalletMnemonic.setText(status.toString()); tvWalletHeight.setText(walletStatus.toString());
tvWalletViewKey.setText(status.toString()); tvWalletMnemonic.setText(walletStatus.toString());
tvWalletSpendKey.setText(status.toString()); tvWalletViewKey.setText(walletStatus.toString());
tvWalletSpendKey.setText(walletStatus.toString());
} }
hideProgress(); hideProgress();
} }
@@ -414,12 +422,13 @@ public class GenerateReviewFragment extends Fragment {
} }
boolean ok = false; boolean ok = false;
if (wallet.getStatus() == Wallet.Status.Status_Ok) { Wallet.Status walletStatus = wallet.getStatus();
if (walletStatus.isOk()) {
wallet.setPassword(newPassword); wallet.setPassword(newPassword);
wallet.store(); wallet.store();
ok = true; ok = true;
} else { } else {
Timber.e(wallet.getErrorString()); Timber.e(walletStatus.getErrorString());
} }
if (closeWallet) wallet.close(); if (closeWallet) wallet.close();
return ok; return ok;
@@ -621,8 +630,8 @@ public class GenerateReviewFragment extends Fragment {
return false; return false;
} }
}); });
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) { if (Helper.preventScreenshot()) {
openDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); openDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} }

View File

@@ -315,10 +315,14 @@ public class LoginActivity extends BaseActivity
if (WalletManager.getInstance().walletExists(walletFile)) { if (WalletManager.getInstance().walletExists(walletFile)) {
Helper.promptPassword(LoginActivity.this, walletName, true, new Helper.PasswordAction() { Helper.promptPassword(LoginActivity.this, walletName, true, new Helper.PasswordAction() {
@Override @Override
public void action(String walletName, String password, boolean fingerprintUsed) { public void act(String walletName, String password, boolean fingerprintUsed) {
if (checkDevice(walletName, password)) if (checkDevice(walletName, password))
startDetails(walletFile, password, GenerateReviewFragment.VIEW_TYPE_DETAILS); startDetails(walletFile, password, GenerateReviewFragment.VIEW_TYPE_DETAILS);
} }
@Override
public void fail(String walletName, String password, boolean fingerprintUsed) {
}
}); });
} else { // this cannot really happen as we prefilter choices } else { // this cannot really happen as we prefilter choices
Timber.e("Wallet missing: %s", walletName); Timber.e("Wallet missing: %s", walletName);
@@ -348,10 +352,14 @@ public class LoginActivity extends BaseActivity
if (WalletManager.getInstance().walletExists(walletFile)) { if (WalletManager.getInstance().walletExists(walletFile)) {
Helper.promptPassword(LoginActivity.this, walletName, false, new Helper.PasswordAction() { Helper.promptPassword(LoginActivity.this, walletName, false, new Helper.PasswordAction() {
@Override @Override
public void action(String walletName, String password, boolean fingerprintUsed) { public void act(String walletName, String password, boolean fingerprintUsed) {
if (checkDevice(walletName, password)) if (checkDevice(walletName, password))
startReceive(walletFile, password); startReceive(walletFile, password);
} }
@Override
public void fail(String walletName, String password, boolean fingerprintUsed) {
}
}); });
} else { // this cannot really happen as we prefilter choices } else { // this cannot really happen as we prefilter choices
Toast.makeText(this, getString(R.string.bad_wallet), Toast.LENGTH_SHORT).show(); Toast.makeText(this, getString(R.string.bad_wallet), Toast.LENGTH_SHORT).show();
@@ -918,6 +926,16 @@ public class LoginActivity extends BaseActivity
} }
boolean checkAndCloseWallet(Wallet aWallet) {
Wallet.Status walletStatus = aWallet.getStatus();
if (!walletStatus.isOk()) {
Timber.e(walletStatus.getErrorString());
toast(walletStatus.getErrorString());
}
aWallet.close();
return walletStatus.isOk();
}
@Override @Override
public void onGenerate(final String name, final String password) { public void onGenerate(final String name, final String password) {
createWallet(name, password, createWallet(name, password,
@@ -929,15 +947,13 @@ public class LoginActivity extends BaseActivity
@Override @Override
public boolean createWallet(File aFile, String password) { public boolean createWallet(File aFile, String password) {
NodeInfo currentNode = getNode();
// get it from the connected node if we have one, and go back ca. 4 days
final long restoreHeight =
(currentNode != null) ? currentNode.getHeight() - 2000 : -1;
Wallet newWallet = WalletManager.getInstance() Wallet newWallet = WalletManager.getInstance()
.createWallet(aFile, password, MNEMONIC_LANGUAGE); .createWallet(aFile, password, MNEMONIC_LANGUAGE, restoreHeight);
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok); return checkAndCloseWallet(newWallet);
if (!success) {
Timber.e(newWallet.getErrorString());
toast(newWallet.getErrorString());
}
newWallet.close();
return success;
} }
}); });
} }
@@ -956,13 +972,7 @@ public class LoginActivity extends BaseActivity
public boolean createWallet(File aFile, String password) { public boolean createWallet(File aFile, String password) {
Wallet newWallet = WalletManager.getInstance() Wallet newWallet = WalletManager.getInstance()
.recoveryWallet(aFile, password, seed, restoreHeight); .recoveryWallet(aFile, password, seed, restoreHeight);
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok); return checkAndCloseWallet(newWallet);
if (!success) {
Timber.e(newWallet.getErrorString());
toast(newWallet.getErrorString());
}
newWallet.close();
return success;
} }
}); });
} }
@@ -982,13 +992,7 @@ public class LoginActivity extends BaseActivity
Wallet newWallet = WalletManager.getInstance() Wallet newWallet = WalletManager.getInstance()
.createWalletFromDevice(aFile, password, .createWalletFromDevice(aFile, password,
restoreHeight, "Ledger"); restoreHeight, "Ledger");
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok); return checkAndCloseWallet(newWallet);
if (!success) {
Timber.e(newWallet.getErrorString());
toast(newWallet.getErrorString());
}
newWallet.close();
return success;
} }
}); });
} }
@@ -1009,13 +1013,7 @@ public class LoginActivity extends BaseActivity
Wallet newWallet = WalletManager.getInstance() Wallet newWallet = WalletManager.getInstance()
.createWalletWithKeys(aFile, password, MNEMONIC_LANGUAGE, restoreHeight, .createWalletWithKeys(aFile, password, MNEMONIC_LANGUAGE, restoreHeight,
address, viewKey, spendKey); address, viewKey, spendKey);
boolean success = (newWallet.getStatus() == Wallet.Status.Status_Ok); return checkAndCloseWallet(newWallet);
if (!success) {
Timber.e(newWallet.getErrorString());
toast(newWallet.getErrorString());
}
newWallet.close();
return success;
} }
}); });
} }
@@ -1316,10 +1314,15 @@ public class LoginActivity extends BaseActivity
Helper.promptPassword(LoginActivity.this, walletName, false, Helper.promptPassword(LoginActivity.this, walletName, false,
new Helper.PasswordAction() { new Helper.PasswordAction() {
@Override @Override
public void action(String walletName, String password, boolean fingerprintUsed) { public void act(String walletName, String password, boolean fingerprintUsed) {
if (checkDevice(walletName, password)) if (checkDevice(walletName, password))
startWallet(walletName, password, fingerprintUsed, streetmode); startWallet(walletName, password, fingerprintUsed, streetmode);
} }
@Override
public void fail(String walletName, String password, boolean fingerprintUsed) {
}
}); });
} else { // this cannot really happen as we prefilter choices } else { // this cannot really happen as we prefilter choices
Toast.makeText(this, getString(R.string.bad_wallet), Toast.LENGTH_SHORT).show(); Toast.makeText(this, getString(R.string.bad_wallet), Toast.LENGTH_SHORT).show();
@@ -1370,17 +1373,30 @@ public class LoginActivity extends BaseActivity
if (Ledger.ENABLED) if (Ledger.ENABLED)
try { try {
Ledger.connect(usbManager, usbDevice); Ledger.connect(usbManager, usbDevice);
registerDetachReceiver(); if (!Ledger.check()) {
onLedgerAction(); Ledger.disconnect();
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Toast.makeText(LoginActivity.this, Toast.makeText(LoginActivity.this,
getString(R.string.toast_ledger_attached, usbDevice.getProductName()), getString(R.string.toast_ledger_start_app, usbDevice.getProductName()),
Toast.LENGTH_SHORT) Toast.LENGTH_SHORT)
.show(); .show();
} }
}); });
} else {
registerDetachReceiver();
onLedgerAction();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.toast_ledger_attached, usbDevice.getProductName()),
Toast.LENGTH_SHORT)
.show();
}
});
}
} catch (IOException ex) { } catch (IOException ex) {
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
@Override @Override

View File

@@ -439,10 +439,13 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
} }
Collections.sort(nodesToTest, NodeInfo.BestNodeComparator); Collections.sort(nodesToTest, NodeInfo.BestNodeComparator);
NodeInfo bestNode = nodesToTest.get(0); NodeInfo bestNode = nodesToTest.get(0);
if (bestNode.isValid()) if (bestNode.isValid()) {
return nodesToTest.get(0); activityCallback.setNode(bestNode);
else return bestNode;
} else {
activityCallback.setNode(null);
return null; return null;
}
} }
@Override @Override
@@ -450,7 +453,6 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
if (!isAdded()) return; if (!isAdded()) return;
pbNode.setVisibility(View.INVISIBLE); pbNode.setVisibility(View.INVISIBLE);
llNode.setVisibility(View.VISIBLE); llNode.setVisibility(View.VISIBLE);
activityCallback.setNode(result);
if (result != null) { if (result != null) {
Timber.d("found a good node %s", result.toString()); Timber.d("found a good node %s", result.toString());
showNode(result); showNode(result);

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2020 EarlOfEgo, 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;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import com.m2049r.xmrwallet.onboarding.OnBoardingActivity;
import com.m2049r.xmrwallet.onboarding.OnBoardingManager;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (OnBoardingManager.shouldShowOnBoarding(getApplicationContext())) {
startActivity(new Intent(this, OnBoardingActivity.class));
} else {
startActivity(new Intent(this, LoginActivity.class));
}
finish();
}
}

View File

@@ -266,6 +266,7 @@ public class NodeFragment extends Fragment
seedList.add(new NodeInfo(new InetSocketAddress("198.74.231.92", 18080))); seedList.add(new NodeInfo(new InetSocketAddress("198.74.231.92", 18080)));
seedList.add(new NodeInfo(new InetSocketAddress("195.154.123.123", 18080))); seedList.add(new NodeInfo(new InetSocketAddress("195.154.123.123", 18080)));
seedList.add(new NodeInfo(new InetSocketAddress("212.83.172.165", 18080))); seedList.add(new NodeInfo(new InetSocketAddress("212.83.172.165", 18080)));
seedList.add(new NodeInfo(new InetSocketAddress("192.110.160.146", 18080)));
d.seedPeers(seedList); d.seedPeers(seedList);
d.awaitTermination(NODES_TO_FIND); d.awaitTermination(NODES_TO_FIND);
} }
@@ -506,8 +507,8 @@ public class NodeFragment extends Fragment
}); });
} }
}); });
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) { if (Helper.preventScreenshot()) {
editDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); editDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} }

View File

@@ -302,7 +302,7 @@ public class ReceiveFragment extends Fragment {
File imagePath = new File(getActivity().getCacheDir(), "images"); File imagePath = new File(getActivity().getCacheDir(), "images");
File png = new File(imagePath, "QR.png"); File png = new File(imagePath, "QR.png");
Uri contentUri = FileProvider.getUriForFile(getActivity(), Uri contentUri = FileProvider.getUriForFile(getActivity(),
"com.m2049r.xmrwallet.fileprovider", png); BuildConfig.APPLICATION_ID + ".fileprovider", png);
if (contentUri != null) { if (contentUri != null) {
Intent shareIntent = new Intent(); Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND); shareIntent.setAction(Intent.ACTION_SEND);
@@ -574,6 +574,7 @@ public class ReceiveFragment extends Fragment {
@Override @Override
public void onPause() { public void onPause() {
Timber.d("onPause()"); Timber.d("onPause()");
Helper.hideKeyboard(getActivity());
super.onPause(); super.onPause();
} }

View File

@@ -21,6 +21,7 @@ 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 com.m2049r.xmrwallet.util.LocaleHelper; import com.m2049r.xmrwallet.util.LocaleHelper;
import static android.view.WindowManager.LayoutParams; import static android.view.WindowManager.LayoutParams;
@@ -30,8 +31,7 @@ public abstract class SecureActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// set FLAG_SECURE to prevent screenshots in Release Mode if (Helper.preventScreenshot()) {
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE); getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
} }
} }

View File

@@ -71,7 +71,6 @@ public class TxFragment extends Fragment {
private TextView tvTxFee; private TextView tvTxFee;
private TextView tvTxTransfers; private TextView tvTxTransfers;
private TextView etTxNotes; private TextView etTxNotes;
private Button bTxNotes;
// XMRTO stuff // XMRTO stuff
private View cvXmrTo; private View cvXmrTo;
@@ -102,21 +101,9 @@ public class TxFragment extends Fragment {
tvTxFee = view.findViewById(R.id.tvTxFee); tvTxFee = view.findViewById(R.id.tvTxFee);
tvTxTransfers = view.findViewById(R.id.tvTxTransfers); tvTxTransfers = view.findViewById(R.id.tvTxTransfers);
etTxNotes = view.findViewById(R.id.etTxNotes); etTxNotes = view.findViewById(R.id.etTxNotes);
bTxNotes = view.findViewById(R.id.bTxNotes);
etTxNotes.setRawInputType(InputType.TYPE_CLASS_TEXT); etTxNotes.setRawInputType(InputType.TYPE_CLASS_TEXT);
bTxNotes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
info.notes = null; // force reload on next view
bTxNotes.setEnabled(false);
etTxNotes.setEnabled(false);
userNotes.setNote(etTxNotes.getText().toString());
activityCallback.onSetNote(info.hash, userNotes.txNotes);
}
});
tvTxXmrToKey.setOnClickListener(new View.OnClickListener() { tvTxXmrToKey.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@@ -131,14 +118,6 @@ public class TxFragment extends Fragment {
return view; return view;
} }
public void onNotesSet(boolean reload) {
bTxNotes.setEnabled(true);
etTxNotes.setEnabled(true);
if (reload) {
loadNotes(this.info);
}
}
void shareTxInfo() { void shareTxInfo() {
if (this.info == null) return; if (this.info == null) return;
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
@@ -315,7 +294,6 @@ public class TxFragment extends Fragment {
} }
} }
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -337,9 +315,9 @@ public class TxFragment extends Fragment {
String getTxNotes(String hash); String getTxNotes(String hash);
String getTxAddress(int major, int minor); boolean setTxNotes(String txId, String txNotes);
void onSetNote(String txId, String notes); String getTxAddress(int major, int minor);
void setToolbarButton(int type); void setToolbarButton(int type);
@@ -357,4 +335,16 @@ public class TxFragment extends Fragment {
+ " must implement Listener"); + " must implement Listener");
} }
} }
}
@Override
public void onPause() {
if (!etTxNotes.getText().toString().equals(userNotes.note)) { // notes have changed
// save them
userNotes.setNote(etTxNotes.getText().toString());
info.notes = userNotes.txNotes;
activityCallback.setTxNotes(info.hash, info.notes);
}
Helper.hideKeyboard(getActivity());
super.onPause();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -50,9 +50,8 @@ import com.m2049r.xmrwallet.widget.Toolbar;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import timber.log.Timber; import timber.log.Timber;
@@ -114,9 +113,12 @@ public class WalletFragment extends Fragment
ivSynced = view.findViewById(R.id.ivSynced); ivSynced = view.findViewById(R.id.ivSynced);
sCurrency = view.findViewById(R.id.sCurrency); sCurrency = view.findViewById(R.id.sCurrency);
ArrayAdapter currencyAdapter = ArrayAdapter.createFromResource(getContext(), R.array.currency, R.layout.item_spinner_balance); List<String> currencies = new ArrayList<>();
currencyAdapter.setDropDownViewResource(R.layout.item_spinner_dropdown_item); currencies.add(Helper.BASE_CRYPTO);
sCurrency.setAdapter(currencyAdapter); currencies.addAll(Arrays.asList(getResources().getStringArray(R.array.currency)));
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(getContext(), R.layout.item_spinner_balance, currencies);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sCurrency.setAdapter(spinnerAdapter);
bSend = view.findViewById(R.id.bSend); bSend = view.findViewById(R.id.bSend);
bReceive = view.findViewById(R.id.bReceive); bReceive = view.findViewById(R.id.bReceive);
@@ -219,8 +221,8 @@ public class WalletFragment extends Fragment
if (isExchanging) return; // wait for exchange to finish - it will fire this itself then. if (isExchanging) return; // wait for exchange to finish - it will fire this itself then.
// at this point selection is XMR in case of error // at this point selection is XMR in case of error
String displayB; String displayB;
double amountA = Double.parseDouble(Wallet.getDisplayAmount(unlockedBalance)); // crash if this fails! double amountA = Helper.getDecimalAmount(unlockedBalance).doubleValue();
if (!Helper.CRYPTO.equals(balanceCurrency)) { // not XMR if (!Helper.BASE_CRYPTO.equals(balanceCurrency)) { // not XMR
double amountB = amountA * balanceRate; double amountB = amountA * balanceRate;
displayB = Helper.getFormattedAmount(amountB, false); displayB = Helper.getFormattedAmount(amountB, false);
} else { // XMR } else { // XMR
@@ -229,23 +231,23 @@ public class WalletFragment extends Fragment
showBalance(displayB); showBalance(displayB);
} }
String balanceCurrency = Helper.CRYPTO; String balanceCurrency = Helper.BASE_CRYPTO;
double balanceRate = 1.0; double balanceRate = 1.0;
private final ExchangeApi exchangeApi = Helper.getExchangeApi(); private final ExchangeApi exchangeApi = Helper.getExchangeApi();
void refreshBalance() { void refreshBalance() {
double unconfirmedXmr = Double.parseDouble(Helper.getDisplayAmount(balance - unlockedBalance)); double unconfirmedXmr = Helper.getDecimalAmount(balance - unlockedBalance).doubleValue();
showUnconfirmed(unconfirmedXmr); showUnconfirmed(unconfirmedXmr);
if (sCurrency.getSelectedItemPosition() == 0) { // XMR if (sCurrency.getSelectedItemPosition() == 0) { // XMR
double amountXmr = Double.parseDouble(Wallet.getDisplayAmount(unlockedBalance)); // assume this cannot fail! double amountXmr = Helper.getDecimalAmount(unlockedBalance).doubleValue();
showBalance(Helper.getFormattedAmount(amountXmr, true)); showBalance(Helper.getFormattedAmount(amountXmr, true));
} else { // not XMR } else { // not XMR
String currency = (String) sCurrency.getSelectedItem(); String currency = (String) sCurrency.getSelectedItem();
Timber.d(currency); Timber.d(currency);
if (!currency.equals(balanceCurrency) || (balanceRate <= 0)) { if (!currency.equals(balanceCurrency) || (balanceRate <= 0)) {
showExchanging(); showExchanging();
exchangeApi.queryExchangeRate(Helper.CRYPTO, currency, exchangeApi.queryExchangeRate(Helper.BASE_CRYPTO, currency,
new ExchangeCallback() { new ExchangeCallback() {
@Override @Override
public void onSuccess(final ExchangeRate exchangeRate) { public void onSuccess(final ExchangeRate exchangeRate) {
@@ -294,17 +296,17 @@ public class WalletFragment extends Fragment
public void exchangeFailed() { public void exchangeFailed() {
sCurrency.setSelection(0, true); // default to XMR sCurrency.setSelection(0, true); // default to XMR
double amountXmr = Double.parseDouble(Wallet.getDisplayAmount(unlockedBalance)); // assume this cannot fail! double amountXmr = Helper.getDecimalAmount(unlockedBalance).doubleValue();
showBalance(Helper.getFormattedAmount(amountXmr, true)); showBalance(Helper.getFormattedAmount(amountXmr, true));
hideExchanging(); hideExchanging();
} }
public void exchange(final ExchangeRate exchangeRate) { public void exchange(final ExchangeRate exchangeRate) {
hideExchanging(); hideExchanging();
if (!Helper.CRYPTO.equals(exchangeRate.getBaseCurrency())) { if (!Helper.BASE_CRYPTO.equals(exchangeRate.getBaseCurrency())) {
Timber.e("Not XMR"); Timber.e("Not XMR");
sCurrency.setSelection(0, true); sCurrency.setSelection(0, true);
balanceCurrency = Helper.CRYPTO; balanceCurrency = Helper.BASE_CRYPTO;
balanceRate = 1.0; balanceRate = 1.0;
} else { } else {
int spinnerPosition = ((ArrayAdapter) sCurrency.getAdapter()).getPosition(exchangeRate.getQuoteCurrency()); int spinnerPosition = ((ArrayAdapter) sCurrency.getAdapter()).getPosition(exchangeRate.getQuoteCurrency());
@@ -354,6 +356,15 @@ public class WalletFragment extends Fragment
if (isVisible()) enableAccountsList(true); //otherwise it is enabled in onResume() if (isVisible()) enableAccountsList(true); //otherwise it is enabled in onResume()
} }
public void unsync() {
if (!activityCallback.isWatchOnly()) {
bSend.setVisibility(View.INVISIBLE);
bSend.setEnabled(false);
}
if (isVisible()) enableAccountsList(false); //otherwise it is enabled in onResume()
firstBlock = 0;
}
boolean walletLoaded = false; boolean walletLoaded = false;
public void onLoaded() { public void onLoaded() {

View File

@@ -59,42 +59,36 @@ public class BarcodeData {
final public Asset asset; final public Asset asset;
final public String address; final public String address;
final public String addressName; final public String addressName;
final public String paymentId;
final public String amount; final public String amount;
final public String description; final public String description;
final public Security security; final public Security security;
final public String bip70; final public String bip70;
public BarcodeData(Asset asset, String address) { public BarcodeData(Asset asset, String address) {
this(asset, address, null, null, null, null, Security.NORMAL); this(asset, address, null, null, null, Security.NORMAL);
} }
public BarcodeData(Asset asset, String address, String amount) { public BarcodeData(Asset asset, String address, String amount) {
this(asset, address, null, null, null, amount, Security.NORMAL); this(asset, address, null, null, amount, Security.NORMAL);
} }
public BarcodeData(Asset asset, String address, String amount, String description, Security security) { public BarcodeData(Asset asset, String address, String amount, String description, Security security) {
this(asset, address, null, null, description, amount, security); this(asset, address, null, description, amount, security);
}
public BarcodeData(Asset asset, String address, String paymentId, String amount) {
this(asset, address, null, paymentId, null, amount, Security.NORMAL);
} }
public BarcodeData(Asset asset, String address, String paymentId, String description, String amount) { public BarcodeData(Asset asset, String address, String paymentId, String description, String amount) {
this(asset, address, null, paymentId, description, amount, Security.NORMAL); this(asset, address, null, description, amount, Security.NORMAL);
} }
public BarcodeData(Asset asset, String address, String addressName, String paymentId, String description, String amount, Security security) { public BarcodeData(Asset asset, String address, String addressName, String description, String amount, Security security) {
this(asset, address, addressName, null, paymentId, description, amount, security); this(asset, address, addressName, null, description, amount, security);
} }
public BarcodeData(Asset asset, String address, String addressName, String bip70, String paymentId, String description, String amount, Security security) { public BarcodeData(Asset asset, String address, String addressName, String bip70, String description, String amount, Security security) {
this.asset = asset; this.asset = asset;
this.address = address; this.address = address;
this.bip70 = bip70; this.bip70 = bip70;
this.addressName = addressName; this.addressName = addressName;
this.paymentId = paymentId;
this.description = description; this.description = description;
this.amount = amount; this.amount = amount;
this.security = security; this.security = security;
@@ -110,11 +104,6 @@ public class BarcodeData {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(BarcodeData.XMR_SCHEME).append(address); sb.append(BarcodeData.XMR_SCHEME).append(address);
boolean first = true; boolean first = true;
if ((paymentId != null) && !paymentId.isEmpty()) {
sb.append("?");
first = false;
sb.append(BarcodeData.XMR_PAYMENTID).append('=').append(paymentId);
}
if ((description != null) && !description.isEmpty()) { if ((description != null) && !description.isEmpty()) {
sb.append(first ? "?" : "&"); sb.append(first ? "?" : "&");
first = false; first = false;
@@ -185,8 +174,11 @@ public class BarcodeData {
String address = monero.getPath(); String address = monero.getPath();
String paymentId = parms.get(XMR_PAYMENTID); String paymentId = parms.get(XMR_PAYMENTID);
// deal with empty payment_id created by non-spec-conforming apps // no support for payment ids!
if ((paymentId != null) && paymentId.isEmpty()) paymentId = null; if (paymentId != null) {
Timber.e("no support for payment ids!");
return null;
}
String description = parms.get(XMR_DESCRIPTION); String description = parms.get(XMR_DESCRIPTION);
String amount = parms.get(XMR_AMOUNT); String amount = parms.get(XMR_AMOUNT);
@@ -198,10 +190,6 @@ public class BarcodeData {
return null; // we have an amount but its not a number! return null; // we have an amount but its not a number!
} }
} }
if ((paymentId != null) && !Wallet.isPaymentIdValid(paymentId)) {
Timber.d("paymentId invalid");
return null;
}
if (!Wallet.isAddressValid(address)) { if (!Wallet.isAddressValid(address)) {
Timber.d("address invalid"); Timber.d("address invalid");
@@ -267,7 +255,7 @@ public class BarcodeData {
Timber.d("[%s] is not http url", bip70); Timber.d("[%s] is not http url", bip70);
return null; return null;
} }
return new BarcodeData(BarcodeData.Asset.BTC, null, null, bip70, null, description, null, Security.NORMAL); return new BarcodeData(BarcodeData.Asset.BTC, null, null, bip70, description, null, Security.NORMAL);
} }
if (!BitcoinAddressValidator.validate(address)) { if (!BitcoinAddressValidator.validate(address)) {
Timber.d("BTC address (%s) invalid", address); Timber.d("BTC address (%s) invalid", address);

View File

@@ -46,7 +46,8 @@ import okhttp3.ResponseBody;
import timber.log.Timber; import timber.log.Timber;
public class NodeInfo extends Node { public class NodeInfo extends Node {
final static public int MIN_MAJOR_VERSION = 9; final static public int MIN_MAJOR_VERSION = 11;
final static public String RPC_VERSION = "2.0";
private long height = 0; private long height = 0;
private long timestamp = 0; private long timestamp = 0;
@@ -228,11 +229,16 @@ public class NodeInfo extends Node {
responseCode = response.code(); responseCode = response.code();
if (response.isSuccessful()) { if (response.isSuccessful()) {
ResponseBody respBody = response.body(); // closed through Response object ResponseBody respBody = response.body(); // closed through Response object
if ((respBody != null) && (respBody.contentLength() < 1000)) { // sanity check if ((respBody != null) && (respBody.contentLength() < 2000)) { // sanity check
final JSONObject json = new JSONObject( final JSONObject json = new JSONObject(
respBody.string()); respBody.string());
final JSONObject header = json.getJSONObject( String rpcVersion = json.getString("jsonrpc");
"result").getJSONObject("block_header"); if (!RPC_VERSION.equals(rpcVersion))
return false;
final JSONObject result = json.getJSONObject("result");
if (!result.has("credits")) // introduced in monero v0.15.0
return false;
final JSONObject header = result.getJSONObject("block_header");
height = header.getLong("height"); height = header.getLong("height");
timestamp = header.getLong("timestamp"); timestamp = header.getLong("timestamp");
majorVersion = header.getInt("major_version"); majorVersion = header.getInt("major_version");

View File

@@ -29,19 +29,16 @@ public class TxData implements Parcelable {
public TxData(TxData txData) { public TxData(TxData txData) {
this.dstAddr = txData.dstAddr; this.dstAddr = txData.dstAddr;
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 dstAddr, public TxData(String dstAddr,
String paymentId,
long amount, long amount,
int mixin, int mixin,
PendingTransaction.Priority priority) { PendingTransaction.Priority priority) {
this.dstAddr = dstAddr; this.dstAddr = dstAddr;
this.paymentId = paymentId;
this.amount = amount; this.amount = amount;
this.mixin = mixin; this.mixin = mixin;
this.priority = priority; this.priority = priority;
@@ -51,10 +48,6 @@ public class TxData implements Parcelable {
return dstAddr; return dstAddr;
} }
public String getPaymentId() {
return paymentId;
}
public long getAmount() { public long getAmount() {
return amount; return amount;
} }
@@ -71,10 +64,6 @@ public class TxData implements Parcelable {
this.dstAddr = dstAddr; this.dstAddr = dstAddr;
} }
public void setPaymentId(String paymentId) {
this.paymentId = paymentId;
}
public void setAmount(long amount) { public void setAmount(long amount) {
this.amount = amount; this.amount = amount;
} }
@@ -96,7 +85,6 @@ public class TxData implements Parcelable {
} }
private String dstAddr; private String dstAddr;
private String paymentId;
private long amount; private long amount;
private int mixin; private int mixin;
private PendingTransaction.Priority priority; private PendingTransaction.Priority priority;
@@ -106,7 +94,6 @@ public class TxData implements Parcelable {
@Override @Override
public void writeToParcel(Parcel out, int flags) { public void writeToParcel(Parcel out, int flags) {
out.writeString(dstAddr); out.writeString(dstAddr);
out.writeString(paymentId);
out.writeLong(amount); out.writeLong(amount);
out.writeInt(mixin); out.writeInt(mixin);
out.writeInt(priority.getValue()); out.writeInt(priority.getValue());
@@ -125,7 +112,6 @@ public class TxData implements Parcelable {
protected TxData(Parcel in) { protected TxData(Parcel in) {
dstAddr = in.readString(); dstAddr = in.readString();
paymentId = in.readString();
amount = in.readLong(); amount = in.readLong();
mixin = in.readInt(); mixin = in.readInt();
priority = PendingTransaction.Priority.fromInteger(in.readInt()); priority = PendingTransaction.Priority.fromInteger(in.readInt());
@@ -142,14 +128,12 @@ public class TxData implements Parcelable {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append("dstAddr:"); sb.append("dstAddr:");
sb.append(dstAddr); sb.append(dstAddr);
sb.append(",paymentId:");
sb.append(paymentId);
sb.append(",amount:"); sb.append(",amount:");
sb.append(amount); sb.append(amount);
sb.append(",mixin:"); sb.append(",mixin:");
sb.append(mixin); sb.append(mixin);
sb.append(",priority:"); sb.append(",priority:");
sb.append(String.valueOf(priority)); sb.append(priority);
return sb.toString(); return sb.toString();
} }
} }

View File

@@ -28,6 +28,7 @@ import android.widget.TextView;
import com.m2049r.xmrwallet.BuildConfig; import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.util.Helper;
import java.util.Locale; import java.util.Locale;
@@ -76,8 +77,7 @@ public class ProgressDialog extends AlertDialog {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// set FLAG_SECURE to prevent screenshots in Release Mode if (Helper.preventScreenshot()) {
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} }
} }

View File

@@ -31,9 +31,10 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton;
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.data.BarcodeData; import com.m2049r.xmrwallet.data.BarcodeData;
@@ -84,14 +85,12 @@ public class SendAddressWizardFragment extends SendWizardFragment {
private EditText etDummy; private EditText etDummy;
private TextInputLayout etAddress; private TextInputLayout etAddress;
private TextInputLayout etPaymentId;
private TextInputLayout etNotes; private TextInputLayout etNotes;
private Button bPaymentId;
private CardView cvScan; private CardView cvScan;
private View tvPaymentIdIntegrated; private View tvPaymentIdIntegrated;
private View llPaymentId;
private TextView tvXmrTo; private TextView tvXmrTo;
private View llXmrTo; private View llXmrTo;
private ImageButton bPasteAddress;
private boolean resolvingOA = false; private boolean resolvingOA = false;
private boolean resolvingPP = false; private boolean resolvingPP = false;
@@ -111,7 +110,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
View view = inflater.inflate(R.layout.fragment_send_address, container, false); View view = inflater.inflate(R.layout.fragment_send_address, container, false);
tvPaymentIdIntegrated = view.findViewById(R.id.tvPaymentIdIntegrated); tvPaymentIdIntegrated = view.findViewById(R.id.tvPaymentIdIntegrated);
llPaymentId = view.findViewById(R.id.llPaymentId);
llXmrTo = view.findViewById(R.id.llXmrTo); llXmrTo = view.findViewById(R.id.llXmrTo);
tvXmrTo = view.findViewById(R.id.tvXmrTo); tvXmrTo = view.findViewById(R.id.tvXmrTo);
tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto))); tvXmrTo.setText(Html.fromHtml(getString(R.string.info_xmrto)));
@@ -137,28 +135,12 @@ public class SendAddressWizardFragment extends SendWizardFragment {
next = null; next = null;
} else { } else {
// maybe a bip72 or 70 URI // maybe a bip72 or 70 URI
String bip70 = PaymentProtocolHelper.getBip70(enteredAddress); final String bip70 = PaymentProtocolHelper.getBip70(enteredAddress);
if (bip70 != null) { if (bip70 != null) {
// looks good - resolve through xmr.to // looks good - resolve through xmr.to
processBip70(bip70); processBip70(bip70);
next = null;
} else if (checkAddress()) {
if (llPaymentId.getVisibility() == View.VISIBLE) {
next = etPaymentId;
} else {
next = etNotes;
}
} }
} }
if (next != null) {
final View focus = next;
etAddress.post(new Runnable() {
@Override
public void run() {
focus.requestFocus();
}
});
}
} }
} }
}); });
@@ -171,8 +153,7 @@ public class SendAddressWizardFragment extends SendWizardFragment {
etAddress.setError(null); etAddress.setError(null);
if (isIntegratedAddress()) { if (isIntegratedAddress()) {
Timber.d("isIntegratedAddress"); Timber.d("isIntegratedAddress");
etPaymentId.getEditText().getText().clear(); etAddress.setError(getString(R.string.info_paymentid_integrated));
llPaymentId.setVisibility(View.INVISIBLE);
tvPaymentIdIntegrated.setVisibility(View.VISIBLE); tvPaymentIdIntegrated.setVisibility(View.VISIBLE);
llXmrTo.setVisibility(View.INVISIBLE); llXmrTo.setVisibility(View.INVISIBLE);
sendListener.setMode(SendFragment.Mode.XMR); sendListener.setMode(SendFragment.Mode.XMR);
@@ -181,7 +162,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
setBtcMode(); setBtcMode();
} else { } else {
Timber.d("isStandardAddress or other"); Timber.d("isStandardAddress or other");
llPaymentId.setVisibility(View.VISIBLE);
tvPaymentIdIntegrated.setVisibility(View.INVISIBLE); tvPaymentIdIntegrated.setVisibility(View.INVISIBLE);
llXmrTo.setVisibility(View.INVISIBLE); llXmrTo.setVisibility(View.INVISIBLE);
sendListener.setMode(SendFragment.Mode.XMR); sendListener.setMode(SendFragment.Mode.XMR);
@@ -197,40 +177,29 @@ public class SendAddressWizardFragment extends SendWizardFragment {
} }
}); });
etPaymentId = view.findViewById(R.id.etPaymentId); bPasteAddress = view.findViewById(R.id.bPasteAddress);
etPaymentId.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); bPasteAddress.setOnClickListener(new View.OnClickListener() {
etPaymentId.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|| (actionId == EditorInfo.IME_ACTION_NEXT)) {
if (checkPaymentId()) {
etNotes.requestFocus();
}
return true;
}
return false;
}
});
etPaymentId.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
etPaymentId.setError(null);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
bPaymentId = view.findViewById(R.id.bPaymentId);
bPaymentId.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
etPaymentId.getEditText().setText((Wallet.generatePaymentId())); final String clip = Helper.getClipBoardText(getActivity());
if (clip == null) return;
// clean it up
final String address = clip.replaceAll("[^0-9A-Z-a-z]", "");
if (Wallet.isAddressValid(address) || BitcoinAddressValidator.validate(address)) {
final EditText et = etAddress.getEditText();
et.setText(address);
et.setSelection(et.getText().length());
etAddress.requestFocus();
} else {
final String bip70 = PaymentProtocolHelper.getBip70(clip);
if (bip70 != null) {
final EditText et = etAddress.getEditText();
et.setText(clip);
et.setSelection(et.getText().length());
processBip70(bip70);
} else
Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show();
}
} }
}); });
@@ -241,7 +210,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|| (actionId == EditorInfo.IME_ACTION_DONE)) { || (actionId == EditorInfo.IME_ACTION_DONE)) {
etDummy.requestFocus(); etDummy.requestFocus();
Helper.hideKeyboard(getActivity());
return true; return true;
} }
return false; return false;
@@ -259,7 +227,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
etDummy = view.findViewById(R.id.etDummy); etDummy = view.findViewById(R.id.etDummy);
etDummy.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); etDummy.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etDummy.requestFocus(); etDummy.requestFocus();
Helper.hideKeyboard(getActivity());
View tvNfc = view.findViewById(R.id.tvNfc); View tvNfc = view.findViewById(R.id.tvNfc);
NfcManager manager = (NfcManager) getContext().getSystemService(Context.NFC_SERVICE); NfcManager manager = (NfcManager) getContext().getSystemService(Context.NFC_SERVICE);
@@ -271,8 +238,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
private void setBtcMode() { private void setBtcMode() {
Timber.d("setBtcMode"); Timber.d("setBtcMode");
etPaymentId.getEditText().getText().clear();
llPaymentId.setVisibility(View.INVISIBLE);
tvPaymentIdIntegrated.setVisibility(View.INVISIBLE); tvPaymentIdIntegrated.setVisibility(View.INVISIBLE);
llXmrTo.setVisibility(View.VISIBLE); llXmrTo.setVisibility(View.VISIBLE);
sendListener.setMode(SendFragment.Mode.BTC); sendListener.setMode(SendFragment.Mode.BTC);
@@ -327,7 +292,7 @@ public class SendAddressWizardFragment extends SendWizardFragment {
final BarcodeData barcodeData = final BarcodeData barcodeData =
new BarcodeData(BarcodeData.Asset.BTC, address, null, new BarcodeData(BarcodeData.Asset.BTC, address, null,
resolvedBip70, null, null, String.valueOf(amount), resolvedBip70, null, String.valueOf(amount),
BarcodeData.Security.BIP70); BarcodeData.Security.BIP70);
etNotes.post(new Runnable() { etNotes.post(new Runnable() {
@Override @Override
@@ -388,22 +353,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
return BitcoinAddressValidator.validate(address); return BitcoinAddressValidator.validate(address);
} }
private boolean checkPaymentId() {
String paymentId = etPaymentId.getEditText().getText().toString();
boolean ok = paymentId.isEmpty() || Wallet.isPaymentIdValid(paymentId);
if (!ok) {
etPaymentId.setError(getString(R.string.receive_paymentid_invalid));
} else {
if (!paymentId.isEmpty() && isIntegratedAddress()) {
ok = false;
etPaymentId.setError(getString(R.string.receive_integrated_paymentid_invalid));
} else {
etPaymentId.setError(null);
}
}
return ok;
}
private void shakeAddress() { private void shakeAddress() {
etAddress.startAnimation(Helper.getShakeAnimation(getContext())); etAddress.startAnimation(Helper.getShakeAnimation(getContext()));
} }
@@ -426,11 +375,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
return false; return false;
} }
if (!checkPaymentId()) {
etPaymentId.startAnimation(Helper.getShakeAnimation(getContext()));
return false;
}
if (sendListener != null) { if (sendListener != null) {
TxData txData = sendListener.getTxData(); TxData txData = sendListener.getTxData();
if (txData instanceof TxDataBtc) { if (txData instanceof TxDataBtc) {
@@ -444,10 +388,8 @@ public class SendAddressWizardFragment extends SendWizardFragment {
((TxDataBtc) txData).setBip70(null); ((TxDataBtc) txData).setBip70(null);
} }
txData.setDestinationAddress(null); txData.setDestinationAddress(null);
txData.setPaymentId("");
} else { } else {
txData.setDestinationAddress(etAddress.getEditText().getText().toString()); txData.setDestinationAddress(etAddress.getEditText().getText().toString());
txData.setPaymentId(etPaymentId.getEditText().getText().toString());
} }
txData.setUserNotes(new UserNotes(etNotes.getEditText().getText().toString())); txData.setUserNotes(new UserNotes(etNotes.getEditText().getText().toString()));
txData.setPriority(PendingTransaction.Priority.Priority_Default); txData.setPriority(PendingTransaction.Priority.Priority_Default);
@@ -510,14 +452,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
etAddress.setError(null); etAddress.setError(null);
} }
String scannedPaymentId = barcodeData.paymentId;
if (scannedPaymentId != null) {
etPaymentId.getEditText().setText(scannedPaymentId);
checkPaymentId();
} else {
etPaymentId.getEditText().getText().clear();
etPaymentId.setError(null);
}
String scannedNotes = barcodeData.description; String scannedNotes = barcodeData.description;
if (scannedNotes != null) { if (scannedNotes != null) {
etNotes.getEditText().setText(scannedNotes); etNotes.getEditText().setText(scannedNotes);
@@ -533,7 +467,6 @@ public class SendAddressWizardFragment extends SendWizardFragment {
public void onResumeFragment() { public void onResumeFragment() {
super.onResumeFragment(); super.onResumeFragment();
Timber.d("onResumeFragment()"); Timber.d("onResumeFragment()");
Helper.hideKeyboard(getActivity());
etDummy.requestFocus(); etDummy.requestFocus();
} }

View File

@@ -21,8 +21,6 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.R;
@@ -30,8 +28,7 @@ import com.m2049r.xmrwallet.data.BarcodeData;
import com.m2049r.xmrwallet.data.TxData; 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.ExchangeEditText;
import com.m2049r.xmrwallet.widget.NumberPadView;
import timber.log.Timber; import timber.log.Timber;
@@ -59,8 +56,7 @@ public class SendAmountWizardFragment extends SendWizardFragment {
} }
private TextView tvFunds; private TextView tvFunds;
private ExchangeTextView evAmount; private ExchangeEditText etAmount;
private View llAmount;
private View rlSweep; private View rlSweep;
private ImageButton ibSweep; private ImageButton ibSweep;
@@ -75,12 +71,9 @@ public class SendAmountWizardFragment extends SendWizardFragment {
View view = inflater.inflate(R.layout.fragment_send_amount, container, false); View view = inflater.inflate(R.layout.fragment_send_amount, container, false);
tvFunds = view.findViewById(R.id.tvFunds); tvFunds = view.findViewById(R.id.tvFunds);
etAmount = view.findViewById(R.id.etAmount);
evAmount = view.findViewById(R.id.evAmount);
((NumberPadView) view.findViewById(R.id.numberPad)).setListener(evAmount);
rlSweep = view.findViewById(R.id.rlSweep); rlSweep = view.findViewById(R.id.rlSweep);
llAmount = view.findViewById(R.id.llAmount);
view.findViewById(R.id.ivSweep).setOnClickListener(new View.OnClickListener() { view.findViewById(R.id.ivSweep).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@@ -97,8 +90,7 @@ public class SendAmountWizardFragment extends SendWizardFragment {
} }
}); });
Helper.hideKeyboard(getActivity()); etAmount.requestFocus();
return view; return view;
} }
@@ -107,11 +99,11 @@ public class SendAmountWizardFragment extends SendWizardFragment {
private void sweepAll(boolean spendAllMode) { private void sweepAll(boolean spendAllMode) {
if (spendAllMode) { if (spendAllMode) {
ibSweep.setVisibility(View.INVISIBLE); ibSweep.setVisibility(View.INVISIBLE);
llAmount.setVisibility(View.GONE); etAmount.setVisibility(View.GONE);
rlSweep.setVisibility(View.VISIBLE); rlSweep.setVisibility(View.VISIBLE);
} else { } else {
ibSweep.setVisibility(View.VISIBLE); ibSweep.setVisibility(View.VISIBLE);
llAmount.setVisibility(View.VISIBLE); etAmount.setVisibility(View.VISIBLE);
rlSweep.setVisibility(View.GONE); rlSweep.setVisibility(View.GONE);
} }
this.spendAllMode = spendAllMode; this.spendAllMode = spendAllMode;
@@ -124,12 +116,12 @@ public class SendAmountWizardFragment extends SendWizardFragment {
sendListener.getTxData().setAmount(Wallet.SWEEP_ALL); sendListener.getTxData().setAmount(Wallet.SWEEP_ALL);
} }
} else { } else {
if (!evAmount.validate(maxFunds)) { if (!etAmount.validate(maxFunds, 0)) {
return false; return false;
} }
if (sendListener != null) { if (sendListener != null) {
String xmr = evAmount.getAmount(); String xmr = etAmount.getNativeAmount();
if (xmr != null) { if (xmr != null) {
sendListener.getTxData().setAmount(Wallet.getAmountFromString(xmr)); sendListener.getTxData().setAmount(Wallet.getAmountFromString(xmr));
} else { } else {
@@ -146,7 +138,7 @@ public class SendAmountWizardFragment extends SendWizardFragment {
public void onResumeFragment() { public void onResumeFragment() {
super.onResumeFragment(); super.onResumeFragment();
Timber.d("onResumeFragment()"); Timber.d("onResumeFragment()");
Helper.hideKeyboard(getActivity()); Helper.showKeyboard(getActivity());
final long funds = getTotalFunds(); final long funds = getTotalFunds();
maxFunds = 1.0 * funds / 1000000000000L; maxFunds = 1.0 * funds / 1000000000000L;
if (!sendListener.getActivityCallback().isStreetMode()) { if (!sendListener.getActivityCallback().isStreetMode()) {
@@ -156,11 +148,11 @@ public class SendAmountWizardFragment extends SendWizardFragment {
tvFunds.setText(getString(R.string.send_available, tvFunds.setText(getString(R.string.send_available,
getString(R.string.unknown_amount))); getString(R.string.unknown_amount)));
} }
// getAmount is null if exchange is in progress // getNativeAmount is null if exchange is in progress
if ((evAmount.getAmount() != null) && evAmount.getAmount().isEmpty()) { if ((etAmount.getNativeAmount() != null) && etAmount.getNativeAmount().isEmpty()) {
final BarcodeData data = sendListener.popBarcodeData(); final BarcodeData data = sendListener.popBarcodeData();
if ((data != null) && (data.amount != null)) { if ((data != null) && (data.amount != null)) {
evAmount.setAmount(data.amount); etAmount.setAmount(data.amount);
} }
} }
} }

View File

@@ -31,8 +31,8 @@ import com.m2049r.xmrwallet.data.TxDataBtc;
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.util.OkHttpHelper; import com.m2049r.xmrwallet.util.OkHttpHelper;
import com.m2049r.xmrwallet.widget.ExchangeBtcTextView; import com.m2049r.xmrwallet.widget.ExchangeEditText;
import com.m2049r.xmrwallet.widget.NumberPadView; import com.m2049r.xmrwallet.widget.ExchangeOtherEditText;
import com.m2049r.xmrwallet.widget.SendProgressView; import com.m2049r.xmrwallet.widget.SendProgressView;
import com.m2049r.xmrwallet.xmrto.XmrToError; import com.m2049r.xmrwallet.xmrto.XmrToError;
import com.m2049r.xmrwallet.xmrto.XmrToException; import com.m2049r.xmrwallet.xmrto.XmrToException;
@@ -62,8 +62,7 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
} }
private TextView tvFunds; private TextView tvFunds;
private ExchangeBtcTextView evAmount; private ExchangeOtherEditText etAmount;
private NumberPadView numberPad;
private TextView tvXmrToParms; private TextView tvXmrToParms;
private SendProgressView evParams; private SendProgressView evParams;
@@ -86,24 +85,20 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
tvXmrToParms = view.findViewById(R.id.tvXmrToParms); tvXmrToParms = view.findViewById(R.id.tvXmrToParms);
evAmount = view.findViewById(R.id.evAmount); etAmount = view.findViewById(R.id.etAmount);
numberPad = view.findViewById(R.id.numberPad); etAmount.requestFocus();
numberPad.setListener(evAmount);
Helper.hideKeyboard(getActivity());
return view; return view;
} }
@Override @Override
public boolean onValidateFields() { public boolean onValidateFields() {
if (!evAmount.validate(maxBtc, minBtc)) { if (!etAmount.validate(maxBtc, minBtc)) {
return false; return false;
} }
if (sendListener != null) { if (sendListener != null) {
TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData(); TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData();
String btcString = evAmount.getAmount(); String btcString = etAmount.getNativeAmount();
if (btcString != null) { if (btcString != null) {
try { try {
double btc = Double.parseDouble(btcString); double btc = Double.parseDouble(btcString);
@@ -122,10 +117,12 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
private void setBip70Mode() { private void setBip70Mode() {
TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData(); TxDataBtc txDataBtc = (TxDataBtc) sendListener.getTxData();
if (txDataBtc.getBip70() != null) { if (txDataBtc.getBip70() == null) {
numberPad.setVisibility(View.INVISIBLE); etAmount.setEditable(true);
Helper.showKeyboard(getActivity());
} else { } else {
numberPad.setVisibility(View.VISIBLE); etAmount.setEditable(false);
Helper.hideKeyboard(getActivity());
} }
} }
@@ -141,7 +138,6 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
public void onResumeFragment() { public void onResumeFragment() {
super.onResumeFragment(); super.onResumeFragment();
Timber.d("onResumeFragment()"); Timber.d("onResumeFragment()");
Helper.hideKeyboard(getActivity());
final long funds = getTotalFunds(); final long funds = getTotalFunds();
if (!sendListener.getActivityCallback().isStreetMode()) { if (!sendListener.getActivityCallback().isStreetMode()) {
tvFunds.setText(getString(R.string.send_available, tvFunds.setText(getString(R.string.send_available,
@@ -153,7 +149,7 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
final BarcodeData data = sendListener.popBarcodeData(); final BarcodeData data = sendListener.popBarcodeData();
if (data != null) { if (data != null) {
if (data.amount != null) { if (data.amount != null) {
evAmount.setAmount(data.amount); etAmount.setAmount(data.amount);
} }
} }
setBip70Mode(); setBip70Mode();
@@ -171,7 +167,7 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
getView().post(new Runnable() { getView().post(new Runnable() {
@Override @Override
public void run() { public void run() {
evAmount.setRate(1.0d / orderParameters.getPrice()); etAmount.setExchangeRate(1.0d / orderParameters.getPrice());
NumberFormat df = NumberFormat.getInstance(Locale.US); NumberFormat df = NumberFormat.getInstance(Locale.US);
df.setMaximumFractionDigits(6); df.setMaximumFractionDigits(6);
String min = df.format(orderParameters.getLowerLimit()); String min = df.format(orderParameters.getLowerLimit());
@@ -211,7 +207,7 @@ public class SendBtcAmountWizardFragment extends SendWizardFragment {
} }
private void processOrderParmsError(final Exception ex) { private void processOrderParmsError(final Exception ex) {
evAmount.setRate(0); etAmount.setExchangeRate(0);
orderParameters = null; orderParameters = null;
maxBtc = 0; maxBtc = 0;
minBtc = 0; minBtc = 0;

View File

@@ -346,103 +346,16 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements
} }
public void preSend() { public void preSend() {
final Activity activity = getActivity(); Helper.promptPassword(getContext(), getActivityCallback().getWalletName(), false, new Helper.PasswordAction() {
View promptsView = getLayoutInflater().inflate(R.layout.prompt_password, null);
android.app.AlertDialog.Builder alertDialogBuilder = new android.app.AlertDialog.Builder(activity);
alertDialogBuilder.setView(promptsView);
final TextInputLayout etPassword = promptsView.findViewById(R.id.etPassword);
etPassword.setHint(getString(R.string.prompt_send_password));
etPassword.getEditText().addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void act(String walletName, String password, boolean fingerprintUsed) {
if (etPassword.getError() != null) { send();
etPassword.setError(null);
}
} }
@Override public void fail(String walletName, String password, boolean fingerprintUsed) {
public void beforeTextChanged(CharSequence s, int start, bSend.setEnabled(sendCountdown > 0); // allow to try again
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
} }
}); });
alertDialogBuilder
.setCancelable(false)
.setPositiveButton(getString(R.string.label_ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String pass = etPassword.getEditText().getText().toString();
if (getActivityCallback().verifyWalletPassword(pass)) {
dialog.dismiss();
Helper.hideKeyboardAlways(activity);
send();
} else {
etPassword.setError(getString(R.string.bad_password));
}
}
})
.setNegativeButton(getString(R.string.label_cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Helper.hideKeyboardAlways(activity);
dialog.cancel();
bSend.setEnabled(sendCountdown > 0); // allow to try again
}
});
final android.app.AlertDialog passwordDialog = alertDialogBuilder.create();
passwordDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
Button button = ((android.app.AlertDialog) dialog).getButton(android.app.AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String pass = etPassword.getEditText().getText().toString();
if (getActivityCallback().verifyWalletPassword(pass)) {
Helper.hideKeyboardAlways(activity);
passwordDialog.dismiss();
send();
} else {
etPassword.setError(getString(R.string.bad_password));
}
}
});
}
});
Helper.showKeyboard(passwordDialog);
// accept keyboard "ok"
etPassword.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|| (actionId == EditorInfo.IME_ACTION_DONE)) {
String pass = etPassword.getEditText().getText().toString();
if (getActivityCallback().verifyWalletPassword(pass)) {
Helper.hideKeyboardAlways(activity);
passwordDialog.dismiss();
send();
} else {
etPassword.setError(getString(R.string.bad_password));
}
return true;
}
return false;
}
});
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
passwordDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
passwordDialog.show();
} }
// creates a pending transaction and calls us back with transactionCreated() // creates a pending transaction and calls us back with transactionCreated()
@@ -457,9 +370,8 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements
} }
showProgress(3, getString(R.string.label_send_progress_create_tx)); showProgress(3, getString(R.string.label_send_progress_create_tx));
TxData txData = sendListener.getTxData(); TxData txData = sendListener.getTxData();
txData.setDestinationAddress(xmrtoStatus.getXmrReceivingAddress()); txData.setDestinationAddress(xmrtoStatus.getReceivingSubaddress());
txData.setPaymentId(xmrtoStatus.getXmrRequiredPaymentIdShort()); txData.setAmount(Wallet.getAmountFromDouble(xmrtoStatus.getIncomingAmountTotal()));
txData.setAmount(Wallet.getAmountFromDouble(xmrtoStatus.getXmrAmountTotal()));
getActivityCallback().onPrepareSend(xmrtoStatus.getUuid(), txData); getActivityCallback().onPrepareSend(xmrtoStatus.getUuid(), txData);
} }
@@ -573,22 +485,22 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements
NumberFormat df = NumberFormat.getInstance(Locale.US); NumberFormat df = NumberFormat.getInstance(Locale.US);
df.setMaximumFractionDigits(12); df.setMaximumFractionDigits(12);
String btcAmount = df.format(status.getBtcAmount()); String btcAmount = df.format(status.getBtcAmount());
String xmrAmountTotal = df.format(status.getXmrAmountTotal()); String xmrAmountTotal = df.format(status.getIncomingAmountTotal());
tvTxBtcAmount.setText(getString(R.string.text_send_btc_amount, btcAmount, xmrAmountTotal)); tvTxBtcAmount.setText(getString(R.string.text_send_btc_amount, btcAmount, xmrAmountTotal));
String xmrPriceBtc = df.format(status.getXmrPriceBtc()); String xmrPriceBtc = df.format(status.getIncomingPriceBtc());
tvTxBtcRate.setText(getString(R.string.text_send_btc_rate, xmrPriceBtc)); tvTxBtcRate.setText(getString(R.string.text_send_btc_rate, xmrPriceBtc));
double calcRate = status.getBtcAmount() / status.getXmrPriceBtc(); double calcRate = status.getBtcAmount() / status.getIncomingPriceBtc();
Timber.i("Rates: %f / %f", calcRate, status.getXmrPriceBtc()); Timber.d("Rates: %f / %f", calcRate, status.getIncomingPriceBtc());
tvTxBtcAddress.setText(status.getBtcDestAddress()); // TODO test if this is different? tvTxBtcAddress.setText(status.getBtcDestAddress()); // TODO test if this is different?
Timber.i("Expires @ %s, in %s seconds", status.getExpiresAt().toString(), status.getSecondsTillTimeout()); Timber.d("Expires @ %s, in %s seconds", status.getExpiresAt().toString(), status.getSecondsTillTimeout());
Timber.i("Status = %s", status.getState().toString()); Timber.d("Status = %s", status.getState().toString());
tvTxXmrToKey.setText(status.getUuid()); tvTxXmrToKey.setText(status.getUuid());
Timber.d("AmountRemaining=%f, XmrAmountTotal=%f", status.getXmrAmountRemaining(), status.getXmrAmountTotal()); Timber.d("AmountRemaining=%f, XmrAmountTotal=%f", status.getRemainingAmountIncoming(), status.getIncomingAmountTotal());
hideProgress(); hideProgress();
startSendTimer(); startSendTimer();
prepareSend(); prepareSend();

View File

@@ -138,12 +138,6 @@ public class SendBtcSuccessWizardFragment extends SendWizardFragment {
btcData = (TxDataBtc) sendListener.getTxData(); btcData = (TxDataBtc) sendListener.getTxData();
tvTxAddress.setText(btcData.getDestinationAddress()); tvTxAddress.setText(btcData.getDestinationAddress());
String paymentId = btcData.getPaymentId();
if ((paymentId != null) && (!paymentId.isEmpty())) {
tvTxPaymentId.setText(btcData.getPaymentId());
} else {
tvTxPaymentId.setText("-");
}
final PendingTx committedTx = sendListener.getCommittedTx(); final PendingTx committedTx = sendListener.getCommittedTx();
if (committedTx != null) { if (committedTx != null) {

View File

@@ -70,7 +70,6 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
} }
private TextView tvTxAddress; private TextView tvTxAddress;
private TextView tvTxPaymentId;
private TextView tvTxNotes; private TextView tvTxNotes;
private TextView tvTxAmount; private TextView tvTxAmount;
private TextView tvTxFee; private TextView tvTxFee;
@@ -90,7 +89,6 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
R.layout.fragment_send_confirm, container, false); R.layout.fragment_send_confirm, container, false);
tvTxAddress = view.findViewById(R.id.tvTxAddress); tvTxAddress = view.findViewById(R.id.tvTxAddress);
tvTxPaymentId = view.findViewById(R.id.tvTxPaymentId);
tvTxNotes = view.findViewById(R.id.tvTxNotes); tvTxNotes = view.findViewById(R.id.tvTxNotes);
tvTxAmount = view.findViewById(R.id.tvTxAmount); tvTxAmount = view.findViewById(R.id.tvTxAmount);
tvTxFee = view.findViewById(R.id.tvTxFee); tvTxFee = view.findViewById(R.id.tvTxFee);
@@ -143,7 +141,12 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
void send() { void send() {
sendListener.commitTransaction(); sendListener.commitTransaction();
pbProgressSend.setVisibility(View.VISIBLE); getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
pbProgressSend.setVisibility(View.VISIBLE);
}
});
} }
@Override @Override
@@ -192,12 +195,6 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
final TxData txData = sendListener.getTxData(); final TxData txData = sendListener.getTxData();
tvTxAddress.setText(txData.getDestinationAddress()); tvTxAddress.setText(txData.getDestinationAddress());
String paymentId = txData.getPaymentId();
if ((paymentId != null) && (!paymentId.isEmpty())) {
tvTxPaymentId.setText(txData.getPaymentId());
} else {
tvTxPaymentId.setText("-");
}
UserNotes notes = sendListener.getTxData().getUserNotes(); UserNotes notes = sendListener.getTxData().getUserNotes();
if ((notes != null) && (!notes.note.isEmpty())) { if ((notes != null) && (!notes.note.isEmpty())) {
tvTxNotes.setText(notes.note); tvTxNotes.setText(notes.note);
@@ -233,103 +230,16 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
} }
public void preSend() { public void preSend() {
final Activity activity = getActivity(); Helper.promptPassword(getContext(), getActivityCallback().getWalletName(), false, new Helper.PasswordAction() {
View promptsView = getLayoutInflater().inflate(R.layout.prompt_password, null);
android.app.AlertDialog.Builder alertDialogBuilder = new android.app.AlertDialog.Builder(activity);
alertDialogBuilder.setView(promptsView);
final TextInputLayout etPassword = promptsView.findViewById(R.id.etPassword);
etPassword.setHint(getString(R.string.prompt_send_password));
etPassword.getEditText().addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void act(String walletName, String password, boolean fingerprintUsed) {
if (etPassword.getError() != null) { send();
etPassword.setError(null);
}
} }
@Override public void fail(String walletName, String password, boolean fingerprintUsed) {
public void beforeTextChanged(CharSequence s, int start, bSend.setEnabled(true); // allow to try again
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
} }
}); });
alertDialogBuilder
.setCancelable(false)
.setPositiveButton(getString(R.string.label_ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String pass = etPassword.getEditText().getText().toString();
if (getActivityCallback().verifyWalletPassword(pass)) {
dialog.dismiss();
Helper.hideKeyboardAlways(activity);
send();
} else {
etPassword.setError(getString(R.string.bad_password));
}
}
})
.setNegativeButton(getString(R.string.label_cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Helper.hideKeyboardAlways(activity);
dialog.cancel();
bSend.setEnabled(true); // allow to try again
}
});
final android.app.AlertDialog passwordDialog = alertDialogBuilder.create();
passwordDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
Button button = ((android.app.AlertDialog) dialog).getButton(android.app.AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String pass = etPassword.getEditText().getText().toString();
if (getActivityCallback().verifyWalletPassword(pass)) {
Helper.hideKeyboardAlways(activity);
passwordDialog.dismiss();
send();
} else {
etPassword.setError(getString(R.string.bad_password));
}
}
});
}
});
Helper.showKeyboard(passwordDialog);
// accept keyboard "ok"
etPassword.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|| (actionId == EditorInfo.IME_ACTION_DONE)) {
String pass = etPassword.getEditText().getText().toString();
if (getActivityCallback().verifyWalletPassword(pass)) {
Helper.hideKeyboardAlways(activity);
passwordDialog.dismiss();
send();
} else {
etPassword.setError(getString(R.string.bad_password));
}
return true;
}
return false;
}
});
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
passwordDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
passwordDialog.show();
} }
// creates a pending transaction and calls us back with transactionCreated() // creates a pending transaction and calls us back with transactionCreated()

View File

@@ -75,7 +75,7 @@ public class SendFragment extends Fragment
void onPrepareSend(String tag, TxData data); void onPrepareSend(String tag, TxData data);
boolean verifyWalletPassword(String password); String getWalletName();
void onSend(UserNotes notes); void onSend(UserNotes notes);

View File

@@ -111,12 +111,6 @@ public class SendSuccessWizardFragment extends SendWizardFragment {
final TxData txData = sendListener.getTxData(); final TxData txData = sendListener.getTxData();
tvTxAddress.setText(txData.getDestinationAddress()); tvTxAddress.setText(txData.getDestinationAddress());
String paymentId = txData.getPaymentId();
if ((paymentId != null) && (!paymentId.isEmpty())) {
tvTxPaymentId.setText(txData.getPaymentId());
} else {
tvTxPaymentId.setText("-");
}
final PendingTx committedTx = sendListener.getCommittedTx(); final PendingTx committedTx = sendListener.getCommittedTx();
if (committedTx != null) { if (committedTx != null) {

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