Updated on 2026-08-14
This commit is contained in:
parent
08f641216f
commit
53897c2926
11 changed files with 335 additions and 30 deletions
|
|
@ -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'
|
||||
|
|
|
|||
13
app/src/main/java/com/tangem/data/network/CoinmarketApi.java
Normal file
13
app/src/main/java/com/tangem/data/network/CoinmarketApi.java
Normal file
|
|
@ -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<List<RateInfoModel>> getRateInfoList();
|
||||
}
|
||||
|
|
@ -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";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
199
app/src/main/java/com/tangem/data/network/ServerApiHelper.java
Normal file
199
app/src/main/java/com/tangem/data/network/ServerApiHelper.java
Normal file
|
|
@ -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<ElectrumRequest> 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<ElectrumRequest>() {
|
||||
@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<ElectrumRequest> 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<ElectrumRequest> 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, ">> <NULL>");
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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/";
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String, String>()
|
||||
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<String, String>()
|
||||
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<String, String>) {
|
||||
|
|
@ -84,7 +82,7 @@ class VolleyHelper (private val requestCardVerify: IRequestCardVerify){
|
|||
Response.Listener<String> { 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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Verify>? = null,
|
||||
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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() {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ import java.util.List;
|
|||
|
||||
public class ElectrumTask extends AsyncTask<ElectrumRequest, Integer, List<ElectrumRequest>> {
|
||||
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<ElectrumRequest, Integer, List<Elect
|
|||
try {
|
||||
InetAddress serverAddress = InetAddress.getByName(Host);
|
||||
Log.v(logTag, "Connecting..." + Host);
|
||||
// Socket socket = new Socket(serverAddress, Port);
|
||||
// Socket socket = new Socket(serverAddress, port);
|
||||
Socket socket = new Socket();
|
||||
socket.setSoTimeout(5000);
|
||||
socket.bind(new InetSocketAddress(0));
|
||||
socket.connect(new InetSocketAddress(serverAddress, Port));
|
||||
// Log.i("effefefe", Host);
|
||||
// Log.i("effefefe", String.valueOf(Port));
|
||||
// Log.i("effefefe", host);
|
||||
// Log.i("effefefe", String.valueOf(port));
|
||||
try {
|
||||
OutputStream os = socket.getOutputStream();
|
||||
out = new OutputStreamWriter(os, "UTF-8");
|
||||
|
|
@ -105,8 +105,8 @@ public class ElectrumTask extends AsyncTask<ElectrumRequest, Integer, List<Elect
|
|||
out.flush();
|
||||
|
||||
request.answerData = in.readLine();
|
||||
request.Host = Host;
|
||||
request.Port = Port;
|
||||
request.host = Host;
|
||||
request.port = Port;
|
||||
if (request.answerData != null) {
|
||||
Log.v(logTag, ">> " + request.answerData);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue