From d4ca731332764e388355166296c5853a54ebf615 Mon Sep 17 00:00:00 2001 From: striderDM <51991544+StriderDM@users.noreply.github.com> Date: Thu, 2 Sep 2021 23:27:42 +0200 Subject: [PATCH 1/2] feat: added wrapper classes for TariTransactionKernel Update libwallet version Update jniWallet.cpp to latest interface Update FFIWallet.kt to reflect changes in jniWallet.cpp --- app/src/main/cpp/CMakeLists.txt | 1 + app/src/main/cpp/jniCompletedTransaction.cpp | 20 ++++ .../cpp/jniCompletedTransactionKernel.cpp | 102 ++++++++++++++++++ app/src/main/cpp/jniWallet.cpp | 17 +++ .../tari/android/wallet/ffi/FFICompletedTx.kt | 11 +- .../wallet/ffi/FFICompletedTxKernel.kt | 77 +++++++++++++ .../com/tari/android/wallet/ffi/FFIWallet.kt | 42 ++++---- build.gradle | 2 +- 8 files changed, 246 insertions(+), 26 deletions(-) create mode 100644 app/src/main/cpp/jniCompletedTransactionKernel.cpp create mode 100644 app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTxKernel.kt diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index eb5133544..a7a35cf71 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -65,6 +65,7 @@ add_library( jniContact.cpp jniCommsConfig.cpp jniCompletedTransaction.cpp + jniCompletedTransactionKernel.cpp jniPendingInboundTransaction.cpp jniPendingOutboundTransaction.cpp jniCollections.cpp diff --git a/app/src/main/cpp/jniCompletedTransaction.cpp b/app/src/main/cpp/jniCompletedTransaction.cpp index 5db3cefe5..67cb72331 100644 --- a/app/src/main/cpp/jniCompletedTransaction.cpp +++ b/app/src/main/cpp/jniCompletedTransaction.cpp @@ -92,6 +92,26 @@ Java_com_tari_android_wallet_ffi_FFICompletedTx_jniGetSourcePublicKey( return result; } +extern "C" +JNIEXPORT jlong JNICALL +Java_com_tari_android_wallet_ffi_FFICompletedTx_jniGetTransactionKernel( + JNIEnv *jEnv, + jobject jThis, + jobject error) { + int i = 0; + int *r = &i; + jlong lCompletedTx = GetPointerField(jEnv, jThis); + auto *pCompletedTx = reinterpret_cast(lCompletedTx); + auto result = reinterpret_cast( + completed_transaction_get_transaction_kernel( + pCompletedTx, + r + ) + ); + setErrorCode(jEnv, error, i); + return result; +} + extern "C" JNIEXPORT jbyteArray JNICALL Java_com_tari_android_wallet_ffi_FFICompletedTx_jniGetAmount( diff --git a/app/src/main/cpp/jniCompletedTransactionKernel.cpp b/app/src/main/cpp/jniCompletedTransactionKernel.cpp new file mode 100644 index 000000000..a7fdb478d --- /dev/null +++ b/app/src/main/cpp/jniCompletedTransactionKernel.cpp @@ -0,0 +1,102 @@ +/** + * Copyright 2020 The Tari Project + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include "jniCommon.cpp" + +extern "C" +JNIEXPORT jstring JNICALL +Java_com_tari_android_wallet_ffi_FFICompletedTxKernel_jniGetExcess( + JNIEnv *jEnv, + jobject jThis, + jobject error) { + int i = 0; + int *r = &i; + jlong lKernel = GetPointerField(jEnv, jThis); + auto *pKernel = reinterpret_cast(lKernel); + const char *pStr = transaction_kernel_get_excess_hex(pKernel, r); + setErrorCode(jEnv, error, i); + jstring result = jEnv->NewStringUTF(pStr); + string_destroy(const_cast(pStr)); + return result; +} + +extern "C" +JNIEXPORT jstring JNICALL +Java_com_tari_android_wallet_ffi_FFICompletedTxKernel_jniGetExcessPublicNonce( + JNIEnv *jEnv, + jobject jThis, + jobject error) { + int i = 0; + int *r = &i; + jlong lKernel = GetPointerField(jEnv, jThis); + auto *pKernel = reinterpret_cast(lKernel); + const char *pStr = transaction_kernel_get_excess_public_nonce_hex(pKernel, r); + setErrorCode(jEnv, error, i); + jstring result = jEnv->NewStringUTF(pStr); + string_destroy(const_cast(pStr)); + return result; +} + +extern "C" +JNIEXPORT jstring JNICALL +Java_com_tari_android_wallet_ffi_FFICompletedTxKernel_jniGetExcessSignature( + JNIEnv *jEnv, + jobject jThis, + jobject error) { + int i = 0; + int *r = &i; + jlong lKernel = GetPointerField(jEnv, jThis); + auto *pKernel = reinterpret_cast(lKernel); + const char *pStr = transaction_kernel_get_excess_signature_hex(pKernel, r); + setErrorCode(jEnv, error, i); + jstring result = jEnv->NewStringUTF(pStr); + string_destroy(const_cast(pStr)); + return result; +} + +extern "C" +JNIEXPORT void JNICALL +Java_com_tari_android_wallet_ffi_FFICompletedTxKernel_jniDestroy( + JNIEnv *jEnv, + jobject jThis) { + jlong lKernel = GetPointerField(jEnv, jThis); + auto *pKernel = reinterpret_cast(lKernel); + transaction_kernel_destroy(pKernel); + SetPointerField(jEnv, jThis, reinterpret_cast(nullptr)); +} \ No newline at end of file diff --git a/app/src/main/cpp/jniWallet.cpp b/app/src/main/cpp/jniWallet.cpp index f4af7600c..22f09e4dc 100644 --- a/app/src/main/cpp/jniWallet.cpp +++ b/app/src/main/cpp/jniWallet.cpp @@ -465,6 +465,9 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniCreate( pPassphrase = jEnv->GetStringUTFChars(jPassphrase, JNI_FALSE); } + bool recoveryInProgress = false; + bool *recovery = &recoveryInProgress; + TariWallet *pWallet; if (strlen(pLogPath) == 0) { pWallet = wallet_create( @@ -488,6 +491,7 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniCreate( invalidTxoValidationCompleteCallback, transactionValidationCompleteCallback, storeAndForwardMessagesReceivedCallback, + recovery, r); } else { pWallet = wallet_create( @@ -511,6 +515,7 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniCreate( invalidTxoValidationCompleteCallback, transactionValidationCompleteCallback, storeAndForwardMessagesReceivedCallback, + recovery, r); } setErrorCode(jEnv, error, i); @@ -1249,6 +1254,7 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniSetConfirmations( } //region Wallet Test Functions +/* extern "C" JNIEXPORT jboolean JNICALL Java_com_tari_android_wallet_ffi_FFIWallet_jniGenerateTestData( @@ -1269,7 +1275,9 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniGenerateTestData( jEnv->ReleaseStringUTFChars(jDatastorePath, pDatastorePath); return result; } +*/ +/* extern "C" JNIEXPORT jboolean JNICALL Java_com_tari_android_wallet_ffi_FFIWallet_jniTestBroadcastTx( @@ -1289,7 +1297,9 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniTestBroadcastTx( setErrorCode(jEnv, error, i); return result; } +*/ +/* extern "C" JNIEXPORT jboolean JNICALL Java_com_tari_android_wallet_ffi_FFIWallet_jniTestFinalizeReceivedTx( @@ -1309,7 +1319,9 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniTestFinalizeReceivedTx( setErrorCode(jEnv, error, i); return result; } +*/ +/* extern "C" JNIEXPORT jboolean JNICALL Java_com_tari_android_wallet_ffi_FFIWallet_jniTestCompleteSentTx( @@ -1328,7 +1340,9 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniTestCompleteSentTx( setErrorCode(jEnv, error, i); return result; } +*/ +/* extern "C" JNIEXPORT jboolean JNICALL Java_com_tari_android_wallet_ffi_FFIWallet_jniTestMineTx( @@ -1348,7 +1362,9 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniTestMineTx( setErrorCode(jEnv, error, i); return result; } +*/ +/* extern "C" JNIEXPORT jboolean JNICALL Java_com_tari_android_wallet_ffi_FFIWallet_jniTestReceiveTx( @@ -1363,6 +1379,7 @@ Java_com_tari_android_wallet_ffi_FFIWallet_jniTestReceiveTx( setErrorCode(jEnv, error, i); return result; } +*/ extern "C" JNIEXPORT jbyteArray JNICALL diff --git a/app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTx.kt b/app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTx.kt index 672f11911..6df76e4ba 100644 --- a/app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTx.kt +++ b/app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTx.kt @@ -47,7 +47,9 @@ internal class FFICompletedTx() : FFIBase() { private external fun jniGetDestinationPublicKey( libError: FFIError ): FFIPointer - + private external fun jniGetTransactionKernel( + libError: FFIError + ): FFIPointer private external fun jniGetSourcePublicKey( libError: FFIError ): FFIPointer @@ -143,6 +145,13 @@ internal class FFICompletedTx() : FFIBase() { return result } + fun getTransactionKernel(): FFICompletedTxKernel { + val error = FFIError() + val result = FFICompletedTxKernel(jniGetTransactionKernel(error)) + throwIf(error) + return result + } + override fun destroy() { jniDestroy() } diff --git a/app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTxKernel.kt b/app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTxKernel.kt new file mode 100644 index 000000000..24c23ea9b --- /dev/null +++ b/app/src/main/java/com/tari/android/wallet/ffi/FFICompletedTxKernel.kt @@ -0,0 +1,77 @@ +/** + * Copyright 2020 The Tari Project + * + * 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. + */ +package com.tari.android.wallet.ffi + +/** + * Wrapper for native TariTransactionKernel type. + * + * @author The Tari Development Team + */ +internal class FFICompletedTxKernel() : FFIBase() { + + private external fun jniGetExcess(libError: FFIError): String + private external fun jniGetExcessPublicNonce(libError: FFIError): String + private external fun jniGetExcessSignature(libError: FFIError): String + private external fun jniDestroy() + + // endregion + constructor(pointer: FFIPointer): this() { + this.pointer = pointer + } + + fun getExcess(): String { + val error = FFIError() + val result = jniGetExcess(error) + throwIf(error) + return result + } + + fun getExcessPublicNonce(): String { + val error = FFIError() + val result = jniGetExcessPublicNonce(error) + throwIf(error) + return result + } + + fun getExcessSignature(): String { + val error = FFIError() + val result = jniGetExcessSignature(error) + throwIf(error) + return result + } + + override fun destroy() { + jniDestroy() + } + +} diff --git a/app/src/main/java/com/tari/android/wallet/ffi/FFIWallet.kt b/app/src/main/java/com/tari/android/wallet/ffi/FFIWallet.kt index 5021eb8c2..9a2ec141b 100644 --- a/app/src/main/java/com/tari/android/wallet/ffi/FFIWallet.kt +++ b/app/src/main/java/com/tari/android/wallet/ffi/FFIWallet.kt @@ -278,32 +278,44 @@ internal class FFIWallet( libError: FFIError ): ByteArray + /* private external fun jniGenerateTestData( datastorePath: String, libError: FFIError ): Boolean + */ + /* private external fun jniTestBroadcastTx( txPtr: String, libError: FFIError ): Boolean + */ + /* private external fun jniTestFinalizeReceivedTx( txPtr: FFIPendingInboundTx, libError: FFIError ): Boolean + */ + /* private external fun jniTestCompleteSentTx( txPtr: FFIPendingOutboundTx, libError: FFIError ): Boolean + */ + /* private external fun jniTestMineTx( txId: String, libError: FFIError ): Boolean + */ + /* private external fun jniTestReceiveTx(libError: FFIError): Boolean + */ private external fun jniApplyEncryption(passphrase: String, libError: FFIError) @@ -947,38 +959,23 @@ internal class FFIWallet( } fun generateTestData(datastorePath: String): Boolean { - val error = FFIError() - val result = jniGenerateTestData(datastorePath, error) - throwIf(error) - return result + return false } fun testBroadcastTx(tx: BigInteger): Boolean { - val error = FFIError() - val result = jniTestBroadcastTx(tx.toString(), error) - throwIf(error) - return result + return false } fun testCompleteSentTx(tx: FFIPendingOutboundTx): Boolean { - val error = FFIError() - val result = jniTestCompleteSentTx(tx, error) - throwIf(error) - return result + return false } fun testMineTx(tx: BigInteger): Boolean { - val error = FFIError() - val result = jniTestMineTx(tx.toString(), error) - throwIf(error) - return result + return false } fun testFinalizeReceivedTx(tx: FFIPendingInboundTx): Boolean { - val error = FFIError() - val result = jniTestFinalizeReceivedTx(tx, error) - throwIf(error) - return result + return false } fun setEncryption(passphrase: String) { @@ -996,10 +993,7 @@ internal class FFIWallet( } fun testReceiveTx(): Boolean { - val error = FFIError() - val result = jniTestReceiveTx(error) - throwIf(error) - return result + return false } override fun destroy() { diff --git a/build.gradle b/build.gradle index a61d884f9..dd02f2103 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { ext.versionNumber = "0.6.4" // JNI libs - ext.libwalletVersion = "0.17.3_network" + ext.libwalletVersion = "0.17.6" ext.libwalletHostURL = "https://tari-binaries.s3.amazonaws.com/libwallet/" ext.supportedABIs = ["arm64-v8a", "armeabi-v7a", "x86_64"] From 3c4d7d924995fa2a964958f6ef111a6ff8075e5b Mon Sep 17 00:00:00 2001 From: Aleksandr Vakhtin Date: Tue, 7 Sep 2021 09:33:50 +0300 Subject: [PATCH 2/2] Crash fixes Signed-off-by: Aleksandr Vakhtin --- app/build.gradle | 12 ++--- app/src/main/AndroidManifest.xml | 5 ++- .../application/TariWalletApplication.kt | 3 +- .../data/sharedPrefs/SharedPrefsRepository.kt | 1 + .../com/tari/android/wallet/ffi/FFIWallet.kt | 1 + .../android/wallet/service/WalletService.kt | 7 ++- .../android/wallet/tor/TorProxyManager.kt | 7 ++- .../wallet/ui/dialog/error/ErrorDialog.kt | 6 +-- .../inputSeedWords/InputSeedWordsViewModel.kt | 20 +++------ .../WalletRestoringFromSeedWordsFragment.kt | 4 +- .../WalletRestoringFromSeedWordsViewModel.kt | 44 ++++++++++++++----- build.gradle | 4 +- 12 files changed, 72 insertions(+), 42 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8804489cf..31b601420 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,13 +10,13 @@ apply from: "../download-libwallet.gradle" apply plugin: 'io.sentry.android.gradle' android { - compileSdkVersion 30 - buildToolsVersion "30.0.2" + compileSdkVersion 31 + buildToolsVersion "30.0.3" defaultConfig { applicationId "com.tari.android.wallet" minSdkVersion 24 - targetSdkVersion 30 + targetSdkVersion 31 versionCode buildNumber versionName versionNumber + "-libwallet-" + libwalletVersion testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -165,10 +165,10 @@ dependencies { // kotlin extensions implementation 'androidx.core:core-ktx:1.6.0' // android - implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'androidx.appcompat:appcompat:1.3.1' // support lib implementation 'androidx.legacy:legacy-support-v13:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.constraintlayout:constraintlayout:2.1.0' // android jetpack implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" // recycler view @@ -238,7 +238,7 @@ dependencies { implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0' // Google services & Google drive - regularImplementation 'com.google.android.gms:play-services-auth:19.0.0' + regularImplementation 'com.google.android.gms:play-services-auth:19.2.0' regularImplementation 'com.google.http-client:google-http-client-gson:1.39.0' regularImplementation('com.google.api-client:google-api-client-android:1.31.3') { exclude group: 'org.apache.httpcomponents' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d5d904f17..8100053e6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -30,7 +30,8 @@ + android:enabled="true" + android:exported="false"> @@ -51,6 +52,7 @@ @@ -76,6 +78,7 @@ startService() stopAction -> stopService(startId) @@ -208,16 +209,20 @@ internal class WalletService : Service(), FFIWalletListener, LifecycleObserver { return START_NOT_STICKY } + private fun startService() { // start wallet manager on a separate thead & listen to events EventBus.walletState.subscribe(this, this::onWalletStateChanged) Thread { walletManager.start() }.start() + Logger.d("Wallet service started.") + } + + private fun startForeground() { // start service & post foreground service notification val notification = notificationHelper.buildForegroundServiceNotification() startForeground(NOTIFICATION_ID, notification) - Logger.d("Wallet service started.") } private fun stopService(startId: Int) { diff --git a/app/src/main/java/com/tari/android/wallet/tor/TorProxyManager.kt b/app/src/main/java/com/tari/android/wallet/tor/TorProxyManager.kt index 30a2ad5d7..173dbf4ab 100644 --- a/app/src/main/java/com/tari/android/wallet/tor/TorProxyManager.kt +++ b/app/src/main/java/com/tari/android/wallet/tor/TorProxyManager.kt @@ -35,8 +35,8 @@ package com.tari.android.wallet.tor import android.app.Service import android.content.Context import com.orhanobut.logger.Logger -import com.tari.android.wallet.event.EventBus import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository +import com.tari.android.wallet.event.EventBus import io.reactivex.Observable import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers @@ -155,6 +155,7 @@ internal class TorProxyManager( * Check Tor status every 5 seconds. */ private val statusCheckPeriodSecs = 5L + /** * Timer to check Tor status. */ @@ -172,7 +173,9 @@ internal class TorProxyManager( @Synchronized fun shutdownTor() { timerSubscription?.dispose() - controlConnection.shutdownTor("SHUTDOWN") + if (this::controlConnection.isInitialized) { + controlConnection.shutdownTor("SHUTDOWN") + } } private fun connectToTor() { diff --git a/app/src/main/java/com/tari/android/wallet/ui/dialog/error/ErrorDialog.kt b/app/src/main/java/com/tari/android/wallet/ui/dialog/error/ErrorDialog.kt index 731f47e31..046ccf6f5 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/dialog/error/ErrorDialog.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/dialog/error/ErrorDialog.kt @@ -40,10 +40,8 @@ class ErrorDialog constructor(context: Context, errorDialogArgs: ErrorDialogArgs setCanceledOnTouchOutside(canceledOnTouchOutside) ui.errorDialogTitleTextView.text = title ui.errorDialogDescriptionTextView.text = description - ui.errorDialogCloseView.setOnClickListener { - onClose() - dismiss() - } + ui.errorDialogCloseView.setOnClickListener { dismiss() } + setOnDismissListener { onClose() } } } } diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsViewModel.kt index 21a901e12..f7fbcf038 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsViewModel.kt @@ -3,7 +3,6 @@ package com.tari.android.wallet.ui.fragment.restore.inputSeedWords import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Transformations -import androidx.lifecycle.viewModelScope import com.tari.android.wallet.R import com.tari.android.wallet.application.WalletState import com.tari.android.wallet.event.EventBus @@ -16,9 +15,6 @@ import com.tari.android.wallet.ui.common.SingleLiveEvent import com.tari.android.wallet.ui.common.domain.ResourceManager import com.tari.android.wallet.ui.dialog.error.ErrorDialogArgs import io.reactivex.disposables.CompositeDisposable -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch import javax.inject.Inject internal class InputSeedWordsViewModel() : CommonViewModel() { @@ -55,6 +51,7 @@ internal class InputSeedWordsViewModel() : CommonViewModel() { component?.inject(this) _words.value = mutableListOf() _focusedIndex.value = 0 + clear() } fun startRestoringWallet() { @@ -71,9 +68,12 @@ internal class InputSeedWordsViewModel() : CommonViewModel() { } private fun startRestoring() { - EventBus.walletState.publishSubject.subscribe { + EventBus.walletState.publishSubject.distinct().subscribe { when (it) { - is WalletState.Failed -> onError(RestorationError.Unknown(resourceManager)) + is WalletState.Failed -> { + onError(RestorationError.Unknown(resourceManager)) + clear() + } WalletState.Running -> _navigation.postValue(InputSeedWordsNavigation.ToRestoreFormSeedWordsInProgress) else -> Unit } @@ -93,11 +93,7 @@ internal class InputSeedWordsViewModel() : CommonViewModel() { onError(errorDialogArgs) } - private fun onError(restorationError: RestorationError) { - walletServiceLauncher.stopAndDelete() - clear() - _errorDialog.postValue(restorationError.args) - } + private fun onError(restorationError: RestorationError) = _errorDialog.postValue(restorationError.args) private fun clear() { walletServiceLauncher.stopAndDelete() @@ -105,7 +101,6 @@ internal class InputSeedWordsViewModel() : CommonViewModel() { compositeDisposable = CompositeDisposable() } - fun addWord(index: Int, text: String = "") { val newWord = WordItemViewModel.create(text) _words.value?.add(index, newWord) @@ -194,7 +189,6 @@ internal class InputSeedWordsViewModel() : CommonViewModel() { } } - sealed class RestorationError(title: String, message: String) { val args = ErrorDialogArgs(title, message) diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsFragment.kt index 0a969b75e..b6e57bd9e 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsFragment.kt @@ -36,7 +36,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.fragment.app.activityViewModels +import androidx.fragment.app.viewModels import com.tari.android.wallet.databinding.FragmentWalletRestoringFromSeedWordsBinding import com.tari.android.wallet.extension.observe import com.tari.android.wallet.ui.activity.restore.WalletRestoreRouter @@ -55,7 +55,7 @@ internal class WalletRestoringFromSeedWordsFragment : super.onViewCreated(view, savedInstanceState) changeOnBackPressed(true) - val viewModel: WalletRestoringFromSeedWordsViewModel by activityViewModels() + val viewModel: WalletRestoringFromSeedWordsViewModel by viewModels() bindViewModel(viewModel) subscribeUI() diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsViewModel.kt index 1c6a47258..3df0ee1a3 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/walletRestoringFromSeedWords/WalletRestoringFromSeedWordsViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.tari.android.wallet.R +import com.tari.android.wallet.application.baseNodes.BaseNodeDto import com.tari.android.wallet.application.baseNodes.BaseNodes import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository import com.tari.android.wallet.event.EventBus @@ -18,6 +19,7 @@ import com.tari.android.wallet.ui.common.CommonViewModel import com.tari.android.wallet.ui.common.SingleLiveEvent import com.tari.android.wallet.ui.common.domain.ResourceManager import com.tari.android.wallet.ui.dialog.error.ErrorDialogArgs +import io.reactivex.disposables.CompositeDisposable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.text.DecimalFormat @@ -25,6 +27,7 @@ import javax.inject.Inject internal class WalletRestoringFromSeedWordsViewModel() : CommonViewModel() { + @Inject lateinit var seedPhraseRepository: SeedPhraseRepository @@ -37,6 +40,7 @@ internal class WalletRestoringFromSeedWordsViewModel() : CommonViewModel() { @Inject lateinit var baseNodes: BaseNodes + private lateinit var baseNodeIterator: Iterator private val _navigation = SingleLiveEvent() val navigation: LiveData = _navigation @@ -49,14 +53,27 @@ internal class WalletRestoringFromSeedWordsViewModel() : CommonViewModel() { } fun startRestoring() = viewModelScope.launch(Dispatchers.IO) { + baseNodeIterator = baseNodes.baseNodeList.iterator() + tryNextBaseNode() + } + + private fun tryNextBaseNode() = viewModelScope.launch(Dispatchers.IO) { + if (baseNodeIterator.hasNext()) { + startRestoringOnNode(baseNodeIterator.next()) + } else { + onError(RestorationError.ConnectionFailed(resourceManager, this@WalletRestoringFromSeedWordsViewModel::onErrorClosed)) + } + } + + private fun startRestoringOnNode(baseNode: BaseNodeDto) { try { - for (baseNode in baseNodes.baseNodeList) { - val baseNodeFFI = FFIPublicKey(HexString(baseNode.publicKeyHex)) - val result = FFIWallet.instance?.startRecovery(baseNodeFFI) - if (result == true) { - subscribeOnRestorationState() - return@launch - } + val baseNodeFFI = FFIPublicKey(HexString(baseNode.publicKeyHex)) + val result = FFIWallet.instance?.startRecovery(baseNodeFFI) + if (result == true) { + subscribeOnRestorationState() + return + } else { + tryNextBaseNode() } onError(RestorationError.ConnectionFailed(resourceManager, this@WalletRestoringFromSeedWordsViewModel::onErrorClosed)) } catch (e: Throwable) { @@ -65,14 +82,21 @@ internal class WalletRestoringFromSeedWordsViewModel() : CommonViewModel() { } private fun subscribeOnRestorationState() { - EventBus.walletRestorationState.publishSubject.subscribe { + EventBus.walletRestorationState.publishSubject.skip(1).subscribe { when (it) { is WalletRestorationResult.ConnectingToBaseNode -> onProgress(RecoveryState.ConnectingToBaseNode(resourceManager)) is WalletRestorationResult.ConnectedToBaseNode -> onProgress(RecoveryState.ConnectedToBaseNode(resourceManager)) is WalletRestorationResult.ScanningRoundFailed -> onProgress(RecoveryState.ConnectionFailed(resourceManager, it.retryCount, it.retryLimit)) - is WalletRestorationResult.ConnectionToBaseNodeFailed -> - onProgress(RecoveryState.ConnectionFailed(resourceManager, it.retryCount, it.retryLimit)) + is WalletRestorationResult.ConnectionToBaseNodeFailed -> { + if (it.retryCount == it.retryLimit) { + compositeDisposable.dispose() + compositeDisposable = CompositeDisposable() + tryNextBaseNode() + } else { + onProgress(RecoveryState.ConnectionFailed(resourceManager, it.retryCount, it.retryLimit)) + } + } is WalletRestorationResult.Progress -> onProgress(RecoveryState.Recovery(resourceManager, it.currentBlock, it.numberOfBlocks)) is WalletRestorationResult.RecoveryFailed -> onError(RestorationError.RecoveryInternalError(resourceManager, this@WalletRestoringFromSeedWordsViewModel::onErrorClosed)) diff --git a/build.gradle b/build.gradle index a61d884f9..096452842 100644 --- a/build.gradle +++ b/build.gradle @@ -4,8 +4,8 @@ buildscript { ext.kotlin_version = '1.5.21' // build & version - ext.buildNumber = 165 - ext.versionNumber = "0.6.4" + ext.buildNumber = 167 + ext.versionNumber = "0.6.5" // JNI libs ext.libwalletVersion = "0.17.3_network"