From 53897c29268afbd71a1324a00faab0b3c49201b5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 29 Aug 2018 14:45:53 +0300 Subject: [PATCH] Updated on 2026-08-14 --- app/build.gradle | 7 +- .../tangem/data/network/CoinmarketApi.java | 13 ++ .../java/com/tangem/data/network/Server.java | 24 ++- .../tangem/data/network/ServerApiHelper.java | 199 ++++++++++++++++++ .../com/tangem/data/network/ServerURL.java | 3 +- .../com/tangem/data/network/VolleyHelper.kt | 14 +- .../{ResponseVerify.kt => CardVerifyModel.kt} | 2 +- .../data/network/model/RateInfoModel.kt | 76 +++++++ .../data/network/request/ElectrumRequest.java | 4 +- .../data/network/task/ElectrumTask.java | 14 +- .../presentation/fragment/LoadedWallet.kt | 9 +- 11 files changed, 335 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/com/tangem/data/network/CoinmarketApi.java create mode 100644 app/src/main/java/com/tangem/data/network/ServerApiHelper.java rename app/src/main/java/com/tangem/data/network/model/{ResponseVerify.kt => CardVerifyModel.kt} (94%) create mode 100644 app/src/main/java/com/tangem/data/network/model/RateInfoModel.kt diff --git a/app/build.gradle b/app/build.gradle index 152f2cfe39..e4c73f7411 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,6 +19,9 @@ android { versionName "0.88.1." + generateVersionName() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } + androidExtensions { + experimental = true + } buildTypes { release { debuggable false @@ -41,7 +44,6 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 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' @@ -54,7 +56,10 @@ dependencies { implementation 'com.madgag.spongycastle:core:1.56.0.0' implementation 'com.madgag.spongycastle:prov:1.56.0.0' implementation 'com.scottyab:rootbeer-lib:0.0.6' + implementation 'com.squareup.retrofit2:converter-gson:2.3.0' + implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' implementation 'com.skyfishjy.ripplebackground:library:1.0.1' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'org.bitcoinj:bitcoinj-parent:0.14.4' implementation 'org.bitcoinj:bitcoinj-core:0.14.4' implementation 'me.dm7.barcodescanner:zxing:1.9.8' diff --git a/app/src/main/java/com/tangem/data/network/CoinmarketApi.java b/app/src/main/java/com/tangem/data/network/CoinmarketApi.java new file mode 100644 index 0000000000..fdf50b4884 --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/CoinmarketApi.java @@ -0,0 +1,13 @@ +package com.tangem.data.network; + +import com.tangem.data.network.model.RateInfoModel; + +import java.util.List; + +import io.reactivex.Observable; +import retrofit2.http.GET; + +public interface CoinmarketApi { + @GET(Server.ApiCoinmarket.Method.V1_TICKER_CONVERT) + Observable> getRateInfoList(); +} diff --git a/app/src/main/java/com/tangem/data/network/Server.java b/app/src/main/java/com/tangem/data/network/Server.java index d4d5bd4e3e..68e41e0a27 100644 --- a/app/src/main/java/com/tangem/data/network/Server.java +++ b/app/src/main/java/com/tangem/data/network/Server.java @@ -11,15 +11,14 @@ public class Server { return headers; } - public static class API { + /** + * https://tangem-webapp.appspot.com/ + */ + public static class ApiTangem { private static final String URL_TANGEM = ServerURL.API_TANGEM; public static class Method { - /** - * https://tangem-webapp.appspot.com/ - */ public static final String INFO_VERIFY = URL_TANGEM + "info/version"; - public static final String CARD_VERIFY = URL_TANGEM + "card/verify"; public static final String VERIFY = URL_TANGEM + "verify"; public static final String CARD_VALIDATE = URL_TANGEM + "card/validate"; @@ -27,4 +26,19 @@ public class Server { } } + /** + * https://coinmarketcap.com/api/ + */ + public static class ApiCoinmarket { + public static final String URL_COINMARKET = ServerURL.API_COINMARKET; + + public static class Method { + public static final String V1_TICKER_CONVERT = URL_COINMARKET + "v1/ticker/?convert=USD&lmit=10"; + + } + + } + + + } \ 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 new file mode 100644 index 0000000000..2c842515eb --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/ServerApiHelper.java @@ -0,0 +1,199 @@ +package com.tangem.data.network; + +import android.annotation.SuppressLint; +import android.util.Log; + +import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import com.tangem.data.network.model.RateInfoModel; +import com.tangem.data.network.request.ElectrumRequest; +import com.tangem.domain.BitcoinNode; +import com.tangem.domain.BitcoinNodeTestNet; +import com.tangem.domain.wallet.Blockchain; +import com.tangem.domain.wallet.TangemCard; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.observers.DefaultObserver; +import io.reactivex.schedulers.Schedulers; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class ServerApiHelper { + private static String TAG = ServerApiHelper.class.getSimpleName(); + + /** + * HTTP + * Used in Crypto-currency course + */ + private RateInfoDataListener rateInfoDataListener; + + public interface RateInfoDataListener { + void onRateInfoDataData(RateInfoModel rateInfoModel); + } + + public void setRateInfoData(RateInfoDataListener listener) { + rateInfoDataListener = listener; + } + + @SuppressLint("CheckResult") + public void rateInfoData(String cryptoId) { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(Server.ApiCoinmarket.URL_COINMARKET) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build(); + + CoinmarketApi coinmarketApi = retrofit.create(CoinmarketApi.class); + + coinmarketApi.getRateInfoList() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(rateInfoModelList -> { + if (!rateInfoModelList.isEmpty()) { + for (RateInfoModel rateInfoMode : rateInfoModelList) { + if (rateInfoMode.getId().equals(cryptoId)) { + rateInfoDataListener.onRateInfoDataData(rateInfoMode); + Log.i("rateInfoData", rateInfoMode.getId()); + Log.i("rateInfoData", rateInfoMode.getPriceUsd()); + } + } + } + }, + // handle error + Throwable::printStackTrace); + } + + /** + * TCP + * Used in BTC + */ + private String host; + private int port; + private ElectrumRequestDataListener electrumRequestDataListener; + + public interface ElectrumRequestDataListener { + void onElectrumRequestData(ElectrumRequest electrumRequest); + } + + public void setElectrumRequestData(ElectrumRequestDataListener listener) { + electrumRequestDataListener = listener; + } + + public void electrumRequestData(TangemCard card, ElectrumRequest electrumRequest) { + Observable checkBalanceObserver = Observable.just(electrumRequest) + .doOnNext(electrumRequest1 -> doElectrumRequest(card, electrumRequest)) + .flatMap(electrumRequest1 -> { + if (electrumRequest1.answerData == null) + return Observable.error(new NullPointerException()); + else + return Observable.just(electrumRequest1); + }) + .retryWhen(errors -> errors + .filter(throwable -> throwable instanceof NullPointerException) + .zipWith(Observable.range(1, 2), (n, i) -> i)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + checkBalanceObserver.subscribe(new DefaultObserver() { + @Override + public void onNext(ElectrumRequest electrumRequest) { + if (electrumRequest.answerData != null) { + electrumRequestDataListener.onElectrumRequestData(electrumRequest); + } else { + Log.i(TAG, "onNext ElectrumRequest == null"); + } + Log.i(TAG, "onNext"); + } + + @Override + public void onError(Throwable e) { + Log.i(TAG, "onError " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.i(TAG, "onComplete"); + } + }); + } + + 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) { + BitcoinNodeTestNet bitcoinNodeTestNet = BitcoinNodeTestNet.values()[new Random().nextInt(BitcoinNodeTestNet.values().length)]; + this.host = bitcoinNodeTestNet.getHost(); + this.port = bitcoinNodeTestNet.getPort(); + + } else { + this.host = bitcoinNode.getHost(); + this.port = bitcoinNode.getPort(); + } + + List result = new ArrayList<>(); + Collections.addAll(result, electrumRequest); + + try { + Log.i(TAG, "host " + host + " !!!!!!!!!!!! " + "port " + String.valueOf(port)); + InetAddress serverAddress = InetAddress.getByName(host); + Socket socket = new Socket(); + socket.setSoTimeout(5000); + socket.bind(new InetSocketAddress(0)); + socket.connect(new InetSocketAddress(serverAddress, port)); + try { + Log.i(TAG, "<< "); + 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); + + // do request + try { + 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 (Exception e) { + electrumRequest.error = e.toString(); + } + + } catch (Exception e) { + e.printStackTrace(); + Log.i(TAG, e.getMessage()); + } finally { + Log.i(TAG, "close"); + socket.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + public String getValidationNodeDescription() { + return "Electrum, " + host + ":" + String.valueOf(port); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/data/network/ServerURL.java b/app/src/main/java/com/tangem/data/network/ServerURL.java index 6a71c917e0..d376baaeed 100644 --- a/app/src/main/java/com/tangem/data/network/ServerURL.java +++ b/app/src/main/java/com/tangem/data/network/ServerURL.java @@ -1,8 +1,9 @@ + package com.tangem.data.network; public class ServerURL { -// public static final String API_TANGEM = "https://tangem-webapp.appspot.com/"; public static final String API_TANGEM = "https://verify.tangem.com/"; + public static final String API_COINMARKET = "https://api.coinmarketcap.com/"; } diff --git a/app/src/main/java/com/tangem/data/network/VolleyHelper.kt b/app/src/main/java/com/tangem/data/network/VolleyHelper.kt index 44d1fd38ff..e46145882b 100644 --- a/app/src/main/java/com/tangem/data/network/VolleyHelper.kt +++ b/app/src/main/java/com/tangem/data/network/VolleyHelper.kt @@ -4,7 +4,6 @@ import android.app.Activity import android.content.Context import android.content.Intent import android.support.v7.app.AlertDialog -import android.util.Log import com.android.volley.AuthFailureError import com.android.volley.DefaultRetryPolicy import com.android.volley.Request @@ -12,18 +11,17 @@ import com.android.volley.Response import com.android.volley.toolbox.StringRequest import com.google.gson.Gson import com.tangem.AppController -import com.tangem.data.network.model.ResponseVerify +import com.tangem.data.network.model.CardVerifyModel import com.tangem.domain.wallet.TangemCard -import com.tangem.presentation.fragment.LoadedWallet import com.tangem.util.Util import com.tangem.wallet.R -import java.util.HashMap +import java.util.* class VolleyHelper (private val requestCardVerify: IRequestCardVerify){ interface IRequestCardVerify { - fun success(responseVerify: ResponseVerify) + fun success(cardVerifyModel: CardVerifyModel) fun error(error: String) } @@ -32,14 +30,14 @@ class VolleyHelper (private val requestCardVerify: IRequestCardVerify){ val params = HashMap() params["CID"] = Util.bytesToHex(card.cid) params["publicKey"] = Util.bytesToHex(card.cardPublicKey) - doRequestString(Server.API.Method.VERIFY, params) + doRequestString(Server.ApiTangem.Method.VERIFY, params) } fun requestCardVerifyShowResponse(context: Activity, card: TangemCard) { val params = HashMap() params["CID"] = Util.bytesToHex(card.cid) params["publicKey"] = Util.bytesToHex(card.cardPublicKey) - doRequestDebug(context, Server.API.Method.VERIFY, params) + doRequestDebug(context, Server.ApiTangem.Method.VERIFY, params) } fun doRequestDebug(context: Context, url: String, params: Map) { @@ -84,7 +82,7 @@ class VolleyHelper (private val requestCardVerify: IRequestCardVerify){ Response.Listener { response -> val requestResponse = response.toString().substring(response.toString().lastIndexOf("Response:") + 10) - val responseVerify = Gson().fromJson(requestResponse, ResponseVerify::class.java) + val responseVerify = Gson().fromJson(requestResponse, CardVerifyModel::class.java) requestCardVerify.success(responseVerify) diff --git a/app/src/main/java/com/tangem/data/network/model/ResponseVerify.kt b/app/src/main/java/com/tangem/data/network/model/CardVerifyModel.kt similarity index 94% rename from app/src/main/java/com/tangem/data/network/model/ResponseVerify.kt rename to app/src/main/java/com/tangem/data/network/model/CardVerifyModel.kt index 9b10a37e7e..f0c27d1efd 100644 --- a/app/src/main/java/com/tangem/data/network/model/ResponseVerify.kt +++ b/app/src/main/java/com/tangem/data/network/model/CardVerifyModel.kt @@ -2,7 +2,7 @@ package com.tangem.data.network.model import com.google.gson.annotations.SerializedName -data class ResponseVerify( +data class CardVerifyModel( @SerializedName("results") var results: ArrayList? = null, diff --git a/app/src/main/java/com/tangem/data/network/model/RateInfoModel.kt b/app/src/main/java/com/tangem/data/network/model/RateInfoModel.kt new file mode 100644 index 0000000000..80236d0872 --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/model/RateInfoModel.kt @@ -0,0 +1,76 @@ +package com.tangem.data.network.model + +import android.os.Parcelable +import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class RateInfoModel( + @SerializedName(ID) + var id: String = "", + + @SerializedName(NAME) + var name: String = "", + + @SerializedName(SYMBOL) + var symbol: String = "", + + @SerializedName(RANK) + var rank: String = "", + + @SerializedName(PRICE_USD) + var priceUsd: String = "", + + @SerializedName(PRICE_BTC) + var priceBtc: String = "", + + @SerializedName(VOLUME_USD_24H) + var volumeUsd24h: String = "", + + @SerializedName(MARKET_CAP_USD) + var marketCapUsd: String = "", + + @SerializedName(AVAILABLE_SUPPLY) + var availableSupply: String = "", + + @SerializedName(TOTAL_SUPPLY) + var totalSupply: String = "", + + @SerializedName(MAX_SUPPLY) + var maxSupply: String = "", + + @SerializedName(PERCENT_CHANGE_1H) + var percentChange1h: String = "", + + @SerializedName(PERCENT_CHANGE_24H) + var percentChange24h: String = "", + + @SerializedName(PERCENT_CHANGE_7H) + var percentChange7h: String = "", + + @SerializedName(LAST_UPDATED) + var lastUpdated: String = "" + +) : Parcelable { + + companion object { + val TAG: String = RateInfoModel::class.java.simpleName + + const val ID = "id" + const val NAME = "name" + const val SYMBOL = "symbol" + const val RANK = "rank" + const val PRICE_USD = "price_usd" + const val PRICE_BTC = "price_btc" + const val VOLUME_USD_24H = "24h_volume_usd" + const val MARKET_CAP_USD = "market_cap_usd" + const val AVAILABLE_SUPPLY = "available_supply" + const val TOTAL_SUPPLY = "total_supply" + const val MAX_SUPPLY = "max_supply" + const val PERCENT_CHANGE_1H = "percent_change_1h" + const val PERCENT_CHANGE_24H = "percent_change_24h" + const val PERCENT_CHANGE_7H = "percent_change_7d" + const val LAST_UPDATED = "last_updated" + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/data/network/request/ElectrumRequest.java b/app/src/main/java/com/tangem/data/network/request/ElectrumRequest.java index 197dbafeab..3072c2e40c 100644 --- a/app/src/main/java/com/tangem/data/network/request/ElectrumRequest.java +++ b/app/src/main/java/com/tangem/data/network/request/ElectrumRequest.java @@ -23,8 +23,8 @@ public class ElectrumRequest { public String walletAddress; public String txHash; public String TX; - public String Host; - public int Port; + public String host; + public int port; private ElectrumRequest() { } diff --git a/app/src/main/java/com/tangem/data/network/task/ElectrumTask.java b/app/src/main/java/com/tangem/data/network/task/ElectrumTask.java index 2001e0fc9f..2d1855c16d 100644 --- a/app/src/main/java/com/tangem/data/network/task/ElectrumTask.java +++ b/app/src/main/java/com/tangem/data/network/task/ElectrumTask.java @@ -24,8 +24,8 @@ import java.util.List; public class ElectrumTask extends AsyncTask> { public static final String logTag = "Electrum"; - //public static final String Host = /*"hsmiths.changeip.net";*/ "testnetnode.arihanc.com"; - //public static final int Port = /*8080*/51001; + //public static final String host = /*"hsmiths.changeip.net";*/ "testnetnode.arihanc.com"; + //public static final int port = /*8080*/51001; private int reqID = 1; private String Host = ""; private int Port = 0; @@ -58,13 +58,13 @@ public class ElectrumTask extends AsyncTask> " + request.answerData); } else { diff --git a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt index 11d3313327..a288814f5c 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt +++ b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt @@ -21,9 +21,8 @@ import android.view.ViewGroup import android.widget.Toast import com.android.volley.BuildConfig import com.google.zxing.WriterException -import com.tangem.data.network.Server import com.tangem.data.network.VolleyHelper -import com.tangem.data.network.model.ResponseVerify +import com.tangem.data.network.model.CardVerifyModel import com.tangem.data.network.request.ElectrumRequest import com.tangem.data.network.request.ExchangeRequest import com.tangem.data.network.request.InfuraRequest @@ -54,8 +53,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific } } - override fun success(responseVerify: ResponseVerify) { -// Toast.makeText(activity, responseVerify.results!![1].CID, Toast.LENGTH_SHORT).show() + override fun success(cardVerifyModel: CardVerifyModel) { +// Toast.makeText(activity, cardVerifyModel.results!![1].CID, Toast.LENGTH_SHORT).show() } override fun error(error: String) { @@ -74,7 +73,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific private const val REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN = 7 private const val REQUEST_CODE_SWAP_PIN = 8 - private const val URL_CARD_VERIFY = Server.API.Method.VERIFY +// private const val URL_CARD_VERIFY = Server.API.Method.VERIFY } private var singleToast: Toast? = null