Updated on 2026-08-14

This commit is contained in:
Tangem 2018-12-16 19:51:54 +03:00
parent e7c57f1e11
commit 97c60b5f9d
18 changed files with 1098 additions and 611 deletions

View file

@ -17,14 +17,14 @@ public class ElectrumRequest {
public static final String METHOD_SendTransaction = "blockchain.transaction.broadcast";
public static final String METHOD_GetFee = "blockchain.estimatefee";
public JSONObject jsRequestData;
public String answerData;
public String error;
public String walletAddress;
private JSONObject jsRequestData;
String answerData;
private String error = null;
private String walletAddress;
public String txHash;
public String TX;
public String host;
public int port;
private String TX;
String host;
int port;
private ElectrumRequest() {
}
@ -155,15 +155,30 @@ public class ElectrumRequest {
return getAnswer().getJSONObject("result");
}
public JSONObject getError() throws JSONException {
JSONObject answer = getAnswer();
if (answer.has("error")) {
return getAnswer().getJSONObject("error");
} else {
return null;
public String getError() {
if( answerData!=null ) {
// answer received - return error from it
JSONObject answer = getAnswer();
if (answer.has("error")) {
try {
return getAnswer().getJSONObject("error").toString();
} catch (JSONException e) {
e.printStackTrace();
return null;
}
} else {
return null;
}
}else{
// no answer received - return saved error reason
return error;
}
}
public void setError(String error) {
this.error = error;
}
public String getResultString() throws JSONException {
if (getAnswer().has("result")) {
return getAnswer().getString("result");

View file

@ -28,7 +28,7 @@ public class ServerApiCommon {
public interface EstimateFeeListener {
void onSuccess(int blockCount, String estimateFeeResponse);
void onFail(String message);
void onFail(int blockCount, String message);
}
public void setEstimateFee(EstimateFeeListener listener) {
@ -63,13 +63,13 @@ public class ServerApiCommon {
estimateFeeListener.onSuccess(blockCount, response.body());
Log.i(TAG, "estimateFee onResponse " + response.code() + " " + response.body());
} else
estimateFeeListener.onFail(response.body());
estimateFeeListener.onFail(blockCount, response.body());
Log.e(TAG, "estimateFee onResponse " + response.code());
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
estimateFeeListener.onFail(t.getMessage());
estimateFeeListener.onFail(blockCount, t.getMessage());
Log.e(TAG, "estimateFee onFailure " + t.getMessage());
}
});

View file

@ -8,6 +8,7 @@ import com.tangem.data.Blockchain;
import com.tangem.domain.wallet.bch.BitcoinCashNode;
import com.tangem.domain.wallet.btc.BitcoinNode;
import com.tangem.domain.wallet.btc.BitcoinNodeTestNet;
import com.tangem.wallet.R;
import java.io.BufferedReader;
import java.io.IOException;
@ -54,23 +55,15 @@ public class ServerApiElectrum {
private int requestsCount=0;
public boolean hasRequests() {
return requestsCount>0;
}
private String error=null;
public boolean isErrorOccured() {
return error!=null;
}
public void setErrorOccured(String error) {
this.error=error;
public boolean isRequestsSequenceCompleted() {
Log.i(TAG, String.format("isRequestsSequenceCompleted: %s (%d requests left)", String.valueOf(requestsCount <= 0), requestsCount));
return requestsCount <= 0;
}
public interface ElectrumRequestDataListener {
void onSuccess(ElectrumRequest electrumRequest);
void onFail(String method);
void onFail(ElectrumRequest electrumRequest);
}
public void setElectrumRequestData(ElectrumRequestDataListener listener) {
@ -79,6 +72,7 @@ public class ServerApiElectrum {
public void electrumRequestData(TangemContext ctx, ElectrumRequest electrumRequest) {
requestsCount++;
Log.i(TAG, String.format("New request[%d]: %s", requestsCount,electrumRequest.getMethod()));
Observable<ElectrumRequest> checkElectrumDataObserver = Observable.just(electrumRequest)
.doOnNext(electrumRequest1 -> doElectrumRequest(ctx, electrumRequest))
@ -97,33 +91,47 @@ public class ServerApiElectrum {
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
checkElectrumDataObserver.subscribe(new DefaultObserver<ElectrumRequest>() {
//TODO remove onNext
@Override
public void onNext(ElectrumRequest v) {
if (electrumRequest.answerData != null) {
requestsCount--;
electrumRequestDataListener.onSuccess(electrumRequest);
// Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onNext != null");
Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onNext != null");
} else {
electrumRequestDataListener.onFail(electrumRequest.getMethod());
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onNext == null");
}
}
@Override
public void onError(Throwable e) {
electrumRequestDataListener.onFail(electrumRequest.getMethod());
requestsCount--;
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onError " + e.getMessage());
Log.e(TAG, String.format("%d requests left in processing",requestsCount));
electrumRequest.setError(ctx.getString(R.string.cannot_obtain_data_from_blockchain));
//setErrorOccurred(e.getMessage());//;
electrumRequestDataListener.onFail(electrumRequest);
}
@Override
public void onComplete() {
// Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onComplete");
requestsCount--;
if (electrumRequest.answerData != null) {
Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onComplete, answerData!=null");
} else {
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onComplete, answerData==null");
}
Log.e(TAG, String.format("%d requests left in processing",requestsCount));
if (electrumRequest.answerData != null) {
electrumRequestDataListener.onSuccess(electrumRequest);
} else {
// if( error==null || error.isEmpty() ) setErrorOccurred(ctx.getString(R.string.cannot_obtain_data_from_blockchain));
electrumRequestDataListener.onFail(electrumRequest);
}
}
});
}
private List<ElectrumRequest> doElectrumRequest(TangemContext ctx, ElectrumRequest electrumRequest) {
private void doElectrumRequest(TangemContext ctx, ElectrumRequest electrumRequest) {
String host;
int port;
String proto;
@ -135,8 +143,7 @@ public class ServerApiElectrum {
this.host = host;
this.port = port;
return doElectrumRequestTcp(electrumRequest, host, port);
doElectrumRequestTcp(electrumRequest, host, port);
} else if (ctx.getBlockchain() == Blockchain.BitcoinCash) {
BitcoinCashNode bitcoinCashNode = BitcoinCashNode.values()[new Random().nextInt(BitcoinCashNode.values().length)];
host = bitcoinCashNode.getHost();
@ -147,9 +154,9 @@ public class ServerApiElectrum {
this.port = port;
if (proto.equals("tcp")) {
return doElectrumRequestTcp(electrumRequest, host, port);
doElectrumRequestTcp(electrumRequest, host, port);
} else {
return doElectrumRequestSsl(electrumRequest, host, port);
doElectrumRequestSsl(electrumRequest, host, port);
}
} else if (ctx.getBlockchain() == Blockchain.Bitcoin) {
@ -162,23 +169,19 @@ public class ServerApiElectrum {
this.port = port;
if (proto.equals("tcp")) {
return doElectrumRequestTcp(electrumRequest, host, port);
doElectrumRequestTcp(electrumRequest, host, port);
} else {
return doElectrumRequestSsl(electrumRequest, host, port);
doElectrumRequestSsl(electrumRequest, host, port);
}
}
return null;
}
private List<ElectrumRequest> doElectrumRequestTcp(ElectrumRequest electrumRequest, String host, int port) {
List<ElectrumRequest> result = new ArrayList<>();
Collections.addAll(result, electrumRequest);
private void doElectrumRequestTcp(ElectrumRequest electrumRequest, String host, int port) {
try {
Socket socket = App.getNetworkComponent().getSocket();
socket.setSoTimeout(3000);
Log.i(TAG, "Start process "+electrumRequest.getMethod()+" @ "+host + ":" + port);
socket.connect(new InetSocketAddress(InetAddress.getByName(host), port));
Log.i(TAG, host + " " + port);
try {
OutputStream os = socket.getOutputStream();
OutputStreamWriter out = new OutputStreamWriter(os, "UTF-8");
@ -195,37 +198,38 @@ public class ServerApiElectrum {
if (electrumRequest.answerData != null) {
Log.i(TAG, ">> " + electrumRequest.answerData);
} else {
electrumRequest.error = "No answer from server";
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_answer));
Log.i(TAG, ">> <NULL>");
}
} catch (ConnectException e) {
e.printStackTrace();
electrumRequestDataListener.onFail(e.getMessage());
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " ConnectException " + e.getMessage());
//e.printStackTrace();
//electrumRequestDataListener.onFail(e.getMessage());
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_connection));
Log.e(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " ConnectException " + e.getMessage());
} finally {
Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " CLOSE");
Log.i(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " socket.close");
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
electrumRequestDataListener.onFail(e.getMessage());
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " IOException " + e.getMessage());
//e.printStackTrace();
//electrumRequestDataListener.onFail(e.getMessage());
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
Log.e(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " IOException " + e.getMessage());
}
return result;
}
private List<ElectrumRequest> doElectrumRequestSsl(ElectrumRequest electrumRequest, String host, int port) {
private void doElectrumRequestSsl(ElectrumRequest electrumRequest, String host, int port) {
try {
// create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@ -253,8 +257,8 @@ public class ServerApiElectrum {
Collections.addAll(result, electrumRequest);
try {
sslSocket = (SSLSocket) sf.createSocket(host, port);
Log.i(TAG, host + " " + port);
sslSocket = (SSLSocket) sf.createSocket(host, port);
try {
OutputStream os = sslSocket.getOutputStream();
OutputStreamWriter out = new OutputStreamWriter(os, "UTF-8");
@ -269,30 +273,28 @@ public class ServerApiElectrum {
if (electrumRequest.answerData != null) {
Log.i(TAG, ">> " + electrumRequest.answerData);
} else {
electrumRequest.error = "No answer from server";
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_answer));
Log.i(TAG, ">> <NULL>");
}
} catch (ConnectException e) {
e.printStackTrace();
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " ConnectException " + e.getMessage());
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_connection));
Log.e(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " ConnectException " + e.getMessage());
} finally {
Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " CLOSE");
Log.i(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " socket.close");
sslSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " IOException " + e.getMessage());
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
Log.e(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " IOException " + e.getMessage());
}
return result;
} catch (NoSuchAlgorithmException | KeyManagementException e) {
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain));
Log.e(TAG, e.getMessage());
}
return null;
}
public String getValidationNodeDescription() {

View file

@ -33,17 +33,9 @@ public class ServerApiInfura {
private int requestsCount=0;
public boolean hasRequests() {
return requestsCount>0;
}
private String error=null;
public boolean isErrorOccured() {
return error!=null;
}
public void setErrorOccured(String error) {
this.error=error;
public boolean isRequestsSequenceCompleted() {
Log.i(TAG, String.format("isRequestsSequenceCompleted: %s (%d requests left)", String.valueOf(requestsCount <= 0), requestsCount));
return requestsCount <= 0;
}
private InfuraBodyListener infuraBodyListener;