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

@ -3,7 +3,9 @@ package com.tangem;
import android.app.Application;
import android.support.v7.app.AppCompatDelegate;
import com.tangem.di.DaggerNavigatorComponent;
import com.tangem.di.DaggerNetworkComponent;
import com.tangem.di.NavigatorComponent;
import com.tangem.di.NetworkComponent;
public class App extends Application {
@ -22,6 +24,11 @@ public class App extends Application {
}
private static NetworkComponent networkComponent;
private static NavigatorComponent navigatorComponent;
public static NavigatorComponent getNavigatorComponent() {
return navigatorComponent;
}
@Override
public void onCreate() {
@ -30,6 +37,7 @@ public class App extends Application {
sInstance = this;
networkComponent = DaggerNetworkComponent.create();
navigatorComponent = buildNavigatorComponent();
}
/**
@ -43,4 +51,9 @@ public class App extends Application {
return networkComponent;
}
protected NavigatorComponent buildNavigatorComponent() {
return DaggerNavigatorComponent.builder()
.build();
}
}

View file

@ -46,7 +46,7 @@ public class LogFileProvider extends ContentProvider {
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
String LOG_TAG = CLASS_NAME+"-oF";
String LOG_TAG = CLASS_NAME + "-oF";
Log.v(LOG_TAG,
"Called with uri: '" + uri + "'." + uri.getLastPathSegment());

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet;
package com.tangem.data;
import android.content.Context;
import android.util.Log;

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet
package com.tangem.data.db
import android.annotation.SuppressLint
import android.content.Context
@ -12,6 +12,7 @@ import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import com.tangem.data.network.model.CardVerifyAndGetInfo
import com.tangem.domain.cardReader.CardCrypto
import com.tangem.domain.wallet.TangemCard
import com.tangem.util.Util
import com.tangem.wallet.R
import java.io.InputStream

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet;
package com.tangem.data.db;
import android.content.Context;
import android.content.SharedPreferences;
@ -66,7 +66,7 @@ public class PINStorage {
public static void deletePIN() {
SharedPreferences.Editor editor = sharedPreferences.edit();
if (mSavedPIN != null && mLastUsedPIN != null && mSavedPIN.equals(mLastUsedPIN)) {
if (mSavedPIN != null && mSavedPIN.equals(mLastUsedPIN)) {
mLastUsedPIN = null;
}
mSavedPIN = null;
@ -118,7 +118,7 @@ public class PINStorage {
}
public static void deleteEncryptedPIN() {
if (mEncryptedPIN != null && mLastUsedPIN != null && mEncryptedPIN.equals(mLastUsedPIN)) {
if (mEncryptedPIN != null && mEncryptedPIN.equals(mLastUsedPIN)) {
mLastUsedPIN = null;
}
mEncryptedPIN = null;
@ -149,13 +149,11 @@ public class PINStorage {
public static byte[] loadEncryptedIV2() {
String sIV = sharedPreferences.getString("EncryptedIV2", "");
// Log.d("PINStorage", String.format("loadEncryptedIV: %s",sIV));
return Base64.decode(sIV, Base64.NO_WRAP);
}
public static String loadEncryptedPIN2(Cipher cipher) {
String encryptedPIN = sharedPreferences.getString("EncryptedPIN2", null);
try {
byte[] bytes = Base64.decode(encryptedPIN, Base64.NO_WRAP);
mPIN2 = new String(cipher.doFinal(bytes));
@ -184,11 +182,11 @@ public class PINStorage {
}
public static boolean isDefaultPIN(String pin) {
return (pin != null) && (CardProtocol.DefaultPIN.equals(pin));
return (CardProtocol.DefaultPIN.equals(pin));
}
public static boolean isDefaultPIN2(String pin2) {
return (pin2 != null) && (CardProtocol.DefaultPIN2.equals(pin2));
return (CardProtocol.DefaultPIN2.equals(pin2));
}
public static String getDefaultPIN() {

View file

@ -1,9 +1,8 @@
package com.tangem.data.network.task.save_pin;
package com.tangem.data.fingerprint;
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;

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet;
package com.tangem.data.fingerprint;
import android.annotation.TargetApi;
import android.hardware.fingerprint.FingerprintManager;

View file

@ -1,4 +1,4 @@
package com.tangem.data.network.task.request_pin;
package com.tangem.data.fingerprint;
import android.annotation.TargetApi;
import android.hardware.fingerprint.FingerprintManager;
@ -8,8 +8,7 @@ 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.data.db.PINStorage;
import com.tangem.presentation.activity.PinRequestActivity;
import java.io.IOException;

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

@ -6,7 +6,7 @@ import android.util.Log;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.NfcManager;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.wallet.TangemCard;
public class CreateNewWalletTask extends Thread {

View file

@ -1,7 +1,6 @@
package com.tangem.domain.wallet
package com.tangem.data.nfc
import android.os.Build
import com.tangem.data.NFCLocation
class DeviceNFCAntennaLocation {
companion object {

View file

@ -1,4 +1,4 @@
package com.tangem.data
package com.tangem.data.nfc
enum class NFCLocation(val codename: String, val fullName: String, val orientation: Int, val x: Int, val y: Int, val z: Int) {
model1("sailfish", "Google Pixel", 0, 65, 25, 0),

View file

@ -6,7 +6,7 @@ import android.util.Log;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.NfcManager;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.wallet.TangemCard;
public class PurgeTask extends Thread {

View file

@ -6,7 +6,7 @@ import android.util.Log;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.NfcManager;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.util.Util;

View file

@ -13,7 +13,7 @@ import com.tangem.domain.wallet.CoinEngineFactory;
import com.tangem.domain.wallet.TangemContext;
import com.tangem.presentation.activity.SendTransactionActivity;
import com.tangem.presentation.activity.SignPaymentActivity;
import com.tangem.util.BTCUtils;
import com.tangem.domain.wallet.BTCUtils;
import java.io.IOException;
@ -86,7 +86,7 @@ public class SignPaymentTask extends Thread {
// SignBTC_TX(protocol);
// }
CoinEngine engine = CoinEngineFactory.create(mCtx);
CoinEngine engine = CoinEngineFactory.INSTANCE.create(mCtx);
if (engine != null) {
if (mCtx.getCard().getPauseBeforePIN2() > 0) {
mNotifications.onReadWait(mCtx.getCard().getPauseBeforePIN2());

View file

@ -6,7 +6,7 @@ import android.util.Log;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.NfcManager;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.wallet.TangemCard;
public class SwapPINTask extends Thread {

View file

@ -7,7 +7,7 @@ import android.util.Log;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.FW;
import com.tangem.domain.cardReader.NfcManager;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.wallet.TangemCard;
import java.util.Arrays;

View file

@ -0,0 +1,21 @@
package com.tangem.di;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
import javax.inject.Singleton;
@Singleton
public class AppModule {
private Context appContext;
public AppModule(@NotNull Context context) {
appContext = context;
}
Context provideContext() {
return appContext;
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.di;
import android.content.Context;
import com.tangem.presentation.activity.MainActivity;
public class Navigator {
public void showMain(Context context) {
context.startActivity(MainActivity.Companion.callingIntent(context));
}
}

View file

@ -0,0 +1,20 @@
package com.tangem.di;
import com.tangem.presentation.activity.LogoActivity;
import com.tangem.presentation.activity.MainActivity;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
// AppModule.class,
NavigatorModule.class})
public interface NavigatorComponent {
void inject(LogoActivity activity);
void inject(MainActivity activity);
}

View file

@ -0,0 +1,17 @@
package com.tangem.di;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
class NavigatorModule {
@Singleton
@Provides
Navigator provideNavigator() {
return new Navigator();
}
}

View file

@ -9,7 +9,7 @@ import android.util.Log;
import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.CoinEngineFactory;
import com.tangem.domain.wallet.Issuer;
import com.tangem.domain.wallet.LocalStorage;
import com.tangem.data.db.LocalStorage;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.domain.wallet.Manufacturer;
import com.tangem.domain.wallet.TangemContext;
@ -587,7 +587,7 @@ public class CardProtocol {
TangemContext ctx = new TangemContext(mCard);
try {
CoinEngine engineCoin = CoinEngineFactory.create(ctx);
CoinEngine engineCoin = CoinEngineFactory.INSTANCE.create(ctx);
if( engineCoin==null ) throw new Exception("Can't create CoinEngine!");
String wallet = engineCoin.calculateAddress(pkUncompressed);
mCard.setWallet(wallet);

View file

@ -1,4 +1,4 @@
package com.tangem.util;
package com.tangem.domain.wallet;
/**
* Created by Ilia on 29.09.2017.
@ -6,12 +6,12 @@ package com.tangem.util;
import android.util.Log;
import com.tangem.domain.wallet.Base58;
import com.tangem.domain.wallet.BitcoinException;
import com.tangem.domain.wallet.BitcoinOutputStream;
import com.tangem.domain.wallet.BtcData;
import com.tangem.domain.wallet.Transaction;
import com.tangem.domain.wallet.UnspentOutputInfo;
import com.tangem.domain.wallet.btc.BitcoinException;
import com.tangem.domain.wallet.btc.BitcoinOutputStream;
import com.tangem.domain.wallet.btc.BtcData;
import com.tangem.util.CryptoUtil;
import com.tangem.util.FormatUtil;
import com.tangem.util.Util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -81,34 +81,30 @@ public final class BTCUtils {
forSign.writeInt32(0x01);//write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version
//01
byte inputCount = (byte)unspentOutputs.size();
byte inputCount = (byte) unspentOutputs.size();
forSign.write(inputCount); // input count
//hex str hash prev btc
for(int i = 0; i < inputCount; ++i)
{
for (int i = 0; i < inputCount; ++i) {
UnspentOutputInfo outPut = unspentOutputs.get(i);
int outputIndex = outPut.outputIndex;
byte[] txHash = BTCUtils.reverse(Util.hexToBytes(outPut.txHashForBuild));//Sha256Hash.hash(rawTxByte);
forSign.write(txHash);
forSign.writeInt32(outputIndex); //output index in prev tx
if(inputPos ==-1 || i == inputPos)
{
if (inputPos == -1 || i == inputPos) {
// hex str 1976a914....88ac
forSign.write((byte)outPut.scriptForBuild.length);
forSign.write((byte) outPut.scriptForBuild.length);
forSign.write(outPut.scriptForBuild);
}
else
{
} else {
forSign.write(0x00);
}
//ffffffff
forSign.write(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); // sequence
forSign.write(new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}); // sequence
}
//02
byte outputCount = (byte)((change==0) ? 1 : 2); // outputCount
byte outputCount = (byte) ((change == 0) ? 1 : 2); // outputCount
forSign.write(outputCount);
//8 bytes
@ -116,15 +112,15 @@ public final class BTCUtils {
forSign.writeInt64(amount); //amount
byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out
//hex str 1976a914....88ac
forSign.write((byte)sendScript.length);
forSign.write((byte) sendScript.length);
forSign.write(sendScript);
if(change!=0){
if (change != 0) {
//8 bytes
forSign.writeInt64(change); // change
//hex str 1976a914....88ac
byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out
forSign.write((byte)chancheScript.length);
forSign.write((byte) chancheScript.length);
forSign.write(chancheScript);
}
@ -160,14 +156,14 @@ public final class BTCUtils {
//forSign.write(0x00);
// hex str 1976a914....88ac
forSign.write((byte)script.length);
forSign.write((byte) script.length);
forSign.write(script);
//ffffffff
forSign.write(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); // sequence
forSign.write(new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}); // sequence
//02
byte outputCount = (byte)((change==0) ? 1 : 2); // outputCount
byte outputCount = (byte) ((change == 0) ? 1 : 2); // outputCount
forSign.write(outputCount);
//8 bytes
@ -175,15 +171,15 @@ public final class BTCUtils {
forSign.writeInt64(amount); //amount
byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out
//hex str 1976a914....88ac
forSign.write((byte)sendScript.length);
forSign.write((byte) sendScript.length);
forSign.write(sendScript);
if(change!=0){
if (change != 0) {
//8 bytes
forSign.writeInt64(change); // change
//hex str 1976a914....88ac
byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out
forSign.write((byte)chancheScript.length);
forSign.write((byte) chancheScript.length);
forSign.write(chancheScript);
}
@ -200,17 +196,15 @@ public final class BTCUtils {
public static ArrayList<UnspentOutputInfo> getOutputs(List<BtcData.UnspentTransaction> rawTxList, byte[] outputScriptWeAreAbleToSpend) throws BitcoinException {
ArrayList<UnspentOutputInfo> unspentOutputs = new ArrayList<>();
for(BtcData.UnspentTransaction current: rawTxList)
{
for (BtcData.UnspentTransaction current : rawTxList) {
byte[] rawTxByte = BTCUtils.fromHex(current.Raw);
if (rawTxByte == null || current.Raw.isEmpty())
{
if (rawTxByte == null || current.Raw.isEmpty()) {
continue;
}
Transaction baseTx = new Transaction(rawTxByte);
if(baseTx.inputs.length == 0 || baseTx.outputs.length == 0)
if (baseTx.inputs.length == 0 || baseTx.outputs.length == 0)
throw new IllegalArgumentException("Unable to decode given transaction");
byte[] txHash = BTCUtils.reverse(CryptoUtil.doubleSha256(rawTxByte));

View file

@ -2,8 +2,6 @@ package com.tangem.domain.wallet;
import com.tangem.wallet.R;
import java.math.BigInteger;
public class BalanceValidator {
private String firstLine;
private String secondLine;
@ -14,7 +12,7 @@ public class BalanceValidator {
}
public void setFirstLine(String value) {
firstLine=value;
firstLine = value;
}
public String getSecondLine(Boolean recommend) {
@ -31,7 +29,7 @@ public class BalanceValidator {
}
public void setSecondLine(String value) {
secondLine=value;
secondLine = value;
}
public void setScore(int score) {
@ -53,10 +51,10 @@ public class BalanceValidator {
public void Check(TangemContext ctx, Boolean attest) {
firstLine = "Verification failed";
secondLine = "";
TangemCard card=ctx.getCard();
CoinEngine engine=CoinEngineFactory.create(ctx);
TangemCard card = ctx.getCard();
CoinEngine engine = CoinEngineFactory.INSTANCE.create(ctx);
if( !engine.validateBalance(this) ) return;
if (!engine.validateBalance(this)) return;
// Verify card?
if (attest) {
@ -97,6 +95,6 @@ public class BalanceValidator {
secondLine += "Card identity was not verified. Cannot reach Tangem attestation service. ";
}
}
}
}
}

View file

@ -63,7 +63,7 @@ public abstract class CoinData {
}
public static CoinData fromBundle(Blockchain blockchain, Bundle bundle) {
CoinEngine engine=CoinEngineFactory.create(blockchain);
CoinEngine engine= CoinEngineFactory.INSTANCE.create(blockchain);
if( engine==null ) return null;
CoinData result = engine.createCoinData();
result.loadFromBundle(bundle);

View file

@ -1,52 +0,0 @@
package com.tangem.domain.wallet;
import android.util.Log;
import com.tangem.domain.wallet.BitcoinCash.BtcCashEngine;
/**
* Created by Ilia on 15.02.2018.
*/
public class CoinEngineFactory {
public static CoinEngine create(Blockchain blockchain) {
switch (blockchain) {
case Bitcoin:
case BitcoinTestNet:
return new BtcEngine();
case BitcoinCash:
return new BtcCashEngine();
case Ethereum:
case EthereumTestNet:
return new EthEngine();
case Token:
return new TokenEngine();
default:
return null;
}
}
public static CoinEngine create(TangemContext context) {
CoinEngine result;
try {
if (Blockchain.BitcoinCash == context.getBlockchain()) {
result = new BtcCashEngine(context);
} else if (Blockchain.Bitcoin == context.getBlockchain() || Blockchain.BitcoinTestNet == context.getBlockchain()) {
result = new BtcEngine(context);
} else if (Blockchain.Ethereum == context.getBlockchain() || Blockchain.EthereumTestNet == context.getBlockchain()) {
result = new EthEngine(context);
} else if (Blockchain.Token == context.getBlockchain()) {
result = new TokenEngine(context);
} else {
return null;
}
}
catch (Exception e)
{
e.printStackTrace();
Log.e("CoinEngineFactory","Can't create CoinEngine!");
result=null;
}
return result;
}
}

View file

@ -0,0 +1,52 @@
package com.tangem.domain.wallet
import android.util.Log
import com.tangem.domain.wallet.btc.BtcEngine
import com.tangem.domain.wallet.eth.EthEngine
import com.tangem.domain.wallet.token.TokenEngine
import com.tangem.domain.wallet.bch.BtcCashEngine
/**
* Factory for create specific engine
*
* @param Blockchain
* @param TangemContext
*
*/
object CoinEngineFactory {
private val TAG = CoinEngineFactory::class.java.simpleName
fun create(blockchain: Blockchain): CoinEngine? {
return when (blockchain) {
Blockchain.Bitcoin, Blockchain.BitcoinTestNet -> BtcEngine()
Blockchain.BitcoinCash -> BtcCashEngine()
Blockchain.Ethereum, Blockchain.EthereumTestNet -> EthEngine()
Blockchain.Token -> TokenEngine()
else -> null
}
}
fun create(context: TangemContext): CoinEngine? {
var result: CoinEngine?
try {
result = if (Blockchain.BitcoinCash == context.blockchain)
BtcCashEngine(context)
else if (Blockchain.Bitcoin == context.blockchain || Blockchain.BitcoinTestNet == context.blockchain)
BtcEngine(context)
else if (Blockchain.Ethereum == context.blockchain || Blockchain.EthereumTestNet == context.blockchain)
EthEngine(context)
else if (Blockchain.Token == context.blockchain)
TokenEngine(context)
else
return null
} catch (e: Exception) {
e.printStackTrace()
result = null
Log.e(TAG, "Can't create CoinEngine!")
}
return result
}
}

View file

@ -2,7 +2,6 @@ package com.tangem.domain.wallet;
import android.util.Log;
import com.tangem.util.BTCUtils;
import com.tangem.util.ByteUtil;
import com.tangem.util.CryptoUtil;

View file

@ -1,7 +1,5 @@
package com.tangem.domain.wallet;
import com.tangem.util.BTCUtils;
import java.util.ArrayList;
/**

View file

@ -4,6 +4,7 @@ import android.os.Bundle;
import android.util.Log;
import com.google.common.base.Strings;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.cardReader.SettingsMask;
import com.tangem.util.Util;
@ -250,7 +251,7 @@ public class TangemCard {
return contractAddress;
}
String tokenSymbol = "";
public String tokenSymbol = "";
public void setTokenSymbol(String symbol) {
tokenSymbol = symbol;
@ -598,7 +599,7 @@ public class TangemCard {
public void setDenomination(byte[] denomination) {
this.Denomination = denomination;
try {
CoinEngine engine=CoinEngineFactory.create(getBlockchain());
CoinEngine engine= CoinEngineFactory.INSTANCE.create(getBlockchain());
CoinEngine.InternalAmount internalAmount=engine.convertToInternalAmount(denomination);
CoinEngine.Amount amount=engine.convertToAmount(internalAmount);
this.DenominationText = amount.toString();

View file

@ -90,7 +90,7 @@ public class TangemContext {
if (bundle.containsKey(EXTRA_BLOCKCHAIN_DATA)) {
tangemContext.coinData = CoinData.fromBundle(tangemContext.getBlockchain(), bundle.getBundle(EXTRA_BLOCKCHAIN_DATA));
} else {
tangemContext.coinData = CoinEngineFactory.create(tangemContext).createCoinData();
tangemContext.coinData = CoinEngineFactory.INSTANCE.create(tangemContext).createCoinData();
}
}
tangemContext.error = bundle.getString("Error");

View file

@ -4,7 +4,9 @@ package com.tangem.domain.wallet;
* Created by Ilia on 29.09.2017.
*/
import com.tangem.util.BTCUtils;
import com.tangem.domain.wallet.btc.BitcoinException;
import com.tangem.domain.wallet.btc.BitcoinInputStream;
import com.tangem.domain.wallet.btc.BitcoinOutputStream;
import com.tangem.util.CryptoUtil;
import java.io.ByteArrayOutputStream;

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet.BitcoinCash;
package com.tangem.domain.wallet.bch;
// Helper class for CashAddr

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet.BitcoinCash;
package com.tangem.domain.wallet.bch;
/**

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet.BitcoinCash;
package com.tangem.domain.wallet.bch;
import java.util.HashMap;
import java.util.Map;

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet.BitcoinCash;
package com.tangem.domain.wallet.bch;
/**
* Copyright (c) 2018 Tobias Brandt
*

View file

@ -1,4 +1,4 @@
package com.tangem.domain
package com.tangem.domain.wallet.bch
enum class BitcoinCashNode(val host: String, val port: Int) {
n1("electrumx-bch.cryptonermal.net", 50001),

View file

@ -1,23 +1,22 @@
package com.tangem.domain.wallet.BitcoinCash;
package com.tangem.domain.wallet.bch;
import android.net.Uri;
import android.text.InputFilter;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.TLV;
import com.tangem.domain.wallet.BalanceValidator;
import com.tangem.domain.wallet.Base58;
import com.tangem.domain.wallet.Blockchain;
import com.tangem.domain.wallet.BtcData;
import com.tangem.domain.wallet.CoinEngineFactory;
import com.tangem.domain.wallet.btc.BtcData;
import com.tangem.domain.wallet.CoinData;
import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.CoinEngineFactory;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.domain.wallet.TangemContext;
import com.tangem.domain.wallet.Transaction;
import com.tangem.domain.wallet.UnspentOutputInfo;
import com.tangem.util.BTCUtils;
import com.tangem.domain.wallet.BTCUtils;
import com.tangem.util.CryptoUtil;
import com.tangem.util.DecimalDigitsInputFilter;
import com.tangem.util.DerEncodingUtil;
@ -34,10 +33,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by Ilia on 15.02.2018.
*/
public class BtcCashEngine extends CoinEngine {
public BtcData coinData = null;
@ -443,7 +438,7 @@ public class BtcCashEngine extends CoinEngine {
checkBlockchainDataExists();
CoinEngine engine = CoinEngineFactory.create(ctx);
CoinEngine engine = CoinEngineFactory.INSTANCE.create(ctx);
String srcLegacyAddress = ((BtcCashEngine)engine).convertToLegacyAddress(ctx.getCard().getWallet());
String destLegacyAddress = ((BtcCashEngine)engine).convertToLegacyAddress(destAddress);

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet.BitcoinCash;
package com.tangem.domain.wallet.bch;
import java.math.BigInteger;
import java.util.Arrays;

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.btc;
/**
* Created by Ilia on 29.09.2017.

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.btc;
/**
* Created by Ilia on 29.09.2017.

View file

@ -1,4 +1,4 @@
package com.tangem.domain
package com.tangem.domain.wallet.btc
enum class BitcoinNode(val host: String, val port: Int) {
n1("electrum.anduck.net", 50001),

View file

@ -0,0 +1,7 @@
package com.tangem.domain.wallet.btc
enum class BitcoinNodeSsl(val host: String, val port: Int) {
n1("electrum.anduck.net", 50012),
n2("electrum.eff.ro", 50002),
n3("vps.hsmiths.com", 50002)
}

View file

@ -1,4 +1,4 @@
package com.tangem.domain
package com.tangem.domain.wallet.btc
enum class BitcoinNodeTestNet(val host: String, val port: Int) {
n1("testnetnode.arihanc.com", 51001),

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.btc;
/**
* Created by Ilia on 29.09.2017.

View file

@ -1,8 +1,11 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.btc;
import android.os.Bundle;
import android.util.Log;
import com.tangem.domain.wallet.CoinData;
import com.tangem.domain.wallet.CoinEngine;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

View file

@ -1,11 +1,21 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.btc;
import android.net.Uri;
import android.text.InputFilter;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.TLV;
import com.tangem.util.BTCUtils;
import com.tangem.domain.wallet.BalanceValidator;
import com.tangem.domain.wallet.Base58;
import com.tangem.domain.wallet.Blockchain;
import com.tangem.domain.wallet.CoinData;
import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.domain.wallet.TangemContext;
import com.tangem.domain.wallet.Transaction;
import com.tangem.domain.wallet.UnspentOutputInfo;
import com.tangem.domain.wallet.BTCUtils;
import com.tangem.util.CryptoUtil;
import com.tangem.util.DecimalDigitsInputFilter;
import com.tangem.util.DerEncodingUtil;
@ -52,17 +62,17 @@ public class BtcEngine extends CoinEngine {
}
@Override
public boolean awaitingConfirmation(){
if( coinData ==null ) return false;
public boolean awaitingConfirmation() {
if (coinData == null) return false;
return coinData.getBalanceUnconfirmed() != 0;
}
@Override
public String getBalanceHTML() {
Amount balance=getBalance();
if( balance!=null ) {
Amount balance = getBalance();
if (balance != null) {
return balance.toDescriptionString(getDecimals());
}else{
} else {
return "";
}
}
@ -74,21 +84,21 @@ public class BtcEngine extends CoinEngine {
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if( coinData ==null ) return false;
if (coinData == null) return false;
if (coinData.getBalanceInInternalUnits() == null) return false;
return coinData.getBalanceInInternalUnits().notZero();
}
@Override
public boolean hasBalanceInfo(){
if( coinData ==null ) return false;
public boolean hasBalanceInfo() {
if (coinData == null) return false;
return coinData.hasBalanceInfo();
}
@ -183,12 +193,12 @@ public class BtcEngine extends CoinEngine {
@Override
public InputFilter[] getAmountInputFilters() {
return new InputFilter[] { new DecimalDigitsInputFilter(getDecimals()) };
return new InputFilter[]{new DecimalDigitsInputFilter(getDecimals())};
}
@Override
public boolean checkNewTransactionAmount(Amount amount){
if( coinData ==null ) return false;
public boolean checkNewTransactionAmount(Amount amount) {
if (coinData == null) return false;
if (amount.compareTo(convertToAmount(coinData.getBalanceInInternalUnits())) > 0) {
return false;
}
@ -215,10 +225,10 @@ public class BtcEngine extends CoinEngine {
if (fee.isZero() || amount.isZero())
return false;
if (isIncludeFee && (amount.compareTo(coinData.getBalanceInInternalUnits())>0 || amount.compareTo(fee)<0))
if (isIncludeFee && (amount.compareTo(coinData.getBalanceInInternalUnits()) > 0 || amount.compareTo(fee) < 0))
return false;
if (!isIncludeFee && amount.add(fee).compareTo(coinData.getBalanceInInternalUnits())>0)
if (!isIncludeFee && amount.add(fee).compareTo(coinData.getBalanceInInternalUnits()) > 0)
return false;
return true;
@ -267,7 +277,7 @@ public class BtcEngine extends CoinEngine {
// return;
// }
if ((ctx.getCard().getOfflineBalance() != null) && !coinData.isBalanceReceived() && (ctx.getCard().getRemainingSignatures() == ctx.getCard().getMaxSignatures()) && coinData.getBalanceInInternalUnits().notZero() ) {
if ((ctx.getCard().getOfflineBalance() != null) && !coinData.isBalanceReceived() && (ctx.getCard().getRemainingSignatures() == ctx.getCard().getMaxSignatures()) && coinData.getBalanceInInternalUnits().notZero()) {
balanceValidator.setScore(80);
balanceValidator.setFirstLine("Verified offline balance");
balanceValidator.setSecondLine("Can't obtain balance from blockchain. Restore internet connection to be more confident. ");
@ -293,28 +303,26 @@ public class BtcEngine extends CoinEngine {
@Override
public Amount getBalance() {
if( !hasBalanceInfo() ) return null;
if (!hasBalanceInfo()) return null;
return convertToAmount(coinData.getBalanceInInternalUnits());
}
@Override
public String evaluateFeeEquivalent(String fee) {
if( !coinData.getAmountEquivalentDescriptionAvailable() ) return "";
if (!coinData.getAmountEquivalentDescriptionAvailable()) return "";
try {
Amount feeAmount = new Amount(fee, getFeeCurrency());
return feeAmount.toEquivalentString(coinData.getRate());
}
catch (Exception e)
{
} catch (Exception e) {
return "";
}
}
@Override
public String getBalanceEquivalent() {
if( coinData ==null || !coinData.getAmountEquivalentDescriptionAvailable() ) return "";
Amount balance=getBalance();
if( balance==null ) return "";
if (coinData == null || !coinData.getAmountEquivalentDescriptionAvailable()) return "";
Amount balance = getBalance();
if (balance == null) return "";
return balance.toEquivalentString(coinData.getRate());
}
@ -354,7 +362,7 @@ public class BtcEngine extends CoinEngine {
@Override
public Amount convertToAmount(InternalAmount internalAmount) {
BigDecimal d=internalAmount.divide(new BigDecimal("100000000"));
BigDecimal d = internalAmount.divide(new BigDecimal("100000000"));
return new Amount(d, getBalanceCurrency());
}
@ -365,7 +373,7 @@ public class BtcEngine extends CoinEngine {
@Override
public InternalAmount convertToInternalAmount(Amount amount) throws Exception {
BigDecimal d=amount.multiply(new BigDecimal("100000000"));
BigDecimal d = amount.multiply(new BigDecimal("100000000"));
return new InternalAmount(d, "Satoshi");
}
@ -374,7 +382,7 @@ public class BtcEngine extends CoinEngine {
if (bytes == null) return null;
byte[] reversed = new byte[bytes.length];
for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1];
return new InternalAmount(Util.byteArrayToLong(reversed),"Satoshi");
return new InternalAmount(Util.byteArrayToLong(reversed), "Satoshi");
}
@Override

View file

@ -1,7 +1,11 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.eth;
import android.os.Bundle;
import android.util.Log;
import com.tangem.domain.wallet.CoinData;
import com.tangem.domain.wallet.CoinEngine;
import java.math.BigInteger;
public class EthData extends CoinData {

View file

@ -1,12 +1,23 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.eth;
import android.net.Uri;
import android.text.InputFilter;
import android.util.Log;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.TLV;
import com.tangem.util.BTCUtils;
import com.tangem.domain.wallet.BalanceValidator;
import com.tangem.domain.wallet.Blockchain;
import com.tangem.domain.wallet.CoinData;
import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.ECDSASignatureETH;
import com.tangem.domain.wallet.EthTransaction;
import com.tangem.domain.wallet.Issuer;
import com.tangem.domain.wallet.Keccak256;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.domain.wallet.TangemContext;
import com.tangem.domain.wallet.BTCUtils;
import com.tangem.util.CryptoUtil;
import com.tangem.util.DecimalDigitsInputFilter;
import com.tangem.wallet.R;

View file

@ -1,10 +1,10 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.token;
import android.os.Bundle;
import android.util.Log;
import java.math.BigDecimal;
import java.math.BigInteger;
import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.eth.EthData;
public class TokenData extends EthData {
private CoinEngine.InternalAmount balanceAlter = null;

View file

@ -1,13 +1,23 @@
package com.tangem.domain.wallet;
package com.tangem.domain.wallet.token;
import android.net.Uri;
import android.text.InputFilter;
import android.util.Log;
import com.google.common.base.Strings;
import com.tangem.data.db.PINStorage;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.TLV;
import com.tangem.util.BTCUtils;
import com.tangem.domain.wallet.BalanceValidator;
import com.tangem.domain.wallet.CoinData;
import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.ECDSASignatureETH;
import com.tangem.domain.wallet.EthTransaction;
import com.tangem.domain.wallet.Issuer;
import com.tangem.domain.wallet.Keccak256;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.domain.wallet.TangemContext;
import com.tangem.domain.wallet.BTCUtils;
import com.tangem.util.CryptoUtil;
import com.tangem.util.DecimalDigitsInputFilter;
import com.tangem.wallet.R;

View file

@ -14,11 +14,13 @@ import android.view.KeyEvent
import android.view.View
import android.widget.Toast
import com.tangem.data.network.ElectrumRequest
import com.tangem.data.network.ServerApiHelper
import com.tangem.data.network.ServerApiHelperElectrum
import com.tangem.data.network.ServerApiCommon
import com.tangem.data.network.ServerApiElectrum
import com.tangem.data.network.ServerApiInfura
import com.tangem.data.network.model.InfuraResponse
import com.tangem.domain.cardReader.NfcManager
import com.tangem.domain.wallet.*
import com.tangem.domain.wallet.btc.BtcData
import com.tangem.util.*
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.activity_confirm_payment.*
@ -37,8 +39,9 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
private var nfcManager: NfcManager? = null
private var serverApiHelper: ServerApiHelper = ServerApiHelper()
private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum()
private var serverApiCommon: ServerApiCommon = ServerApiCommon()
private var serverApiInfura: ServerApiInfura = ServerApiInfura()
private var serverApiElectrum: ServerApiElectrum = ServerApiElectrum()
private lateinit var ctx: TangemContext
private lateinit var amount: CoinEngine.Amount
@ -97,7 +100,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet || ctx.blockchain == Blockchain.Token) {
rgFee.isEnabled = false
requestInfura(ServerApiHelper.INFURA_ETH_GAS_PRICE)
requestInfura(ServerApiInfura.INFURA_ETH_GAS_PRICE)
} else {
rgFee.isEnabled = true
@ -228,10 +231,10 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
// serverApiHelperElectrum.setElectrumRequestData(electrumBodyListener)
// request infura eth gasPrice listener
val infuraBodyListener: ServerApiHelper.InfuraBodyListener = object : ServerApiHelper.InfuraBodyListener {
val infuraBodyListener: ServerApiInfura.InfuraBodyListener = object : ServerApiInfura.InfuraBodyListener {
override fun onSuccess(method: String, infuraResponse: InfuraResponse) {
when (method) {
ServerApiHelper.INFURA_ETH_GAS_PRICE -> {
ServerApiInfura.INFURA_ETH_GAS_PRICE -> {
var gasPrice = infuraResponse.result
gasPrice = gasPrice.substring(2)
//TODO - remove Gwei
@ -260,16 +263,16 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
override fun onFail(method: String, message: String) {
when (method) {
ServerApiHelper.INFURA_ETH_GAS_PRICE -> {
ServerApiInfura.INFURA_ETH_GAS_PRICE -> {
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
}
}
}
}
serverApiHelper.setInfuraResponse(infuraBodyListener)
serverApiInfura.setInfuraResponse(infuraBodyListener)
// request estimate fee listener
val estimateFeeListener: ServerApiHelper.EstimateFeeListener = object : ServerApiHelper.EstimateFeeListener {
val estimateFeeListener: ServerApiCommon.EstimateFeeListener = object : ServerApiCommon.EstimateFeeListener {
override fun onSuccess(blockCount: Int, estimateFeeResponse: String?) {
var fee: BigDecimal?
fee = BigDecimal(estimateFeeResponse) // BTC per 1 kb
@ -290,17 +293,17 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
fee = fee!!.setScale(8, RoundingMode.DOWN)
when (blockCount) {
ServerApiHelper.ESTIMATE_FEE_MINIMAL -> {
ServerApiCommon.ESTIMATE_FEE_MINIMAL -> {
minFee = CoinEngine.Amount(fee, engine.feeCurrency)
if (rgFee.checkedRadioButtonId == R.id.rbMinimalFee) doSetFee(rgFee.checkedRadioButtonId)
}
ServerApiHelper.ESTIMATE_FEE_NORMAL -> {
ServerApiCommon.ESTIMATE_FEE_NORMAL -> {
normalFee = CoinEngine.Amount(fee, engine.feeCurrency)
if (rgFee.checkedRadioButtonId == R.id.rbNormalFee) doSetFee(rgFee.checkedRadioButtonId)
}
ServerApiHelper.ESTIMATE_FEE_PRIORITY -> {
ServerApiCommon.ESTIMATE_FEE_PRIORITY -> {
maxFee = CoinEngine.Amount(fee, engine.feeCurrency)
if (rgFee.checkedRadioButtonId == R.id.rbMaximumFee) doSetFee(rgFee.checkedRadioButtonId)
}
@ -318,7 +321,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_calculate_fee_wrong_data_received_from_node))
}
}
serverApiHelper.setEstimateFee(estimateFeeListener)
serverApiCommon.setEstimateFee(estimateFeeListener)
}
public override fun onResume() {
@ -460,22 +463,22 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
private fun requestElectrum(card: TangemCard, electrumRequest: ElectrumRequest) {
if (UtilHelper.isOnline(this)) {
serverApiHelperElectrum.electrumRequestData(card, electrumRequest)
serverApiElectrum.electrumRequestData(card, electrumRequest)
} else
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
}
private fun requestInfura(method: String) {
if (UtilHelper.isOnline(this)) {
serverApiHelper.infura(method, 67, ctx.card!!.wallet, "", "")
serverApiInfura.infura(method, 67, ctx.card!!.wallet, "", "")
} else
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
}
private fun requestEstimateFee() {
serverApiHelper.estimateFee(ServerApiHelper.ESTIMATE_FEE_PRIORITY)
serverApiHelper.estimateFee(ServerApiHelper.ESTIMATE_FEE_NORMAL)
serverApiHelper.estimateFee(ServerApiHelper.ESTIMATE_FEE_MINIMAL)
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_PRIORITY)
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_NORMAL)
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_MINIMAL)
}
private fun doSetFee(checkedRadioButtonId: Int) {

View file

@ -1,13 +1,14 @@
package com.tangem.presentation.activity
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.tangem.data.network.ServerApiHelperElectrum
import com.tangem.App
import com.tangem.di.Navigator
import com.tangem.wallet.BuildConfig
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.activity_logo.*
import javax.inject.Inject
class LogoActivity : AppCompatActivity() {
@ -18,14 +19,17 @@ class LogoActivity : AppCompatActivity() {
const val MILLIS_AUTO_HIDE = 1000
}
private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum()
private val hideRunnable = Runnable { this.hide() }
@Inject
internal lateinit var navigator: Navigator
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_logo)
App.getNavigatorComponent().inject(this)
ivLogo.setOnClickListener { hide() }
}
@ -43,8 +47,7 @@ class LogoActivity : AppCompatActivity() {
}
private fun hide() {
val intent = Intent(baseContext, MainActivity::class.java)
startActivity(intent)
navigator.showMain(this)
finish()
}

View file

@ -24,7 +24,10 @@ import android.view.animation.Transformation
import android.widget.RelativeLayout
import android.widget.Toast
import com.scottyab.rootbeer.RootBeer
import com.tangem.data.network.ServerApiHelper
import com.tangem.data.Logger
import com.tangem.data.db.PINStorage
import com.tangem.data.network.ServerApiCommon
import com.tangem.data.nfc.DeviceNFCAntennaLocation
import com.tangem.data.nfc.ReadCardInfoTask
import com.tangem.domain.cardReader.CardProtocol
import com.tangem.domain.cardReader.FW
@ -150,7 +153,7 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
fab.setOnClickListener { showMenu(it) }
val apiHelper = ServerApiHelper()
val apiHelper = ServerApiCommon()
apiHelper.setLastVersionListener { response ->
try {
if (response.isNullOrEmpty()) return@setLastVersionListener

View file

@ -19,10 +19,10 @@ import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.Button
import com.tangem.data.network.task.request_pin.StartFingerprintReaderTask
import com.tangem.data.fingerprint.StartFingerprintReaderTask
import com.tangem.domain.cardReader.NfcManager
import com.tangem.domain.wallet.FingerprintHelper
import com.tangem.domain.wallet.PINStorage
import com.tangem.data.fingerprint.FingerprintHelper
import com.tangem.data.db.PINStorage
import com.tangem.domain.wallet.TangemCard
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.activity_pin_request.*

View file

@ -19,9 +19,9 @@ import android.text.TextUtils
import android.view.View
import android.widget.Button
import android.widget.Toast
import com.tangem.data.network.task.save_pin.ConfirmWithFingerprintTask
import com.tangem.domain.wallet.FingerprintHelper
import com.tangem.domain.wallet.PINStorage
import com.tangem.data.fingerprint.ConfirmWithFingerprintTask
import com.tangem.data.fingerprint.FingerprintHelper
import com.tangem.data.db.PINStorage
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.activity_pin_save.*
import kotlinx.android.synthetic.main.layout_pin_buttons.*

View file

@ -9,7 +9,7 @@ import android.nfc.Tag
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import com.tangem.data.network.Cryptonit_OtherAPI
import com.tangem.data.network.CryptonitOtherApi
import com.tangem.domain.cardReader.NfcManager
import com.tangem.domain.wallet.Blockchain
import com.tangem.domain.wallet.CoinEngineFactory
@ -18,10 +18,10 @@ import com.tangem.wallet.R
import kotlinx.android.synthetic.main.activity_prepare_cryptonit_other_api_withdrawal.*
import java.io.IOException
class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
class PrepareCryptonitOtherApiWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
companion object {
val TAG: String = PrepareCryptonitOtherAPIWithdrawalActivity::class.java.simpleName
val TAG: String = PrepareCryptonitOtherApiWithdrawalActivity::class.java.simpleName
private const val REQUEST_CODE_SCAN_QR_KEY = 1
private const val REQUEST_CODE_SCAN_QR_SECRET = 2
@ -30,7 +30,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt
private lateinit var ctx: TangemContext
private var nfcManager: NfcManager? = null
private var cryptonit: Cryptonit_OtherAPI? = null
private var cryptonit: CryptonitOtherApi? = null
@SuppressLint("SetTextI18n")
@ -44,7 +44,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt
ctx = TangemContext.loadFromBundle(this, intent.extras)
cryptonit = Cryptonit_OtherAPI(this)
cryptonit = CryptonitOtherApi(this)
tvKey.text = cryptonit!!.key
tvUserID.text = cryptonit!!.userId
@ -54,7 +54,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt
tvWallet.text = ctx.card!!.wallet
val engine = CoinEngineFactory.create(ctx)
tvCurrency.text = engine.balanceCurrency
tvCurrency.text = engine!!.balanceCurrency
etAmount.setText(engine.convertToAmount(engine.convertToInternalAmount(ctx.card!!.denomination)).toValueString())
etAmount.filters=engine.amountInputFilters

View file

@ -55,7 +55,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade
tvWallet.text = ctx.card!!.wallet
val engine = CoinEngineFactory.create(ctx)
tvCurrency.text = engine.balanceCurrency
tvCurrency.text = engine!!.balanceCurrency
tvFeeCurrency.text = engine.feeCurrency
etAmount.setText(engine.convertToAmount(engine.convertToInternalAmount(ctx.card!!.denomination)).toValueString())

View file

@ -60,7 +60,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa
tvWallet.text = ctx.card!!.wallet
val engine = CoinEngineFactory.create(ctx)
tvCurrency.text = engine.balanceCurrency
tvCurrency.text = engine!!.balanceCurrency
etAmount.setText(engine.convertToAmount(engine.convertToInternalAmount(ctx.card!!.denomination)).toValueString())
etAmount.filters=engine.amountInputFilters

View file

@ -81,7 +81,7 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
val engine1 = CoinEngineFactory.create(ctx)
val strAmount: String = etAmount.text.toString().replace(",", ".")
val amount = engine1.convertToAmount(etAmount.text.toString(), tvCurrency.text.toString())
val amount = engine1!!.convertToAmount(etAmount.text.toString(), tvCurrency.text.toString())
try {
if (!engine.checkNewTransactionAmount(amount))

View file

@ -53,23 +53,19 @@ class PurgeActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoc
public override fun onResume() {
super.onResume()
nfcManager!!.onResume()
nfcManager?.onResume()
}
public override fun onPause() {
nfcManager!!.onPause()
if (purgeTask != null) {
purgeTask!!.cancel(true)
}
nfcManager?.onPause()
purgeTask?.cancel(true)
super.onPause()
}
public override fun onStop() {
// dismiss enable NFC dialog
nfcManager!!.onStop()
if (purgeTask != null) {
purgeTask!!.cancel(true)
}
nfcManager?.onStop()
purgeTask?.cancel(true)
super.onStop()
}
@ -88,7 +84,7 @@ class PurgeActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoc
purgeTask!!.start()
} else {
// this Log.d(TAG, "Mismatch card UID (" + sUID + " instead of " + card.getUID() + ")");
nfcManager!!.ignoreTag(isoDep.tag)
nfcManager?.ignoreTag(isoDep.tag)
}
} catch (e: Exception) {
@ -109,9 +105,9 @@ class PurgeActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoc
}
override fun onReadStart(cardProtocol: CardProtocol) {
progressBar!!.post {
progressBar!!.visibility = View.VISIBLE
progressBar!!.progress = 5
progressBar.post {
progressBar.visibility = View.VISIBLE
progressBar.progress = 5
}
}

View file

@ -8,14 +8,14 @@ import android.support.v7.app.AppCompatActivity
import android.view.KeyEvent
import android.widget.Toast
import com.tangem.data.network.ElectrumRequest
import com.tangem.data.network.ServerApiHelper
import com.tangem.data.network.ServerApiHelperElectrum
import com.tangem.data.network.ServerApiElectrum
import com.tangem.data.network.ServerApiInfura
import com.tangem.data.network.model.InfuraResponse
import com.tangem.domain.cardReader.NfcManager
import com.tangem.domain.wallet.*
import com.tangem.domain.wallet.eth.EthData
import com.tangem.util.UtilHelper
import com.tangem.wallet.R
import org.json.JSONException
import java.io.IOException
import java.math.BigInteger
@ -25,8 +25,8 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
const val EXTRA_TX: String = "TX"
}
private var serverApiHelper: ServerApiHelper = ServerApiHelper()
private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum()
private var serverApiInfura: ServerApiInfura = ServerApiInfura()
private var serverApiElectrum: ServerApiElectrum = ServerApiElectrum()
private lateinit var ctx: TangemContext
private var tx: String? = null
@ -46,14 +46,14 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
val engine = CoinEngineFactory.create(ctx)
if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet || ctx.blockchain == Blockchain.Token)
requestInfura(ServerApiHelper.INFURA_ETH_SEND_RAW_TRANSACTION, "")
requestInfura(ServerApiInfura.INFURA_ETH_SEND_RAW_TRANSACTION, "")
else if (ctx.blockchain == Blockchain.Bitcoin || ctx.blockchain == Blockchain.BitcoinTestNet)
requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.card!!.wallet, tx))
else if (ctx.blockchain == Blockchain.BitcoinCash)
requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.card!!.wallet, tx))
// request electrum listener
val electrumBodyListener: ServerApiHelperElectrum.ElectrumRequestDataListener = object : ServerApiHelperElectrum.ElectrumRequestDataListener {
val electrumBodyListener: ServerApiElectrum.ElectrumRequestDataListener = object : ServerApiElectrum.ElectrumRequestDataListener {
override fun onSuccess(electrumRequest: ElectrumRequest?) {
if (electrumRequest!!.isMethod(ElectrumRequest.METHOD_SendTransaction)) {
if (electrumRequest.resultString.isEmpty())
@ -67,13 +67,13 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
finishWithError(message!!)
}
}
serverApiHelperElectrum.setElectrumRequestData(electrumBodyListener)
serverApiElectrum.setElectrumRequestData(electrumBodyListener)
// request infura listener
val infuraBodyListener: ServerApiHelper.InfuraBodyListener = object : ServerApiHelper.InfuraBodyListener {
val infuraBodyListener: ServerApiInfura.InfuraBodyListener = object : ServerApiInfura.InfuraBodyListener {
override fun onSuccess(method: String, infuraResponse: InfuraResponse) {
when (method) {
ServerApiHelper.INFURA_ETH_SEND_RAW_TRANSACTION -> {
ServerApiInfura.INFURA_ETH_SEND_RAW_TRANSACTION -> {
if (infuraResponse.result.isEmpty())
finishWithError("Rejected by node: " + infuraResponse.error)
else {
@ -88,13 +88,13 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
override fun onFail(method: String, message: String) {
when (method) {
ServerApiHelper.INFURA_ETH_SEND_RAW_TRANSACTION -> {
ServerApiInfura.INFURA_ETH_SEND_RAW_TRANSACTION -> {
finishWithError(message)
}
}
}
}
serverApiHelper.setInfuraResponse(infuraBodyListener)
serverApiInfura.setInfuraResponse(infuraBodyListener)
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
@ -132,14 +132,14 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
private fun requestInfura(method: String, contract: String) {
if (UtilHelper.isOnline(this)) {
serverApiHelper.infura(method, 67, ctx.card!!.wallet, contract, tx)
serverApiInfura.infura(method, 67, ctx.card!!.wallet, contract, tx)
} else
finishWithError(getString(R.string.no_connection))
}
private fun requestElectrum(card: TangemCard, electrumRequest: ElectrumRequest) {
if (UtilHelper.isOnline(this)) {
serverApiHelperElectrum.electrumRequestData(card, electrumRequest)
serverApiElectrum.electrumRequestData(card, electrumRequest)
} else
finishWithError(getString(R.string.no_connection))
}

View file

@ -19,16 +19,23 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.tangem.data.db.LocalStorage
import com.tangem.data.db.PINStorage
import com.tangem.data.network.ElectrumRequest
import com.tangem.data.network.ServerApiHelper
import com.tangem.data.network.ServerApiHelperElectrum
import com.tangem.data.network.ServerApiCommon
import com.tangem.data.network.ServerApiElectrum
import com.tangem.data.network.ServerApiInfura
import com.tangem.data.network.model.CardVerifyAndGetInfo
import com.tangem.data.network.model.InfuraResponse
import com.tangem.data.nfc.VerifyCardTask
import com.tangem.domain.cardReader.CardProtocol
import com.tangem.domain.cardReader.NfcManager
import com.tangem.domain.wallet.*
import com.tangem.domain.wallet.BitcoinCash.BtcCashEngine
import com.tangem.domain.wallet.btc.BtcData
import com.tangem.domain.wallet.eth.EthData
import com.tangem.domain.wallet.token.TokenData
import com.tangem.domain.wallet.token.TokenEngine
import com.tangem.domain.wallet.bch.BtcCashEngine
import com.tangem.presentation.activity.*
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
import com.tangem.presentation.dialog.PINSwapWarningDialog
@ -59,12 +66,11 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
private var nfcManager: NfcManager? = null
private var serverApiHelper: ServerApiHelper = ServerApiHelper()
private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum()
private var serverApiCommon: ServerApiCommon = ServerApiCommon()
private var serverApiInfura: ServerApiInfura = ServerApiInfura()
private var serverApiElectrum: ServerApiElectrum = ServerApiElectrum()
private var singleToast: Toast? = null
//private var card: TangemCard? = null
//private var engine: CoinEngine? = null
private lateinit var ctx: TangemContext
private var lastTag: Tag? = null
@ -87,11 +93,6 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
ctx = TangemContext.loadFromBundle(activity, activity.intent.extras)
// card = TangemCard(activity.intent.getStringExtra(TangemCard.EXTRA_UID))
// card!!.loadFromBundle(activity.intent.extras.getBundle(TangemCard.EXTRA_CARD))
//
// engine = CoinEngineFactory.create(activity, card!!, activity.intent.extras.getBundle(CoinEngine.EXTRA_ENGINE))
lastTag = activity.intent.getParcelableExtra(MainActivity.EXTRA_LAST_DISCOVERED_TAG)
localStorage = LocalStorage(activity)
@ -121,7 +122,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
// set listeners
srl!!.setOnRefreshListener { refresh() }
btnLookup.setOnClickListener {
val engine=CoinEngineFactory.create(ctx)
val engine = CoinEngineFactory.create(ctx)
val browserIntent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUriExplorer)
startActivity(browserIntent)
}
@ -137,7 +138,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
when (items[which]) {
getString(R.string.in_app) -> {
try {
val engine=CoinEngineFactory.create(ctx)
val engine = CoinEngineFactory.create(ctx)
val intent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUri)
intent.addCategory(Intent.CATEGORY_DEFAULT)
startActivity(intent)
@ -149,11 +150,11 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
doShareWallet(true)
}
getString(R.string.load_via_qr) -> {
val engine=CoinEngineFactory.create(ctx)
val engine = CoinEngineFactory.create(ctx)
ShowQRCodeDialog.show(activity, engine!!.shareWalletUri.toString())
}
// getString(R.string.via_cryptonit2) -> {
// val intent = Intent(ctx, PrepareCryptonitOtherAPIWithdrawalActivity::class.java)
// val intent = Intent(ctx, PrepareCryptonitOtherApiWithdrawalActivity::class.java)
// intent.putExtra("UID", card!!.uid)
// intent.putExtra("Card", card!!.asBundle)
// startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
@ -178,7 +179,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
dlg.window.attributes = wlp
} else {
try {
val engine=CoinEngineFactory.create(ctx)
val engine = CoinEngineFactory.create(ctx)
val intent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUri)
intent.addCategory(Intent.CATEGORY_DEFAULT)
startActivity(intent)
@ -198,7 +199,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
startActivity(intent)
}
btnExtract.setOnClickListener {
val engine=CoinEngineFactory.create(ctx)
val engine = CoinEngineFactory.create(ctx)
if (UtilHelper.isOnline(activity)) {
if (!engine!!.isExtractPossible)
showSingleToast(ctx.message)
@ -214,7 +215,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
// request electrum listener
val electrumBodyListener: ServerApiHelperElectrum.ElectrumRequestDataListener = object : ServerApiHelperElectrum.ElectrumRequestDataListener {
val electrumBodyListener: ServerApiElectrum.ElectrumRequestDataListener = object : ServerApiElectrum.ElectrumRequestDataListener {
override fun onSuccess(electrumRequest: ElectrumRequest?) {
if (electrumRequest!!.isMethod(ElectrumRequest.METHOD_GetBalance)) {
try {
@ -224,7 +225,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
ctx.coinData!!.isBalanceReceived = true
(ctx.coinData!! as BtcData).setBalanceConfirmed(confBalance)
(ctx.coinData!! as BtcData).balanceUnconfirmed = unconfirmedBalance
(ctx.coinData!! as BtcData).validationNodeDescription = serverApiHelperElectrum.validationNodeDescription
(ctx.coinData!! as BtcData).validationNodeDescription = serverApiElectrum.validationNodeDescription
} catch (e: JSONException) {
e.printStackTrace()
Log.e(TAG, "FAIL METHOD_GetBalance JSONException")
@ -288,13 +289,13 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
}
serverApiHelperElectrum.setElectrumRequestData(electrumBodyListener)
serverApiElectrum.setElectrumRequestData(electrumBodyListener)
// request infura listener
val infuraBodyListener: ServerApiHelper.InfuraBodyListener = object : ServerApiHelper.InfuraBodyListener {
val infuraBodyListener: ServerApiInfura.InfuraBodyListener = object : ServerApiInfura.InfuraBodyListener {
override fun onSuccess(method: String, infuraResponse: InfuraResponse) {
when (method) {
ServerApiHelper.INFURA_ETH_GET_BALANCE -> {
ServerApiInfura.INFURA_ETH_GET_BALANCE -> {
var balanceCap = infuraResponse.result
balanceCap = balanceCap.substring(2)
val l = BigInteger(balanceCap, 16)
@ -305,8 +306,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
// (ctx.coinData!! as EthData).balanceUnconfirmed = 0L
if (ctx.blockchain != Blockchain.Token) {
(ctx.coinData!! as EthData).isBalanceReceived = true
(ctx.coinData!! as EthData).balanceInInternalUnits = CoinEngine.InternalAmount(l.toBigDecimal(),"wei")
}else{
(ctx.coinData!! as EthData).balanceInInternalUnits = CoinEngine.InternalAmount(l.toBigDecimal(), "wei")
} else {
(ctx.coinData!! as TokenData).isBalanceReceived = true
//(ctx.coinData!! as TokenData).balanceInInternalUnits = CoinEngine.InternalAmount(l.toBigDecimal(),ctx.card.tokenSymbol)
(ctx.coinData!! as TokenData).balanceAlterInInternalUnits = CoinEngine.InternalAmount(l.toBigDecimal(), "wei")
@ -315,7 +316,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
// Log.i("$TAG eth_get_balance", balanceCap)
}
ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT -> {
ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT -> {
var nonce = infuraResponse.result
nonce = nonce.substring(2)
val count = BigInteger(nonce, 16)
@ -325,7 +326,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
// Log.i("$TAG eth_getTransCount", nonce)
}
ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT -> {
ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT -> {
var pending = infuraResponse.result
pending = pending.substring(2)
val count = BigInteger(pending, 16)
@ -334,7 +335,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
// Log.i("$TAG eth_getPendingTxCount", pending)
}
ServerApiHelper.INFURA_ETH_CALL -> {
ServerApiInfura.INFURA_ETH_CALL -> {
try {
var balanceCap = infuraResponse.result
balanceCap = balanceCap.substring(2)
@ -350,18 +351,18 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
// requestCounter--
// if (requestCounter == 0) srl!!.isRefreshing = false
//
// requestInfura(ServerApiHelper.INFURA_ETH_GET_BALANCE, "")
// requestInfura(ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT, "")
// requestInfura(ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT, "")
// requestInfura(ServerApiCommon.INFURA_ETH_GET_BALANCE, "")
// requestInfura(ServerApiCommon.INFURA_ETH_GET_TRANSACTION_COUNT, "")
// requestInfura(ServerApiCommon.INFURA_ETH_GET_PENDING_COUNT, "")
// return
// }
(ctx.coinData!! as EthData).balanceInInternalUnits = CoinEngine.InternalAmount(l.toBigDecimal(),ctx.card.tokenSymbol)
(ctx.coinData!! as EthData).balanceInInternalUnits = CoinEngine.InternalAmount(l.toBigDecimal(), ctx.card.tokenSymbol)
// Log.i("$TAG eth_call", balanceCap)
requestInfura(ServerApiHelper.INFURA_ETH_GET_BALANCE, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT, "")
requestInfura(ServerApiInfura.INFURA_ETH_GET_BALANCE, "")
requestInfura(ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT, "")
requestInfura(ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT, "")
} catch (e: JSONException) {
e.printStackTrace()
} catch (e: NumberFormatException) {
@ -371,7 +372,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
}
ServerApiHelper.INFURA_ETH_SEND_RAW_TRANSACTION -> {
ServerApiInfura.INFURA_ETH_SEND_RAW_TRANSACTION -> {
try {
var hashTX: String
try {
@ -406,10 +407,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
}
serverApiHelper.setInfuraResponse(infuraBodyListener)
serverApiInfura.setInfuraResponse(infuraBodyListener)
// request card verify and get info listener
val cardVerifyAndGetInfoListener: ServerApiHelper.CardVerifyAndGetInfoListener = object : ServerApiHelper.CardVerifyAndGetInfoListener {
val cardVerifyAndGetInfoListener: ServerApiCommon.CardVerifyAndGetInfoListener = object : ServerApiCommon.CardVerifyAndGetInfoListener {
override fun onSuccess(cardVerifyAndGetArtworkResponse: CardVerifyAndGetInfo.Response?) {
val result = cardVerifyAndGetArtworkResponse?.results!![0]
if (result.error != null) {
@ -435,7 +436,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
if (result.artwork != null && localStorage.checkNeedUpdateArtwork(result.artwork)) {
Log.w(TAG, "Artwork '${result.artwork!!.id}' updated, need download")
serverApiHelper.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), ctx.card!!)
serverApiCommon.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), ctx.card!!)
updateViews()
}
// Log.i(TAG, "setCardVerify " + it.results!![0].passed)
@ -445,10 +446,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
}
serverApiHelper.setCardVerifyAndGetInfoListener(cardVerifyAndGetInfoListener)
serverApiCommon.setCardVerifyAndGetInfoListener(cardVerifyAndGetInfoListener)
// request artwork listener
val artworkListener: ServerApiHelper.ArtworkListener = object : ServerApiHelper.ArtworkListener {
val artworkListener: ServerApiCommon.ArtworkListener = object : ServerApiCommon.ArtworkListener {
override fun onSuccess(artworkId: String?, inputStream: InputStream?, updateDate: Date?) {
localStorage.updateArtwork(artworkId!!, inputStream!!, updateDate!!)
ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(ctx.card!!))
@ -458,10 +459,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
}
serverApiHelper.setArtworkListener(artworkListener)
serverApiCommon.setArtworkListener(artworkListener)
// request rate info listener
serverApiHelper.setRateInfoData {
serverApiCommon.setRateInfoData {
val rate = it.priceUsd.toFloat()
ctx.coinData!!.rate = rate
ctx.coinData!!.rateAlter = rate
@ -724,168 +725,160 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
}
fun updateViews() {
try {
if (timerHideErrorAndMessage != null) {
timerHideErrorAndMessage!!.cancel()
timerHideErrorAndMessage = null
}
if (timerHideErrorAndMessage != null) {
timerHideErrorAndMessage!!.cancel()
timerHideErrorAndMessage = null
}
if (ctx.error == null || ctx.error.isEmpty()) {
tvError.visibility = View.GONE
tvError.text = ""
} else {
tvError.visibility = View.VISIBLE
tvError.text = ctx.error
}
if (ctx.error == null || ctx.error.isEmpty()) {
tvError.visibility = View.GONE
tvError.text = ""
} else {
tvError.visibility = View.VISIBLE
tvError.text = ctx.error
}
if (ctx.message == null || ctx.message.isEmpty()) {
tvMessage!!.text = ""
tvMessage!!.visibility = View.GONE
} else {
tvMessage!!.text = ctx.message
tvMessage!!.visibility = View.VISIBLE
}
if (ctx.message == null || ctx.message.isEmpty()) {
tvMessage!!.text = ""
tvMessage!!.visibility = View.GONE
} else {
tvMessage!!.text = ctx.message
tvMessage!!.visibility = View.VISIBLE
}
if (srl!!.isRefreshing) {
tvBalanceLine1.setTextColor(resources.getColor(R.color.primary))
tvBalanceLine1.text = getString(R.string.verifying_in_blockchain)
tvBalanceLine2.text = ""
tvBalance.text = ""
tvBalanceEquivalent.text = ""
} else {
val validator = BalanceValidator()
validator.Check(ctx, false)
tvBalanceLine1.setTextColor(ContextCompat.getColor(activity, validator.color))
tvBalanceLine1.text = validator.firstLine
tvBalanceLine2.text = validator.getSecondLine(false)
}
if (srl!!.isRefreshing) {
tvBalanceLine1.setTextColor(resources.getColor(R.color.primary))
tvBalanceLine1.text = getString(R.string.verifying_in_blockchain)
tvBalanceLine2.text = ""
tvBalance.text = ""
tvBalanceEquivalent.text = ""
} else {
val validator = BalanceValidator()
validator.Check(ctx, false)
tvBalanceLine1.setTextColor(ContextCompat.getColor(activity, validator.color))
tvBalanceLine1.text = validator.firstLine
tvBalanceLine2.text = validator.getSecondLine(false)
}
val engine=CoinEngineFactory.create(ctx)
if (engine!!.hasBalanceInfo() || ctx.card!!.offlineBalance == null) {
val html = Html.fromHtml(engine!!.balanceHTML)
tvBalance.text = html
// TODO???
tvBalanceEquivalent.text = engine!!.balanceEquivalent
} else {
// TODO
val html = Html.fromHtml(engine!!.offlineBalanceHTML)
tvBalance.text = html
}
val engine = CoinEngineFactory.create(ctx)
if (engine!!.hasBalanceInfo() || ctx.card!!.offlineBalance == null) {
val html = Html.fromHtml(engine.balanceHTML)
tvBalance.text = html
// TODO???
tvBalanceEquivalent.text = engine.balanceEquivalent
} else {
// TODO
val html = Html.fromHtml(engine.offlineBalanceHTML)
tvBalance.text = html
}
tvWallet.text = ctx.card!!.wallet
tvWallet.text = ctx.card!!.wallet
// tvBlockchain.text = card!!.blockchainName
if (ctx.card!!.tokenSymbol.length > 1) {
val html = Html.fromHtml(ctx.card!!.blockchainName)
tvBlockchain.text = html
} else
tvBlockchain.text = ctx.card!!.blockchainName
if (ctx.card!!.tokenSymbol.length > 1) {
val html = Html.fromHtml(ctx.card!!.blockchainName)
tvBlockchain.text = html
} else
tvBlockchain.text = ctx.card!!.blockchainName
if (engine!!.hasBalanceInfo()) {
btnExtract.isEnabled = true
btnExtract.backgroundTintList = activeColor
} else {
btnExtract.isEnabled = false
btnExtract.backgroundTintList = inactiveColor
}
ctx.error = null
ctx.message = null
} catch (e: Exception) {
e.printStackTrace()
if (engine.hasBalanceInfo()) {
btnExtract.isEnabled = true
btnExtract.backgroundTintList = activeColor
} else {
btnExtract.isEnabled = false
btnExtract.backgroundTintList = inactiveColor
}
ctx.error = null
ctx.message = null
}
private fun refresh() {
if ((srl == null) || (ctx.card == null)) return;
try {
// clear all card data and request again
srl!!.isRefreshing = true
ctx.coinData.clearInfo();
ctx.error = null
ctx.message = null
requestCounter = 0
if (ctx.card == null) return
updateViews()
// clear all card data and request again
srl?.isRefreshing = true
ctx.coinData.clearInfo()
ctx.error = null
ctx.message = null
requestCounter = 0
requestVerifyAndGetInfo()
updateViews()
requestVerifyAndGetInfo()
// Bitcoin
if (ctx.blockchain == Blockchain.Bitcoin) {
if (ctx.blockchain == Blockchain.Bitcoin || ctx.blockchain == Blockchain.BitcoinTestNet) {
ctx.coinData.setIsBalanceEqual(true)
requestElectrum(ElectrumRequest.checkBalance(ctx.card!!.wallet))
requestElectrum(ElectrumRequest.listUnspent(ctx.card!!.wallet))
requestRateInfo("bitcoin")
}
requestElectrum(ElectrumRequest.checkBalance(ctx.card!!.wallet))
requestElectrum(ElectrumRequest.listUnspent(ctx.card!!.wallet))
requestRateInfo("bitcoin")
}
// BitcoinCash
else if (ctx.blockchain == Blockchain.BitcoinCash) {
ctx.coinData.setIsBalanceEqual(true)
val engine = CoinEngineFactory.create(ctx)
requestElectrum(ElectrumRequest.checkBalance((engine as BtcCashEngine).convertToLegacyAddress(ctx.card!!.wallet)))
requestElectrum(ElectrumRequest.listUnspent((engine as BtcCashEngine).convertToLegacyAddress(ctx.card!!.wallet)))
requestRateInfo("bitcoin-cash")
}
requestElectrum(ElectrumRequest.checkBalance((engine as BtcCashEngine).convertToLegacyAddress(ctx.card!!.wallet)))
requestElectrum(ElectrumRequest.listUnspent((engine as BtcCashEngine).convertToLegacyAddress(ctx.card!!.wallet)))
requestRateInfo("bitcoin-cash")
}
// Ethereum
else if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet) {
requestInfura(ServerApiHelper.INFURA_ETH_GET_BALANCE, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT, "")
requestRateInfo("ethereum")
}
// Ethereum
else if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet) {
requestInfura(ServerApiInfura.INFURA_ETH_GET_BALANCE, "")
requestInfura(ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT, "")
requestInfura(ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT, "")
requestRateInfo("ethereum")
}
// Token
else if (ctx.blockchain == Blockchain.Token) {
val engine = CoinEngineFactory.create(ctx)
requestInfura(ServerApiHelper.INFURA_ETH_CALL, (engine as TokenEngine).getContractAddress(ctx.card))
requestRateInfo("ethereum")
}
} catch (e: Exception) {
e.printStackTrace()
// Token
else if (ctx.blockchain == Blockchain.Token) {
val engine = CoinEngineFactory.create(ctx)
requestInfura(ServerApiInfura.INFURA_ETH_CALL, (engine as TokenEngine).getContractAddress(ctx.card))
requestRateInfo("ethereum")
}
}
private fun requestElectrum(electrumRequest: ElectrumRequest) {
if (UtilHelper.isOnline(activity!!)) {
requestCounter++
serverApiHelperElectrum.electrumRequestData(ctx.card, electrumRequest)
serverApiElectrum.electrumRequestData(ctx.card, electrumRequest)
} else {
Toast.makeText(activity!!, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
srl!!.isRefreshing = false
srl?.isRefreshing = false
}
}
private fun requestInfura(method: String, contract: String) {
if (UtilHelper.isOnline(activity)) {
requestCounter++
serverApiHelper.infura(method, 67, ctx.card!!.wallet, contract, "")
serverApiInfura.infura(method, 67, ctx.card!!.wallet, contract, "")
} else {
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
srl!!.isRefreshing = false
srl?.isRefreshing = false
}
}
private fun requestVerifyAndGetInfo() {
if (UtilHelper.isOnline(activity)) {
if ((ctx.card!!.isOnlineVerified == null || !ctx.card!!.isOnlineVerified)) {
serverApiHelper.cardVerifyAndGetInfo(ctx.card)
serverApiCommon.cardVerifyAndGetInfo(ctx.card)
}
} else {
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
srl!!.isRefreshing = false
srl?.isRefreshing = false
}
}
private fun requestRateInfo(cryptoId: String) {
if (UtilHelper.isOnline(activity)) {
serverApiHelper.rateInfoData(cryptoId)
serverApiCommon.rateInfoData(cryptoId)
} else {
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
srl!!.isRefreshing = false
srl?.isRefreshing = false
}
}

View file

@ -13,6 +13,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import android.widget.Toast
import com.tangem.data.db.PINStorage
import com.tangem.domain.cardReader.NfcManager
import com.tangem.domain.wallet.*
import com.tangem.presentation.activity.CreateNewWalletActivity
@ -285,7 +286,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback {
val engine = CoinEngineFactory.create(ctx)
tvInputs.text = engine.unspentInputsDescription
tvInputs.text = engine!!.unspentInputsDescription
ivBlockchain.setImageResource(Blockchain.getLogoImageResource(ctx.card!!.blockchainID, ctx.card!!.tokenSymbol))
@ -467,7 +468,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback {
private fun doPurge() {
requestPIN2Count = 0
val engine=CoinEngineFactory.create(ctx)
if (!engine.hasBalanceInfo()) {
if (!engine!!.hasBalanceInfo()) {
return
} else if (engine.isBalanceNotZero) {
Toast.makeText(context, R.string.cannot_erase_wallet_with_non_zero_balance, Toast.LENGTH_LONG).show()

View file

@ -17,7 +17,7 @@ package com.tangem.presentation.viewmodel
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
import com.dmmatrix.epro.core.exception.Failure
import com.tangem.data.network.exception.Failure
/**
* Base ViewModel class with default Failure handling.

View file

@ -1,7 +1,7 @@
package com.tangem.presentation.viewmodel
import android.arch.lifecycle.MutableLiveData
import com.dmmatrix.epro.core.exception.Failure
import com.tangem.data.network.exception.Failure
class LoadedWalletViewModel : BaseViewModel() {

View file

@ -1,6 +1,6 @@
package com.tangem.util;
import com.tangem.domain.wallet.BitcoinOutputStream;
import com.tangem.domain.wallet.btc.BitcoinOutputStream;
import org.spongycastle.asn1.ASN1Integer;
import org.spongycastle.asn1.DERSequenceGenerator;

View file

@ -1,4 +1,4 @@
package com.tangem.domain.wallet;
package com.tangem.util;
/**
* Created by Ilia on 20.04.2018.

View file

@ -2,8 +2,6 @@ package com.tangem.util;
import android.os.Build;
import com.tangem.domain.wallet.DeviceName;
/**
* Created by Ilia on 20.04.2018.
*/

View file

@ -1,52 +0,0 @@
package com.tangem.util;
import android.content.Context;
import android.graphics.Canvas;
import android.support.v7.widget.AppCompatTextView;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.Gravity;
public class VerticalTextView extends AppCompatTextView {
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs) {
super(context, attrs);
final int gravity = getGravity();
if (Gravity.isVertical(gravity) && (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
} else {
topDown = true;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas canvas) {
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if (topDown) {
canvas.translate(getWidth(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}