From 6a14bb202fa875f165c0d9be5596379dc119973b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 17 Jan 2019 12:55:20 +0300 Subject: [PATCH 1/3] Updated on 2026-08-14 --- .../main/java/com/tangem/data/Blockchain.java | 4 +- .../tangem/data/network/CoinmarketApi.java | 11 +-- .../java/com/tangem/data/network/Server.java | 2 +- .../tangem/data/network/ServerApiCommon.java | 55 ++++++++---- .../com/tangem/data/network/ServerURL.java | 2 +- .../data/network/model/RateInfoResponse.kt | 83 ++++--------------- .../presentation/fragment/LoadedWallet.kt | 41 +++++---- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 9 files changed, 85 insertions(+), 119 deletions(-) diff --git a/app/src/main/java/com/tangem/data/Blockchain.java b/app/src/main/java/com/tangem/data/Blockchain.java index 81229b390b..f3472beb19 100644 --- a/app/src/main/java/com/tangem/data/Blockchain.java +++ b/app/src/main/java/com/tangem/data/Blockchain.java @@ -11,11 +11,11 @@ public enum Blockchain { BitcoinTestNet("BTC/test", "BTC", 100000000.0, R.drawable.ic_logo_bitcoin_testnet, "Bitcoin Testnet"), Ethereum("ETH", "ETH", 1.0, R.drawable.ic_logo_ethereum, "Ethereum"), EthereumTestNet("ETH/test", "ETH", 1.0, R.drawable.ic_logo_ethereum_testnet, "Ethereum Testnet"), - Token("Token", "ERC20", 1.0, R.drawable.ic_logo_bat_token, "Ethereum"), + Token("Token", "ETH", 1.0, R.drawable.ic_logo_bat_token, "Ethereum"), BitcoinCash("BCH", "BCH", 100000000.0, R.drawable.ic_logo_bitcoin_cash, "Bitcoin Cash"), Litecoin("LTC", "LTC", 100000000.0, R.drawable.ic_logo_bitcoin, "Litecoin"), Rootstock("RSK", "RBTC", 1.0, R.drawable.ic_logo_bitcoin, "Rootstock"), - RootstockToken("Token", "ERC20", 1.0, R.drawable.ic_logo_bat_token, "Rootstock"); + RootstockToken("RSKToken", "RBTC", 1.0, R.drawable.ic_logo_bat_token, "Rootstock"); Blockchain(String ID, String currency, double multiplier, int imageResource, String officialName) { mID = ID; diff --git a/app/src/main/java/com/tangem/data/network/CoinmarketApi.java b/app/src/main/java/com/tangem/data/network/CoinmarketApi.java index 9a101000fa..d14422cc88 100644 --- a/app/src/main/java/com/tangem/data/network/CoinmarketApi.java +++ b/app/src/main/java/com/tangem/data/network/CoinmarketApi.java @@ -2,12 +2,13 @@ package com.tangem.data.network; import com.tangem.data.network.model.RateInfoResponse; -import java.util.List; - -import io.reactivex.Observable; +import retrofit2.Call; import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Query; public interface CoinmarketApi { - @GET(Server.ApiCoinmarket.Method.V1_TICKER_CONVERT) - Observable> getRateInfoList(); + @Headers("X-CMC_PRO_API_KEY: 7850b957-6943-42eb-af73-8d536dd8f73e") + @GET(Server.ApiCoinmarket.Method.PRICE_CONVERSION) + Call getRateInfo(@Query("amount") int amount, @Query("symbol") String cryptoId); } \ No newline at end of file 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 9be4f58449..85db1a8643 100644 --- a/app/src/main/java/com/tangem/data/network/Server.java +++ b/app/src/main/java/com/tangem/data/network/Server.java @@ -17,7 +17,7 @@ public class Server { public static final String URL_COINMARKET = ServerURL.API_COINMARKETCAP; public static class Method { - static final String V1_TICKER_CONVERT = URL_COINMARKET + "v1/ticker/?convert=USD&lmit=10"; + static final String PRICE_CONVERSION = URL_COINMARKET + "v1/tools/price-conversion"; } } diff --git a/app/src/main/java/com/tangem/data/network/ServerApiCommon.java b/app/src/main/java/com/tangem/data/network/ServerApiCommon.java index 7ab8fe42e0..43112f0219 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiCommon.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiCommon.java @@ -83,32 +83,53 @@ public class ServerApiCommon { public interface RateInfoDataListener { void onSuccess(RateInfoResponse rateInfoResponse); + + void onFail(String message); } public void setRateInfoData(RateInfoDataListener listener) { rateInfoDataListener = listener; } - @SuppressLint("CheckResult") public void rateInfoData(String cryptoId) { CoinmarketApi coinmarketApi = App.getNetworkComponent().getRetrofitCoinmarketcap().create(CoinmarketApi.class); - coinmarketApi.getRateInfoList() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(rateInfoModelList -> { - if (!rateInfoModelList.isEmpty()) { - for (RateInfoResponse rateInfoMode : rateInfoModelList) { - if (rateInfoMode.getId().equals(cryptoId)) { - rateInfoDataListener.onSuccess(rateInfoMode); - Log.i(TAG, "rateInfoData " + cryptoId + " onResponse " + "200"); - } - } - } else - Log.e(TAG, "rateInfoData " + cryptoId + " onResponse " + "Empty"); - }, - // handle error - Throwable::printStackTrace); + Call call = coinmarketApi.getRateInfo(1, cryptoId); + + call.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.code() == 200) { + rateInfoDataListener.onSuccess(response.body()); + Log.i(TAG, "coinmarketcap onResponse " + response.code()); + } else { + rateInfoDataListener.onFail(String.valueOf(response.code())); + Log.e(TAG, "coinmarketcap onResponse " + response.code()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + rateInfoDataListener.onFail(String.valueOf(t.getMessage())); + Log.e(TAG, "coinmarketcap onFailure " + t.getMessage()); + } + }); +// coinmarketApi.getRateInfoList() +// .subscribeOn(Schedulers.io()) +// .observeOn(AndroidSchedulers.mainThread()) +// .subscribe(rateInfoModelList -> { +// if (!rateInfoModelList.isEmpty()) { +// for (RateInfoResponse rateInfoMode : rateInfoModelList) { +// if (rateInfoMode.getId().equals(cryptoId)) { +// rateInfoDataListener.onSuccess(rateInfoMode); +// Log.i(TAG, "rateInfoData " + cryptoId + " onResponse " + "200"); +// } +// } +// } else +// Log.e(TAG, "rateInfoData " + cryptoId + " onResponse " + "Empty"); +// }, +// // handle error +// Throwable::printStackTrace); } /** 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 b33d4c4ba4..3dc1bf5064 100644 --- a/app/src/main/java/com/tangem/data/network/ServerURL.java +++ b/app/src/main/java/com/tangem/data/network/ServerURL.java @@ -2,7 +2,7 @@ package com.tangem.data.network; class ServerURL { static final String API_TANGEM = "https://verify.tangem.com/"; - static final String API_COINMARKETCAP = "https://api.coinmarketcap.com/"; + static final String API_COINMARKETCAP = "https://sandbox-api.coinmarketcap.com/"; //TODO: change to "https://pro-api.coinmarketcap.com/" for production environment static final String API_INFURA = "https://mainnet.infura.io/"; static final String API_ESTIMATEFEE = "https://estimatefee.com/"; static final String API_UPDATE_VERSION = "https://raw.githubusercontent.com/"; diff --git a/app/src/main/java/com/tangem/data/network/model/RateInfoResponse.kt b/app/src/main/java/com/tangem/data/network/model/RateInfoResponse.kt index 359c450fec..6fd76e8581 100644 --- a/app/src/main/java/com/tangem/data/network/model/RateInfoResponse.kt +++ b/app/src/main/java/com/tangem/data/network/model/RateInfoResponse.kt @@ -1,76 +1,23 @@ package com.tangem.data.network.model -import android.os.Parcelable import com.google.gson.annotations.SerializedName -import kotlinx.android.parcel.Parcelize -@Parcelize data class RateInfoResponse( - @SerializedName(ID) - var id: String = "", + @SerializedName("data") + var data: RateData? = null +) - @SerializedName(NAME) - var name: String = "", +data class RateData( + @SerializedName("quote") + var quote: Quote? = null +) - @SerializedName(SYMBOL) - var symbol: String = "", +data class Quote( + @SerializedName("USD") + var usd: CurrencyRate? = null +) - @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 = RateInfoResponse::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 +data class CurrencyRate( + @SerializedName("price") + var price: Float? = null +) \ No newline at end of file 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 5f1dcb1c92..99e9d96208 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt +++ b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt @@ -22,6 +22,7 @@ import com.tangem.App import com.tangem.Constant import com.tangem.data.Blockchain import com.tangem.data.network.ServerApiCommon +import com.tangem.data.network.model.RateInfoResponse import com.tangem.domain.wallet.BalanceValidator import com.tangem.domain.wallet.CoinEngine import com.tangem.domain.wallet.CoinEngineFactory @@ -258,12 +259,24 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific serverApiTangem.setArtworkListener(artworkListener) // request rate info listener - serverApiCommon.setRateInfoData { - if (activity == null || !UtilHelper.isOnline(activity!!)) return@setRateInfoData - val rate = it.priceUsd.toFloat() - ctx.coinData!!.rate = rate - ctx.coinData!!.rateAlter = rate + val rateInfoDataListener: ServerApiCommon.RateInfoDataListener = object : ServerApiCommon.RateInfoDataListener { + + override fun onSuccess(rateInfoResponse: RateInfoResponse?){ + ctx.coinData!!.rate = rateInfoResponse!!.data!!.quote!!.usd!!.price!! + } + + override fun onFail(message: String?){ + ctx.error = message + } } + serverApiCommon.setRateInfoData(rateInfoDataListener) + +// serverApiCommon.setRateInfoData { +// if (activity == null || !UtilHelper.isOnline(activity!!)) return@setRateInfoData +// val rate = it.priceUsd.toFloat() +// ctx.coinData!!.rate = rate +// ctx.coinData!!.rateAlter = rate +// } refresh() @@ -695,23 +708,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific private fun requestRateInfo() { if (UtilHelper.isOnline(context as Activity)) { LOG.i(TAG, "requestRateInfo") - - // TODO - move requestRateInfo to CoinEngine - val cryptoId: String = when (ctx.blockchain) { - Blockchain.Bitcoin -> "bitcoin" - Blockchain.BitcoinTestNet -> "bitcoin" - Blockchain.Ethereum -> "ethereum" - Blockchain.EthereumTestNet -> "ethereum" - Blockchain.Token -> "ethereum" - Blockchain.BitcoinCash -> "bitcoin-cash" - Blockchain.Litecoin -> "litecoin" - Blockchain.Rootstock -> "bitcoin" - Blockchain.RootstockToken ->"bitcoin" - else -> { - throw Exception("Can''t get rate for blockchain " + ctx.blockchainName) - } - } - serverApiCommon.rateInfoData(cryptoId) + serverApiCommon.rateInfoData(ctx.blockchain.currency) } else { ctx.error = getString(R.string.no_connection) updateViews() diff --git a/build.gradle b/build.gradle index 3942b0608f..03239d7756 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7368b742cc..227eb11196 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Sep 25 21:50:16 MSK 2018 +#Wed Jan 16 11:40:34 MSK 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip From 041948279549f4bfa9135a030b4a44249fa6905a Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 18 Jan 2019 12:30:41 +0300 Subject: [PATCH 2/3] Updated on 2026-08-14 --- app/src/main/java/com/tangem/data/network/ServerApiCommon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/data/network/ServerApiCommon.java b/app/src/main/java/com/tangem/data/network/ServerApiCommon.java index 43112f0219..7b38d550d0 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiCommon.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiCommon.java @@ -103,7 +103,7 @@ public class ServerApiCommon { rateInfoDataListener.onSuccess(response.body()); Log.i(TAG, "coinmarketcap onResponse " + response.code()); } else { - rateInfoDataListener.onFail(String.valueOf(response.code())); + rateInfoDataListener.onFail("Rate info error:" + String.valueOf(response.code())); Log.e(TAG, "coinmarketcap onResponse " + response.code()); } } From 3f743ec35356acf446f4fcddc8517eaf8b584585 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 18 Jan 2019 16:38:17 +0300 Subject: [PATCH 3/3] Updated on 2026-08-14 --- .../tangem/domain/wallet/eth/EthEngine.java | 2 +- .../tangem/domain/wallet/rsk/RskEngine.java | 22 ++++++++----------- .../domain/wallet/rsk/RskTokenEngine.java | 15 ------------- .../domain/wallet/token/TokenEngine.java | 2 +- .../presentation/fragment/LoadedWallet.kt | 9 +++++++- 5 files changed, 19 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java b/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java index 876bc8bd17..b6635e395a 100644 --- a/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java @@ -45,7 +45,7 @@ public class EthEngine extends CoinEngine { } else if (ctx.getCoinData() instanceof EthData) { coinData = (EthData) ctx.getCoinData(); } else { - throw new Exception("Invalid type of Blockchain data for EthEngine"); + throw new Exception("Invalid type of Blockchain data for " + this.getClass().getSimpleName()); } } diff --git a/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java b/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java index 7d34f079cb..b1a83967a1 100644 --- a/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java @@ -28,15 +28,7 @@ public class RskEngine extends EthEngine { private static final String TAG = RskEngine.class.getSimpleName(); public RskEngine(TangemContext ctx) throws Exception { - this.ctx = ctx; - if (ctx.getCoinData() == null) { - coinData = new EthData(); - ctx.setCoinData(coinData); - } else if (ctx.getCoinData() instanceof EthData) { - coinData = (EthData) ctx.getCoinData(); - } else { - throw new Exception("Invalid type of Blockchain data for RskEngine"); - } + super(ctx); } public RskEngine() { @@ -58,10 +50,14 @@ public class RskEngine extends EthEngine { } @Override - public Uri getShareWalletUri() { return Uri.parse(ctx.getCoinData().getWallet()); } + public Uri getShareWalletUri() { + return Uri.parse(ctx.getCoinData().getWallet()); + } @Override - public Uri getShareWalletUriExplorer() { return Uri.parse("https://explorer.rsk.co/address/" + ctx.getCoinData().getWallet()); } + public Uri getShareWalletUriExplorer() { + return Uri.parse("https://explorer.rsk.co/address/" + ctx.getCoinData().getWallet()); + } @Override public SignTask.PaymentToSign constructPayment(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) { @@ -138,7 +134,7 @@ public class RskEngine extends EthEngine { throw new Exception("Error in RskEngine - invalid v"); } tx.signature.v = (byte) v; - Log.e(TAG, "RSK_v: " +String.valueOf(v)); + Log.e(TAG, "RSK_v: " + String.valueOf(v)); byte[] txForSend = tx.getEncoded(); notifyOnNeedSendPayment(txForSend); @@ -272,7 +268,7 @@ public class RskEngine extends EthEngine { blockchainRequestsCallbacks.onComplete(false); } else { BigInteger nonce = coinData.getConfirmedTXCount(); - nonce=nonce.add(BigInteger.valueOf(1)); + nonce = nonce.add(BigInteger.valueOf(1)); coinData.setConfirmedTXCount(nonce); ctx.setError(null); blockchainRequestsCallbacks.onComplete(true); diff --git a/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java b/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java index f571505f4b..e1064e9e74 100644 --- a/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java @@ -34,21 +34,6 @@ public class RskTokenEngine extends TokenEngine { public RskTokenEngine(TangemContext ctx) throws Exception { super(ctx); - if (ctx.getCoinData() == null) { - coinData = new TokenData(); - ctx.setCoinData(coinData); - } else if (ctx.getCoinData() instanceof TokenData) { - coinData = (TokenData) ctx.getCoinData(); - } else if (ctx.getCoinData() instanceof EthData) { - // special case with receive card data substitution from server at the moment - Bundle B=new Bundle(); - ctx.getCoinData().saveToBundle(B); - coinData = new TokenData(); - coinData.loadFromBundle(B); - ctx.setCoinData(coinData); - } else { - throw new Exception("Invalid type of Blockchain data for RskTokenEngine"); - } } public RskTokenEngine() { diff --git a/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java b/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java index dd6e5fb76f..08a1398551 100644 --- a/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java @@ -55,7 +55,7 @@ public class TokenEngine extends CoinEngine { coinData.loadFromBundle(B); ctx.setCoinData(coinData); } else { - throw new Exception("Invalid type of Blockchain data for TokenEngine"); + throw new Exception("Invalid type of Blockchain data for " + this.getClass().getSimpleName()); } } 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 99e9d96208..30565a6493 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt +++ b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt @@ -262,7 +262,14 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific val rateInfoDataListener: ServerApiCommon.RateInfoDataListener = object : ServerApiCommon.RateInfoDataListener { override fun onSuccess(rateInfoResponse: RateInfoResponse?){ - ctx.coinData!!.rate = rateInfoResponse!!.data!!.quote!!.usd!!.price!! + try { + ctx.coinData!!.rate = rateInfoResponse!!.data!!.quote!!.usd!!.price!! + } + catch (e : java.lang.Exception) { + e.printStackTrace() + ctx.error = "Unknown response from CoinMarketCap" + } + } override fun onFail(message: String?){