diff --git a/app/build.gradle b/app/build.gradle index c16fb9fd1e..c6249eba39 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,12 +10,12 @@ static def generateVersionName() { } android { - compileSdkVersion 27 + compileSdkVersion 28 defaultConfig { applicationId "com.tangem.wallet" minSdkVersion 21 - targetSdkVersion 27 - versionCode 94 + targetSdkVersion 28 + versionCode 95 versionName "0.810.1." + generateVersionName() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -44,11 +44,11 @@ android { } dependencies { - implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support:design:27.1.1' - implementation 'com.android.support:support-compat:27.1.1' - implementation 'com.android.support:cardview-v7:27.1.1' - implementation 'com.android.support:support-v4:27.1.1' + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:design:28.0.0' + implementation 'com.android.support:support-compat:28.0.0' + implementation 'com.android.support:cardview-v7:28.0.0' + implementation 'com.android.support:support-v4:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.google.zxing:core:3.3.3' implementation 'com.google.code.gson:gson:2.8.5' diff --git a/app/src/main/java/com/tangem/App.java b/app/src/main/java/com/tangem/App.java index 4e9651f716..d043098cd9 100644 --- a/app/src/main/java/com/tangem/App.java +++ b/app/src/main/java/com/tangem/App.java @@ -3,8 +3,8 @@ package com.tangem; import android.app.Application; import android.support.v7.app.AppCompatDelegate; -import com.tangem.di.AppComponent; -import com.tangem.di.DaggerAppComponent; +import com.tangem.di.DaggerNetworkComponent; +import com.tangem.di.NetworkComponent; public class App extends Application { @@ -21,7 +21,7 @@ public class App extends Application { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } - private static AppComponent component; + private static NetworkComponent networkComponent; @Override public void onCreate() { @@ -29,7 +29,7 @@ public class App extends Application { // initialize the singleton sInstance = this; - component = DaggerAppComponent.create(); + networkComponent = DaggerNetworkComponent.create(); } /** @@ -39,8 +39,8 @@ public class App extends Application { return sInstance; } - public static AppComponent getComponent() { - return component; + public static NetworkComponent getNetworkComponent() { + return networkComponent; } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/data/network/ServerApiHelper.java b/app/src/main/java/com/tangem/data/network/ServerApiHelper.java index 262a5d4ddb..02eaf41fa6 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiHelper.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiHelper.java @@ -46,7 +46,7 @@ public class ServerApiHelper { } public void estimateFee(int blockCount) { - EstimatefeeApi estimatefeeApi = App.getComponent().getRetrofitEstimatefee().create(EstimatefeeApi.class); + EstimatefeeApi estimatefeeApi = App.getNetworkComponent().getRetrofitEstimatefee().create(EstimatefeeApi.class); Call call; switch (blockCount) { @@ -114,7 +114,7 @@ public class ServerApiHelper { } public void infura(String method, int id, String wallet, String contract, String tx) { - InfuraApi infuraApi = App.getComponent().getRetrofitInfura().create(InfuraApi.class); + InfuraApi infuraApi = App.getNetworkComponent().getRetrofitInfura().create(InfuraApi.class); InfuraBody infuraBody; switch (method) { @@ -179,7 +179,7 @@ public class ServerApiHelper { } public void cardVerifyAndGetInfo(TangemCard card) { - TangemApi tangemApi = App.getComponent().getRetrofitTangem().create(TangemApi.class); + TangemApi tangemApi = App.getNetworkComponent().getRetrofitTangem().create(TangemApi.class); List requests = new ArrayList<>(); requests.add(new CardVerifyAndGetInfo.Request.Item(Util.bytesToHex(card.getCID()), Util.bytesToHex(card.getCardPublicKey()))); @@ -224,7 +224,7 @@ public class ServerApiHelper { } public void requestArtwork(String artworkId, Date updateDate, TangemCard card) { - TangemApi tangemApi = App.getComponent().getRetrofitTangem().create(TangemApi.class); + TangemApi tangemApi = App.getNetworkComponent().getRetrofitTangem().create(TangemApi.class); Call call = tangemApi.getArtwork(artworkId, Util.bytesToHex(card.getCID()), Util.bytesToHex(card.getCardPublicKey())); call.enqueue(new Callback() { @@ -267,7 +267,7 @@ public class ServerApiHelper { @SuppressLint("CheckResult") public void rateInfoData(String cryptoId) { - CoinmarketApi coinmarketApi = App.getComponent().getRetrofitCoinmarketcap().create(CoinmarketApi.class); + CoinmarketApi coinmarketApi = App.getNetworkComponent().getRetrofitCoinmarketcap().create(CoinmarketApi.class); coinmarketApi.getRateInfoList() .subscribeOn(Schedulers.io()) @@ -302,7 +302,7 @@ public class ServerApiHelper { } public void requestLastVersion() { - UpdateVersionApi updateVersionApi = App.getComponent().getRetrofitGithubusercontent().create(UpdateVersionApi.class); + UpdateVersionApi updateVersionApi = App.getNetworkComponent().getRetrofitGithubusercontent().create(UpdateVersionApi.class); Call call = updateVersionApi.getLastVersion(); call.enqueue(new Callback() { diff --git a/app/src/main/java/com/tangem/data/network/ServerApiHelperElectrum.java b/app/src/main/java/com/tangem/data/network/ServerApiHelperElectrum.java index f5dac594f2..2dcf50a452 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiHelperElectrum.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiHelperElectrum.java @@ -9,6 +9,7 @@ import com.tangem.domain.wallet.Blockchain; import com.tangem.domain.wallet.TangemCard; import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; @@ -22,6 +23,15 @@ import java.util.Collections; import java.util.List; import java.util.Random; +import javax.net.SocketFactory; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.observers.DefaultObserver; @@ -41,6 +51,7 @@ public class ServerApiHelperElectrum { public interface ElectrumRequestDataListener { void onSuccess(ElectrumRequest electrumRequest); + void onFail(String method); } @@ -52,6 +63,7 @@ public class ServerApiHelperElectrum { Observable checkElectrumDataObserver = Observable.just(electrumRequest) .doOnNext(electrumRequest1 -> doElectrumRequest(card, electrumRequest)) +// .doOnNext(electrumRequest1 -> testSslSocket(card, electrumRequest)) .flatMap(electrumRequest1 -> { if (electrumRequest1.answerData == null) { @@ -94,7 +106,61 @@ public class ServerApiHelperElectrum { }); } - private List doElectrumRequest(TangemCard card, ElectrumRequest electrumRequest) throws ConnectException { + private List testSslSocket(TangemCard card, ElectrumRequest electrumRequest) { + SocketFactory sf = SSLSocketFactory.getDefault(); + SSLSocket socket; + + List result = new ArrayList<>(); + Collections.addAll(result, electrumRequest); + + try { +// socket = (SSLSocket) sf.createSocket("gmail.com", 443); + socket = (SSLSocket) sf.createSocket("electrum.hsmiths.com", 50002); + HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); + SSLSession s = socket.getSession(); + +// if (!hv.verify("mail.google.com", s)) { +// throw new SSLHandshakeException("Expected mail.google.com, found " + s.getPeerPrincipal()); +// } + + + try { + OutputStream os = socket.getOutputStream(); + OutputStreamWriter out = new OutputStreamWriter(os, "UTF-8"); + InputStream is = socket.getInputStream(); + BufferedReader in = new BufferedReader(new InputStreamReader(is)); + electrumRequest.setID(1); + + out.write(electrumRequest.getAsString() + "\n"); + out.flush(); + + electrumRequest.answerData = in.readLine(); +// electrumRequest.host = host; +// electrumRequest.port = port; + if (electrumRequest.answerData != null) { + Log.i(TAG, ">> " + electrumRequest.answerData); + } else { + electrumRequest.error = "No answer from server"; + Log.i(TAG, ">> "); + } + + } catch (ConnectException e) { + e.printStackTrace(); + Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " ConnectException " + e.getMessage()); + } finally { +// Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " CLOSE"); + socket.close(); + } + + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + return result; + } + + private List doElectrumRequest(TangemCard card, ElectrumRequest electrumRequest) { BitcoinNode bitcoinNode = BitcoinNode.values()[new Random().nextInt(BitcoinNode.values().length)]; if (card.getBlockchain() == Blockchain.BitcoinTestNet || card.getBlockchain() == Blockchain.BitcoinCashTestNet) { @@ -111,8 +177,8 @@ public class ServerApiHelperElectrum { Collections.addAll(result, electrumRequest); try { - Socket socket = App.getComponent().getSocket(); - socket.connect(new InetSocketAddress(InetAddress.getByName(host), port)); + Socket socket = App.getNetworkComponent().getSocket(); + socket.connect(new InetSocketAddress(InetAddress.getByName(host), port)); Log.i(TAG, host + " " + port); try { OutputStream os = socket.getOutputStream(); diff --git a/app/src/main/java/com/tangem/data/network/exception/Failure.kt b/app/src/main/java/com/tangem/data/network/exception/Failure.kt new file mode 100644 index 0000000000..f6b9deaa4c --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/exception/Failure.kt @@ -0,0 +1,31 @@ +/** + + * + * 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.dmmatrix.epro.core.exception + +/** + * Base Class for handling errors/failures/exceptions. + * Every feature specific failure should extend [FeatureFailure] class. + */ +sealed class Failure { + class ApplicationError(val message: String) : Failure() + class NotFound : FeatureFailure() + class NetworkConnection : Failure() + class ServerError : Failure() + class Unauthorized : Failure() // 401 + + /** * Extend this class for feature specific failures.*/ + abstract class FeatureFailure : Failure() +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/di/AppComponent.java b/app/src/main/java/com/tangem/di/NetworkComponent.java similarity index 95% rename from app/src/main/java/com/tangem/di/AppComponent.java rename to app/src/main/java/com/tangem/di/NetworkComponent.java index 929a6efec5..b8ac3affa5 100644 --- a/app/src/main/java/com/tangem/di/AppComponent.java +++ b/app/src/main/java/com/tangem/di/NetworkComponent.java @@ -12,7 +12,7 @@ import retrofit2.Retrofit; @Singleton @Component(modules = {NetworkModule.class}) -public interface AppComponent { +public interface NetworkComponent { @Named(Server.ApiInfura.URL_INFURA) Retrofit getRetrofitInfura(); diff --git a/app/src/main/java/com/tangem/domain/BitcoinNode.kt b/app/src/main/java/com/tangem/domain/BitcoinNode.kt index 5a1b1ce6e5..63dd415f57 100644 --- a/app/src/main/java/com/tangem/domain/BitcoinNode.kt +++ b/app/src/main/java/com/tangem/domain/BitcoinNode.kt @@ -12,5 +12,6 @@ enum class BitcoinNode(val host: String, val port: Int) { n9("electrumx.nmdps.net", 50001), n10("kirsche.emzy.de", 50001), n11("electrum.petrkr.net", 50001), - n12("electrum.dk", 50001) + n12("electrum.dk", 50001), +// n13("electrum.hsmiths.com", 50002) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/presentation/activity/LogoActivity.kt b/app/src/main/java/com/tangem/presentation/activity/LogoActivity.kt index cfc23ae554..87ddd9de47 100644 --- a/app/src/main/java/com/tangem/presentation/activity/LogoActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/LogoActivity.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle import android.support.v7.app.AppCompatActivity +import com.tangem.data.network.ServerApiHelperElectrum import com.tangem.wallet.BuildConfig import com.tangem.wallet.R import kotlinx.android.synthetic.main.activity_logo.* @@ -17,6 +18,8 @@ class LogoActivity : AppCompatActivity() { const val MILLIS_AUTO_HIDE = 1000 } + private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum() + private val hideRunnable = Runnable { this.hide() } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt b/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt index 9164b0bd32..8153d00074 100644 --- a/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt @@ -53,6 +53,8 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco const val EXTRA_LAST_DISCOVERED_TAG = "extra_last_tag" + fun callingIntent(context: Context) = Intent(context, MainActivity::class.java) + fun commonInit(context: Context) { if (PINStorage.needInit()) PINStorage.Init(context) diff --git a/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt b/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt index e64b5770dd..da36825bdc 100644 --- a/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt @@ -97,7 +97,7 @@ class SignPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card super.onStop() } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == REQUEST_CODE_SEND_PAYMENT) { setResult(resultCode, data) finish() diff --git a/app/src/main/java/com/tangem/presentation/viewmodel/BaseViewModel.kt b/app/src/main/java/com/tangem/presentation/viewmodel/BaseViewModel.kt new file mode 100644 index 0000000000..959bc6d6d3 --- /dev/null +++ b/app/src/main/java/com/tangem/presentation/viewmodel/BaseViewModel.kt @@ -0,0 +1,34 @@ +/** + + * + * 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.tangem.presentation.viewmodel + +import android.arch.lifecycle.MutableLiveData +import android.arch.lifecycle.ViewModel +import com.dmmatrix.epro.core.exception.Failure + +/** + * Base ViewModel class with default Failure handling. + * @see ViewModel + * @see Failure + */ +abstract class BaseViewModel : ViewModel() { + + var failure: MutableLiveData = MutableLiveData() + + protected fun handleFailure(failure: Failure) { + this.failure.value = failure + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/presentation/viewmodel/LoadedWalletViewModel.kt b/app/src/main/java/com/tangem/presentation/viewmodel/LoadedWalletViewModel.kt new file mode 100644 index 0000000000..46b4defd2c --- /dev/null +++ b/app/src/main/java/com/tangem/presentation/viewmodel/LoadedWalletViewModel.kt @@ -0,0 +1,33 @@ +package com.tangem.presentation.viewmodel + +import android.arch.lifecycle.MutableLiveData +import com.dmmatrix.epro.core.exception.Failure + +class LoadedWalletViewModel : BaseViewModel() { + + private val state: MutableLiveData = MutableLiveData() + + fun getState() = state + + enum class State { + ServerError, + Failed, + Success + } + + fun connectToken(data: String, data2: String) { + + } + + private fun handleTokensSaveFailure(failure: Failure) { + state.value = State.Success + handleFailure(failure) + } + + private fun handleLoginFailure(failure: Failure) { + when (failure) { + is Failure.ServerError -> state.value = State.ServerError + } + handleFailure(failure) + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index a92daa08c4..f32c4373c1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.2.71' + ext.kotlin_version = '1.3.0' repositories { google() jcenter()