Updated on 2026-08-14

This commit is contained in:
Tangem 2018-11-14 12:14:31 +03:00
commit 2af8d5dc82
78 changed files with 646 additions and 575 deletions

View file

@ -37,9 +37,9 @@ import retrofit2.http.Path;
/**
* HTTP
* Used in Cryptonit_OtherAPI service
* Used in CryptonitOtherApi service
*/
public class Cryptonit_OtherAPI {
public class CryptonitOtherApi {
private static final String SERVER_URL = "https://api.cryptonit.net/api/";
private static class Method {
@ -115,7 +115,7 @@ public class Cryptonit_OtherAPI {
private ErrorListener errorListener;
private Context context;
public Cryptonit_OtherAPI(Context context) {
public CryptonitOtherApi(Context context) {
this.context = context;
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
key = sp.getString(context.getResources().getString(R.string.key_cryptonit_key), "");

View file

@ -6,8 +6,6 @@ import android.util.Log;
import com.tangem.App;
import com.tangem.data.network.model.CardVerifyAndGetInfo;
import com.tangem.data.network.model.InfuraBody;
import com.tangem.data.network.model.InfuraResponse;
import com.tangem.data.network.model.RateInfoResponse;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.util.Util;
@ -24,8 +22,8 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ServerApiHelper {
private static String TAG = ServerApiHelper.class.getSimpleName();
public class ServerApiCommon {
private static String TAG = ServerApiCommon.class.getSimpleName();
/**
* HTTP
@ -85,84 +83,6 @@ public class ServerApiHelper {
});
}
/**
* HTTP
* Infura
* <p>
* eth_getBalance
* eth_getTransactionCount
* eth_call
* eth_sendRawTransaction
* eth_gasPrice
*/
public static final String INFURA_ETH_GET_BALANCE = "eth_getBalance";
public static final String INFURA_ETH_GET_TRANSACTION_COUNT = "eth_getTransactionCount";
public static final String INFURA_ETH_GET_PENDING_COUNT = "eth_getPendingCount";
public static final String INFURA_ETH_CALL = "eth_call";
public static final String INFURA_ETH_SEND_RAW_TRANSACTION = "eth_sendRawTransaction";
public static final String INFURA_ETH_GAS_PRICE = "eth_gasPrice";
private InfuraBodyListener infuraBodyListener;
public interface InfuraBodyListener {
void onSuccess(String method, InfuraResponse infuraResponse);
void onFail(String method, String message);
}
public void setInfuraResponse(InfuraBodyListener listener) {
infuraBodyListener = listener;
}
public void infura(String method, int id, String wallet, String contract, String tx) {
InfuraApi infuraApi = App.getNetworkComponent().getRetrofitInfura().create(InfuraApi.class);
InfuraBody infuraBody;
switch (method) {
case INFURA_ETH_GET_BALANCE:
case INFURA_ETH_GET_TRANSACTION_COUNT:
infuraBody = new InfuraBody(method, new String[]{wallet, "latest"}, id);
break;
case INFURA_ETH_GET_PENDING_COUNT:
infuraBody = new InfuraBody(INFURA_ETH_GET_TRANSACTION_COUNT, new String[]{wallet, "pending"}, id);
break;
case INFURA_ETH_CALL:
String address = wallet.substring(2);
infuraBody = new InfuraBody(method, new Object[]{new InfuraBody.EthCallParams("0x70a08231000000000000000000000000" + address, contract), "latest"}, id);
break;
case INFURA_ETH_SEND_RAW_TRANSACTION:
infuraBody = new InfuraBody(method, new String[]{tx}, id);
break;
case INFURA_ETH_GAS_PRICE:
infuraBody = new InfuraBody(method, id);
break;
default:
infuraBody = new InfuraBody();
}
Call<InfuraResponse> call = infuraApi.infura(infuraBody);
call.enqueue(new Callback<InfuraResponse>() {
@Override
public void onResponse(@NonNull Call<InfuraResponse> call, @NonNull Response<InfuraResponse> response) {
if (response.code() == 200) {
infuraBodyListener.onSuccess(method, response.body());
Log.i(TAG, "infura " + method + " onResponse " + response.code());
} else {
infuraBodyListener.onFail(method, String.valueOf(response.code()));
Log.e(TAG, "infura " + method + " onResponse " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<InfuraResponse> call, @NonNull Throwable t) {
infuraBodyListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "infura " + method + " onFailure " + t.getMessage());
}
});
}
/**
* HTTP
* Card verify

View file

@ -3,9 +3,10 @@ package com.tangem.data.network;
import android.util.Log;
import com.tangem.App;
import com.tangem.domain.BitcoinNode;
import com.tangem.domain.BitcoinNodeTestNet;
import com.tangem.domain.BitcoinCashNode;
import com.tangem.domain.wallet.btc.BitcoinNode;
import com.tangem.domain.wallet.btc.BitcoinNodeSsl;
import com.tangem.domain.wallet.btc.BitcoinNodeTestNet;
import com.tangem.domain.wallet.bch.BitcoinCashNode;
import com.tangem.domain.wallet.Blockchain;
import com.tangem.domain.wallet.TangemCard;
@ -27,8 +28,6 @@ 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;
@ -38,9 +37,8 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DefaultObserver;
import io.reactivex.schedulers.Schedulers;
public class ServerApiHelperElectrum {
// private static String TAG = ServerApiHelper.class.getSimpleName();
private static String TAG = ServerApiHelperElectrum.class.getSimpleName();
public class ServerApiElectrum {
private static String TAG = ServerApiElectrum.class.getSimpleName();
/**
* TCP
@ -108,6 +106,11 @@ public class ServerApiHelperElectrum {
}
private List<ElectrumRequest> testSslSocket(TangemCard card, ElectrumRequest electrumRequest) {
BitcoinNodeSsl bitcoinNodeSsl = BitcoinNodeSsl.values()[new Random().nextInt(BitcoinNodeSsl.values().length)];
this.host = bitcoinNodeSsl.getHost();
this.port = bitcoinNodeSsl.getPort();
SocketFactory sf = SSLSocketFactory.getDefault();
SSLSocket socket;
@ -115,8 +118,9 @@ public class ServerApiHelperElectrum {
Collections.addAll(result, electrumRequest);
try {
// socket = (SSLSocket) sf.createSocket("gmail.com", 443);
socket = (SSLSocket) sf.createSocket("electrum.hsmiths.com", 50002);
socket = (SSLSocket) sf.createSocket("gmail.com", 443);
// socket = (SSLSocket) sf.createSocket("electrum.hsmiths.com", 50002);
// socket = (SSLSocket) sf.createSocket(host, port);
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
SSLSession s = socket.getSession();
@ -124,7 +128,7 @@ public class ServerApiHelperElectrum {
// throw new SSLHandshakeException("Expected mail.google.com, found " + s.getPeerPrincipal());
// }
Log.i(TAG, host + " " + port);
try {
OutputStream os = socket.getOutputStream();
OutputStreamWriter out = new OutputStreamWriter(os, "UTF-8");

View file

@ -0,0 +1,96 @@
package com.tangem.data.network;
import android.support.annotation.NonNull;
import android.util.Log;
import com.tangem.App;
import com.tangem.data.network.model.InfuraBody;
import com.tangem.data.network.model.InfuraResponse;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ServerApiInfura {
private static String TAG = ServerApiInfura.class.getSimpleName();
/**
* HTTP
* Infura
* <p>
* eth_getBalance
* eth_getTransactionCount
* eth_call
* eth_sendRawTransaction
* eth_gasPrice
*/
public static final String INFURA_ETH_GET_BALANCE = "eth_getBalance";
public static final String INFURA_ETH_GET_TRANSACTION_COUNT = "eth_getTransactionCount";
public static final String INFURA_ETH_GET_PENDING_COUNT = "eth_getPendingCount";
public static final String INFURA_ETH_CALL = "eth_call";
public static final String INFURA_ETH_SEND_RAW_TRANSACTION = "eth_sendRawTransaction";
public static final String INFURA_ETH_GAS_PRICE = "eth_gasPrice";
private InfuraBodyListener infuraBodyListener;
public interface InfuraBodyListener {
void onSuccess(String method, InfuraResponse infuraResponse);
void onFail(String method, String message);
}
public void setInfuraResponse(InfuraBodyListener listener) {
infuraBodyListener = listener;
}
public void infura(String method, int id, String wallet, String contract, String tx) {
InfuraApi infuraApi = App.getNetworkComponent().getRetrofitInfura().create(InfuraApi.class);
InfuraBody infuraBody;
switch (method) {
case INFURA_ETH_GET_BALANCE:
case INFURA_ETH_GET_TRANSACTION_COUNT:
infuraBody = new InfuraBody(method, new String[]{wallet, "latest"}, id);
break;
case INFURA_ETH_GET_PENDING_COUNT:
infuraBody = new InfuraBody(INFURA_ETH_GET_TRANSACTION_COUNT, new String[]{wallet, "pending"}, id);
break;
case INFURA_ETH_CALL:
String address = wallet.substring(2);
infuraBody = new InfuraBody(method, new Object[]{new InfuraBody.EthCallParams("0x70a08231000000000000000000000000" + address, contract), "latest"}, id);
break;
case INFURA_ETH_SEND_RAW_TRANSACTION:
infuraBody = new InfuraBody(method, new String[]{tx}, id);
break;
case INFURA_ETH_GAS_PRICE:
infuraBody = new InfuraBody(method, id);
break;
default:
infuraBody = new InfuraBody();
}
Call<InfuraResponse> call = infuraApi.infura(infuraBody);
call.enqueue(new Callback<InfuraResponse>() {
@Override
public void onResponse(@NonNull Call<InfuraResponse> call, @NonNull Response<InfuraResponse> response) {
if (response.code() == 200) {
infuraBodyListener.onSuccess(method, response.body());
Log.i(TAG, "infura " + method + " onResponse " + response.code());
} else {
infuraBodyListener.onFail(method, String.valueOf(response.code()));
Log.e(TAG, "infura " + method + " onResponse " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<InfuraResponse> call, @NonNull Throwable t) {
infuraBodyListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "infura " + method + " onFailure " + t.getMessage());
}
});
}
}

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dmmatrix.epro.core.exception
package com.tangem.data.network.exception
/**
* Base Class for handling errors/failures/exceptions.

View file

@ -1,197 +0,0 @@
package com.tangem.data.network.task.request_pin;
import android.annotation.TargetApi;
import android.hardware.fingerprint.FingerprintManager;
import android.os.AsyncTask;
import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import com.tangem.domain.wallet.FingerprintHelper;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.presentation.activity.PinRequestActivity;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
private WeakReference<PinRequestActivity> reference;
private KeyStore keyStore;
private Cipher cipher;
private FingerprintManager.CryptoObject cryptoObject;
FingerprintManager fingerprintManager;
FingerprintHelper fingerprintHelper;
PinRequestActivity activity;
public StartFingerprintReaderTask(PinRequestActivity activity, FingerprintManager fingerprintManager, FingerprintHelper fingerprintHelper) {
reference = new WeakReference<>(activity);
this.fingerprintManager = fingerprintManager;
this.fingerprintHelper = fingerprintHelper;
this.activity = activity;
}
@Override
protected Boolean doInBackground(Void... params) {
if (!getKeyStore())
return false;
if (!createNewKey(false))
return false;
if (!getCipher())
return false;
if (!initCipher(Cipher.DECRYPT_MODE))
return false;
return initCryptObject();
}
@Override
protected void onPostExecute(final Boolean success) {
PinRequestActivity pinRequestActivity = reference.get();
onCancelled();
if (!success) {
pinRequestActivity.doLog("Authentication failed!");
} else {
fingerprintHelper.startAuth(fingerprintManager, cryptoObject);
pinRequestActivity.doLog("Authenticate using fingerprint!");
}
}
@Override
protected void onCancelled() {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.setStartFingerprintReaderTask(null);
}
private boolean getKeyStore() {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Getting keystore...");
try {
keyStore = KeyStore.getInstance(PinRequestActivity.KEYSTORE);
keyStore.load(null); // Create empty keystore
return true;
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
}
return false;
}
@TargetApi(Build.VERSION_CODES.M)
public boolean createNewKey(boolean forceCreate) {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Creating new key...");
try {
if (forceCreate)
keyStore.deleteEntry(PinRequestActivity.KEY_ALIAS);
if (!keyStore.containsAlias(PinRequestActivity.KEY_ALIAS)) {
KeyGenerator generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, PinRequestActivity.KEYSTORE);
generator.init(new KeyGenParameterSpec.Builder(PinRequestActivity.KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setUserAuthenticationRequired(true)
.build()
);
generator.generateKey();
pinRequestActivity.doLog("Key created.");
} else
pinRequestActivity.doLog("Key exists.");
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private boolean getCipher() {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Getting cipher...");
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
return true;
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
return false;
}
@TargetApi(Build.VERSION_CODES.M)
private boolean initCipher(int mode) {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Initializing cipher...");
try {
keyStore.load(null);
SecretKey keyspec = (SecretKey) keyStore.getKey(PinRequestActivity.KEY_ALIAS, null);
if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(mode, keyspec);
} else {
byte[] iv = null;
if (pinRequestActivity.getMode() == PinRequestActivity.Mode.RequestPIN || activity.getMode() == PinRequestActivity.Mode.RequestNewPIN || activity.getMode() == PinRequestActivity.Mode.ConfirmNewPIN) {
iv = PINStorage.loadEncryptedIV();
} else if (activity.getMode() == PinRequestActivity.Mode.RequestPIN2 || activity.getMode() == PinRequestActivity.Mode.RequestNewPIN2 || activity.getMode() == PinRequestActivity.Mode.ConfirmNewPIN2) {
iv = PINStorage.loadEncryptedIV2();
}
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.init(mode, keyspec, ivspec);
}
return true;
} catch (KeyPermanentlyInvalidatedException e) {
e.printStackTrace();
createNewKey(true); // Retry after clearing entry
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
@TargetApi(Build.VERSION_CODES.M)
private boolean initCryptObject() {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Initializing crypt object...");
try {
cryptoObject = new FingerprintManager.CryptoObject(cipher);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}

View file

@ -1,62 +0,0 @@
package com.tangem.data.network.task.save_pin;
import android.os.AsyncTask;
import android.widget.Toast;
import com.tangem.domain.wallet.FingerprintHelper;
import com.tangem.presentation.activity.PinSaveActivity;
import com.tangem.wallet.R;
import java.lang.ref.WeakReference;
import javax.crypto.Cipher;
public class ConfirmWithFingerprintTask extends AsyncTask<Void, Void, Boolean> {
private WeakReference<PinSaveActivity> reference;
public ConfirmWithFingerprintTask(PinSaveActivity context) {
reference = new WeakReference<>(context);
reference.get().setFingerprintHelper(new FingerprintHelper(reference.get()));
}
@Override
protected Boolean doInBackground(Void... params) {
PinSaveActivity pinSaveActivity = reference.get();
if (!pinSaveActivity.getKeyStore())
return false;
if (!pinSaveActivity.createNewKey(false))
return false;
if (!pinSaveActivity.getCipher())
return false;
return pinSaveActivity.initCipher(Cipher.ENCRYPT_MODE) && pinSaveActivity.initCryptObject();
}
@Override
protected void onPostExecute(final Boolean success) {
PinSaveActivity pinSaveActivity = reference.get();
onCancelled();
if (!success) {
Toast.makeText(pinSaveActivity, R.string.pin_save_fail, Toast.LENGTH_LONG).show();
} else {
pinSaveActivity.getFingerprintHelper().startAuth(pinSaveActivity.getFingerprintManager(), pinSaveActivity.getCryptoObject());
}
}
@Override
protected void onCancelled() {
PinSaveActivity pinSaveActivity = reference.get();
if (pinSaveActivity.getDFingerPrintConfirmation() != null) {
pinSaveActivity.getDFingerPrintConfirmation().cancel();
}
}
}