Updated on 2026-08-14
This commit is contained in:
parent
48db52b2a9
commit
71fe425c1b
61 changed files with 592 additions and 454 deletions
|
|
@ -8,7 +8,7 @@ import android.security.keystore.KeyGenParameterSpec;
|
|||
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||
import android.security.keystore.KeyProperties;
|
||||
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.presentation.activity.PinRequestActivity;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
|||
|
|
@ -2,20 +2,6 @@ package com.tangem.data.network;
|
|||
|
||||
public class Server {
|
||||
|
||||
/**
|
||||
* https://tangem-webapp.appspot.com/
|
||||
* https://tangem-services.appspot.com/
|
||||
*/
|
||||
public static class ApiTangem {
|
||||
public static final String URL_TANGEM = ServerURL.API_TANGEM;
|
||||
|
||||
public static class Method {
|
||||
static final String VERIFY = URL_TANGEM + "verify";
|
||||
static final String VERIFY_AND_GET_INFO = URL_TANGEM + "card/verify-and-get-info";
|
||||
static final String ARTWORK = URL_TANGEM + "card/artwork";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ApiUpdateVersion {
|
||||
public static final String URL_UPDATE_VERSION = ServerURL.API_UPDATE_VERSION;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import android.support.annotation.NonNull;
|
|||
import android.util.Log;
|
||||
|
||||
import com.tangem.App;
|
||||
import com.tangem.data.network.model.CardVerifyAndGetInfo;
|
||||
import com.tangem.tangemcard.data.network.TangemApi;
|
||||
import com.tangem.tangemcard.data.network.model.CardVerifyAndGetInfo;
|
||||
import com.tangem.data.network.model.RateInfoResponse;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
|
@ -83,94 +84,6 @@ public class ServerApiCommon {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Card verify
|
||||
*/
|
||||
private CardVerifyAndGetInfoListener cardVerifyAndGetInfoListener;
|
||||
|
||||
public interface CardVerifyAndGetInfoListener {
|
||||
void onSuccess(CardVerifyAndGetInfo.Response cardVerifyAndGetArtworkResponse);
|
||||
void onFail(String message);
|
||||
}
|
||||
|
||||
public void setCardVerifyAndGetInfoListener(CardVerifyAndGetInfoListener listener) {
|
||||
cardVerifyAndGetInfoListener = listener;
|
||||
}
|
||||
|
||||
public void cardVerifyAndGetInfo(TangemCard card) {
|
||||
TangemApi tangemApi = App.getNetworkComponent().getRetrofitTangem().create(TangemApi.class);
|
||||
|
||||
List<CardVerifyAndGetInfo.Request.Item> requests = new ArrayList<>();
|
||||
requests.add(new CardVerifyAndGetInfo.Request.Item(Util.bytesToHex(card.getCID()), Util.bytesToHex(card.getCardPublicKey())));
|
||||
|
||||
CardVerifyAndGetInfo.Request requestBody = new CardVerifyAndGetInfo.Request(requests);
|
||||
|
||||
Call<CardVerifyAndGetInfo.Response> call = tangemApi.getCardVerifyAndGetInfo(requestBody);
|
||||
call.enqueue(new Callback<CardVerifyAndGetInfo.Response>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<CardVerifyAndGetInfo.Response> call, @NonNull Response<CardVerifyAndGetInfo.Response> response) {
|
||||
if (response.code() == 200) {
|
||||
CardVerifyAndGetInfo.Response cardVerifyAndGetArtworkResponse = response.body();
|
||||
cardVerifyAndGetInfoListener.onSuccess(cardVerifyAndGetArtworkResponse);
|
||||
Log.i(TAG, "cardVerifyAndGeInfo onResponse " + response.code());
|
||||
} else {
|
||||
cardVerifyAndGetInfoListener.onFail(String.valueOf(response.code()));
|
||||
Log.e(TAG, "cardVerifyAndGetInfo onResponse " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<CardVerifyAndGetInfo.Response> call, @NonNull Throwable t) {
|
||||
cardVerifyAndGetInfoListener.onFail(t.getMessage());
|
||||
Log.e(TAG, "cardVerifyAndGetInfo onFailure " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Last version request from GitHub
|
||||
*/
|
||||
private ArtworkListener artworkListener;
|
||||
|
||||
public interface ArtworkListener {
|
||||
void onSuccess(String artworkId, InputStream inputStream, Date updateDate);
|
||||
void onFail(String message);
|
||||
}
|
||||
|
||||
public void setArtworkListener(ArtworkListener listener) {
|
||||
artworkListener = listener;
|
||||
}
|
||||
|
||||
public void requestArtwork(String artworkId, Date updateDate, TangemCard card) {
|
||||
TangemApi tangemApi = App.getNetworkComponent().getRetrofitTangem().create(TangemApi.class);
|
||||
|
||||
Call<ResponseBody> call = tangemApi.getArtwork(artworkId, Util.bytesToHex(card.getCID()), Util.bytesToHex(card.getCardPublicKey()));
|
||||
call.enqueue(new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
|
||||
Log.i(TAG, "getArtwork onResponse " + response.code());
|
||||
if (response.code() == 200) {
|
||||
try {
|
||||
ResponseBody body = response.body();
|
||||
if (body != null) {
|
||||
artworkListener.onSuccess(artworkId, body.byteStream(), updateDate);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
|
||||
artworkListener.onFail(t.getMessage());
|
||||
Log.e(TAG, "getArtwork onFailure " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Used in Crypto-currency course
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
package com.tangem.tangemcard.tasks;
|
||||
package com.tangem.data.nfc;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
import com.tangem.domain.wallet.BTCUtils;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
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.domain.wallet.BTCUtils;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SignPaymentTask extends Thread {
|
||||
public class SignPaymentTask extends Thread{
|
||||
public static final String TAG = SignPaymentTask.class.getSimpleName();
|
||||
|
||||
private CoinEngine.Amount txAmount;
|
||||
|
|
@ -72,7 +72,7 @@ public class SignPaymentTask extends Thread {
|
|||
Log.i(TAG, "[-- Start sign payment --]");
|
||||
|
||||
if (isCancelled) return;
|
||||
protocol.run_Read(false);
|
||||
protocol.run_Read();
|
||||
protocol.run_VerifyCard();
|
||||
|
||||
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
|
||||
|
|
@ -4,6 +4,7 @@ import android.app.Activity
|
|||
import android.nfc.Tag
|
||||
import android.os.Bundle
|
||||
import com.tangem.domain.wallet.CoinData
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.presentation.activity.EmptyWalletActivity
|
||||
import com.tangem.presentation.activity.LoadedWalletActivity
|
||||
|
|
@ -17,16 +18,16 @@ class Navigator {
|
|||
context.startActivity(MainActivity.callingIntent(context))
|
||||
}
|
||||
|
||||
fun showLoadedWallet(context: Activity, lastTag: Tag, cardInfo: Bundle) {
|
||||
context.startActivityForResult(LoadedWalletActivity.callingIntent(context, lastTag, cardInfo), MainActivity.REQUEST_CODE_SHOW_CARD_ACTIVITY)
|
||||
fun showLoadedWallet(context: Activity, lastTag: Tag, ctx: TangemContext) {
|
||||
context.startActivityForResult(LoadedWalletActivity.callingIntent(context, lastTag, ctx), MainActivity.REQUEST_CODE_SHOW_CARD_ACTIVITY)
|
||||
}
|
||||
|
||||
fun showEmptyWallet(context: Activity) {
|
||||
context.startActivity(EmptyWalletActivity.callingIntent(context))
|
||||
fun showEmptyWallet(context: Activity, ctx: TangemContext) {
|
||||
context.startActivity(EmptyWalletActivity.callingIntent(context ,ctx))
|
||||
}
|
||||
|
||||
fun showVerifyCard(context: Activity, card: TangemCard, coinData: CoinData, message: String, error: String) {
|
||||
context.startActivityForResult(VerifyCardActivity.callingIntent(context, card, coinData, message, error), LoadedWallet.REQUEST_CODE_VERIFY_CARD)
|
||||
fun showVerifyCard(context: Activity, ctx: TangemContext) {
|
||||
context.startActivityForResult(VerifyCardActivity.callingIntent(context, ctx), LoadedWallet.REQUEST_CODE_VERIFY_CARD)
|
||||
}
|
||||
|
||||
fun showPinSwap(context: Activity) {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@ public interface NetworkComponent {
|
|||
@Named(Server.ApiEstimatefee.URL_ESTIMATEFEE)
|
||||
Retrofit getRetrofitEstimatefee();
|
||||
|
||||
@Named(Server.ApiTangem.URL_TANGEM)
|
||||
Retrofit getRetrofitTangem();
|
||||
|
||||
@Named(Server.ApiCoinmarket.URL_COINMARKET)
|
||||
Retrofit getRetrofitCoinmarketcap();
|
||||
|
||||
|
|
|
|||
|
|
@ -41,17 +41,6 @@ class NetworkModule {
|
|||
.build();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
@Named(Server.ApiTangem.URL_TANGEM)
|
||||
Retrofit provideRetrofitTangem() {
|
||||
return new Retrofit.Builder()
|
||||
.baseUrl(Server.ApiTangem.URL_TANGEM)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.client(createOkHttpClient())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
@Named(Server.ApiUpdateVersion.URL_UPDATE_VERSION)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import android.net.Uri;
|
|||
import android.text.InputFilter;
|
||||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.tasks.SignTask;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
|
@ -20,6 +23,7 @@ import java.util.Locale;
|
|||
|
||||
public abstract class CoinEngine {
|
||||
|
||||
|
||||
public static class InternalAmount extends BigDecimal {
|
||||
private String currency;
|
||||
|
||||
|
|
@ -231,4 +235,21 @@ public abstract class CoinEngine {
|
|||
|
||||
public abstract String getUnspentInputsDescription();
|
||||
|
||||
public void defineWallet() throws CardProtocol.TangemException {
|
||||
try {
|
||||
String wallet = calculateAddress(ctx.getCard().getWalletPublicKey());
|
||||
ctx.getCoinData().setWallet(wallet);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ctx.getCoinData().setWallet("ERROR");
|
||||
throw new CardProtocol.TangemException("Can't define wallet address");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SignTask.PaymentToSign constructPayment(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package com.tangem.domain.wallet.bch;
|
|||
import android.net.Uri;
|
||||
import android.text.InputFilter;
|
||||
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
|
|
@ -181,12 +181,12 @@ public class BtcCashEngine extends CoinEngine {
|
|||
|
||||
@Override
|
||||
public Uri getShareWalletUriExplorer() {
|
||||
return Uri.parse((ctx.getBlockchain() == Blockchain.BitcoinCash ? "https://bitcoincash.blockexplorer.com/address/" : "https://testnet.blockexplorer.com/address/") + ctx.getCard().getWallet());
|
||||
return Uri.parse((ctx.getBlockchain() == Blockchain.BitcoinCash ? "https://bitcoincash.blockexplorer.com/address/" : "https://testnet.blockexplorer.com/address/") + ctx.getCoinData().getWallet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getShareWalletUri() {
|
||||
return Uri.parse(ctx.getCard().getWallet());
|
||||
return Uri.parse(ctx.getCoinData().getWallet());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -440,7 +440,7 @@ public class BtcCashEngine extends CoinEngine {
|
|||
|
||||
CoinEngine engine = CoinEngineFactory.INSTANCE.create(ctx);
|
||||
|
||||
String srcLegacyAddress = ((BtcCashEngine)engine).convertToLegacyAddress(ctx.getCard().getWallet());
|
||||
String srcLegacyAddress = ((BtcCashEngine)engine).convertToLegacyAddress(ctx.getCoinData().getWallet());
|
||||
String destLegacyAddress = ((BtcCashEngine)engine).convertToLegacyAddress(destAddress);
|
||||
byte[] pbKey = ctx.getCard().getWalletPublicKeyRar(); //ALWAYS USING COMPRESS KEY
|
||||
|
||||
|
|
@ -498,9 +498,11 @@ public class BtcCashEngine extends CoinEngine {
|
|||
throw new Exception("Hashes length must be identical!");
|
||||
bs.write(dataForSign[i]);
|
||||
}
|
||||
signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), "sha-256x2", bs.toByteArray(), null, null, null).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
} else {
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer, null, ctx.getCard().getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
//ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer
|
||||
//ctx.getCard().getIssuer()
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, null, null, null).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
// TODO slice signFromCard to hashes.length parts
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.domain.wallet.btc;
|
|||
import android.net.Uri;
|
||||
import android.text.InputFilter;
|
||||
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
|
|
@ -179,15 +179,15 @@ public class BtcEngine extends CoinEngine {
|
|||
|
||||
@Override
|
||||
public Uri getShareWalletUriExplorer() {
|
||||
return Uri.parse((ctx.getBlockchain() == Blockchain.Bitcoin ? "https://blockchain.info/address/" : "https://testnet.blockchain.info/address/") + ctx.getCard().getWallet());
|
||||
return Uri.parse((ctx.getBlockchain() == Blockchain.Bitcoin ? "https://blockchain.info/address/" : "https://testnet.blockchain.info/address/") + ctx.getCoinData().getWallet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getShareWalletUri() {
|
||||
if (ctx.getCard().getDenomination() != null) {
|
||||
return Uri.parse("bitcoin:" + ctx.getCard().getWallet() + "?amount=" + convertToAmount(convertToInternalAmount(ctx.getCard().getDenomination())).toValueString(8));
|
||||
return Uri.parse("bitcoin:" + ctx.getCoinData().getWallet() + "?amount=" + convertToAmount(convertToInternalAmount(ctx.getCard().getDenomination())).toValueString(8));
|
||||
} else {
|
||||
return Uri.parse("bitcoin:" + ctx.getCard().getWallet());
|
||||
return Uri.parse("bitcoin:" + ctx.getCoinData().getWallet());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,7 +408,7 @@ public class BtcEngine extends CoinEngine {
|
|||
|
||||
checkBlockchainDataExists();
|
||||
|
||||
String myAddress = ctx.getCard().getWallet();
|
||||
String myAddress = ctx.getCoinData().getWallet();
|
||||
byte[] pbKey = ctx.getCard().getWalletPublicKey();
|
||||
|
||||
// Build script for our address
|
||||
|
|
@ -464,9 +464,10 @@ public class BtcEngine extends CoinEngine {
|
|||
throw new Exception("Hashes length must be identical!");
|
||||
bs.write(dataForSign[i]);
|
||||
}
|
||||
signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), "sha-256x2",bs.toByteArray(),null,null,null).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
} else {
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer, null, ctx.getCard().getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
//ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer, null, ctx.getCard().getIssuer()
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, null, null, null).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
// TODO slice signFromCard to hashes.length parts
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.net.Uri;
|
|||
import android.text.InputFilter;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
|
|
@ -227,18 +227,18 @@ public class EthEngine extends CoinEngine {
|
|||
@Override
|
||||
public Uri getShareWalletUri() {
|
||||
if (ctx.getCard().getDenomination() != null) {
|
||||
return Uri.parse("ethereum:" + ctx.getCard().getWallet());// + "?value=" + mCard.getDenomination() +"e18");
|
||||
return Uri.parse("ethereum:" + ctx.getCoinData().getWallet());// + "?value=" + mCard.getDenomination() +"e18");
|
||||
} else {
|
||||
return Uri.parse("ethereum:" + ctx.getCard().getWallet());
|
||||
return Uri.parse("ethereum:" + ctx.getCoinData().getWallet());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getShareWalletUriExplorer() {
|
||||
if (ctx.getCard().getBlockchain() == Blockchain.EthereumTestNet)
|
||||
return Uri.parse("https://rinkeby.etherscan.io/address/" + ctx.getCard().getWallet());
|
||||
return Uri.parse("https://rinkeby.etherscan.io/address/" + ctx.getCoinData().getWallet());
|
||||
else
|
||||
return Uri.parse("https://etherscan.io/address/" + ctx.getCard().getWallet());
|
||||
return Uri.parse("https://etherscan.io/address/" + ctx.getCoinData().getWallet());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -383,7 +383,7 @@ public class EthEngine extends CoinEngine {
|
|||
|
||||
BigInteger nonceValue = coinData.getConfirmedTXCount();
|
||||
byte[] pbKey = ctx.getCard().getWalletPublicKey();
|
||||
boolean flag = (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
// boolean flag = (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
Issuer issuer = ctx.getCard().getIssuer();
|
||||
|
||||
BigInteger weiFee=convertToInternalAmount(feeValue).toBigIntegerExact();
|
||||
|
|
@ -412,7 +412,7 @@ public class EthEngine extends CoinEngine {
|
|||
|
||||
byte[] signFromCard = null;
|
||||
try {
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, flag, null, issuer).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, null, null, null).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
// TODO slice signFromCard to hashes.length parts
|
||||
} catch (Exception ex) {
|
||||
Log.e("ETH", ex.getMessage());
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import android.text.InputFilter;
|
|||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
|
|
@ -282,15 +282,15 @@ public class TokenEngine extends CoinEngine {
|
|||
|
||||
@Override
|
||||
public Uri getShareWalletUriExplorer() {
|
||||
return Uri.parse("https://etherscan.io/token/" + getContractAddress(ctx.getCard()) + "?a=" + ctx.getCard().getWallet());
|
||||
return Uri.parse("https://etherscan.io/token/" + getContractAddress(ctx.getCard()) + "?a=" + ctx.getCoinData().getWallet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getShareWalletUri() {
|
||||
if (ctx.getCard().getDenomination() != null) {
|
||||
return Uri.parse("ethereum:" + ctx.getCard().getWallet());// + "?value=" + mCard.getDenomination() +"e18");
|
||||
return Uri.parse("ethereum:" + ctx.getCoinData().getWallet());// + "?value=" + mCard.getDenomination() +"e18");
|
||||
} else {
|
||||
return Uri.parse("ethereum:" + ctx.getCard().getWallet());
|
||||
return Uri.parse("ethereum:" + ctx.getCoinData().getWallet());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +436,7 @@ public class TokenEngine extends CoinEngine {
|
|||
public byte[] signETH(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress, CardProtocol protocol) throws Exception {
|
||||
BigInteger nonceValue = coinData.getConfirmedTXCount();
|
||||
byte[] pbKey = ctx.getCard().getWalletPublicKey();
|
||||
boolean flag = (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
// boolean flag = (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
Issuer issuer = ctx.getCard().getIssuer();
|
||||
|
||||
BigInteger weiFee = convertToInternalAmount(feeValue).toBigIntegerExact();
|
||||
|
|
@ -467,7 +467,7 @@ public class TokenEngine extends CoinEngine {
|
|||
|
||||
byte[] signFromCard = null;
|
||||
try {
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, flag, null, issuer).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, null, null, null).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
// TODO slice signFromCard to hashes.length parts
|
||||
} catch (Exception ex) {
|
||||
Log.e("ETH", ex.getMessage());
|
||||
|
|
@ -500,7 +500,7 @@ public class TokenEngine extends CoinEngine {
|
|||
public byte[] signToken(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress, CardProtocol protocol) throws Exception {
|
||||
BigInteger nonceValue = coinData.getConfirmedTXCount();
|
||||
byte[] pbKey = ctx.getCard().getWalletPublicKey();
|
||||
boolean flag = (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
// boolean flag = (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
Issuer issuer = ctx.getCard().getIssuer();
|
||||
|
||||
|
||||
|
|
@ -553,7 +553,7 @@ public class TokenEngine extends CoinEngine {
|
|||
|
||||
byte[] signFromCard = null;
|
||||
try {
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, flag, null, issuer).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, null, null, null).getTLV(TLV.Tag.TAG_Signature).Value;
|
||||
// TODO slice signFromCard to hashes.length parts
|
||||
} catch (Exception ex) {
|
||||
Log.e("ETH", ex.getMessage());
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
// TODO - move to BtcEngine
|
||||
@Throws(Exception::class)
|
||||
internal fun buildSize(outputAddress: String, outFee: String, outAmount: String): Int {
|
||||
val myAddress = ctx.card!!.wallet
|
||||
val myAddress = ctx.coinData!!.wallet
|
||||
val pbKey = ctx.card!!.walletPublicKey
|
||||
val pbComprKey = ctx.card!!.walletPublicKeyRar
|
||||
|
||||
|
|
@ -472,7 +472,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
|
||||
private fun requestInfura(method: String) {
|
||||
if (UtilHelper.isOnline(this)) {
|
||||
serverApiInfura.infura(method, 67, ctx.card!!.wallet, "", "")
|
||||
serverApiInfura.infura(method, 67, ctx.coinData!!.wallet, "", "")
|
||||
} else
|
||||
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card
|
|||
private const val REQUEST_CODE_REQUEST_PIN2 = 3
|
||||
private const val REQUEST_CODE_VERIFY_CARD = 4
|
||||
|
||||
fun callingIntent(context: Context) = Intent(context, EmptyWalletActivity::class.java)
|
||||
fun callingIntent(context: Context, ctx: TangemContext) : Intent {
|
||||
val intent=Intent(context, EmptyWalletActivity::class.java)
|
||||
ctx.saveToIntent(intent)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
||||
private var nfcManager: NfcManager? = null
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.os.Bundle
|
|||
import android.support.v7.app.AppCompatActivity
|
||||
import com.tangem.App
|
||||
import com.tangem.di.Navigator
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.presentation.fragment.LoadedWallet
|
||||
import com.tangem.wallet.R
|
||||
import javax.inject.Inject
|
||||
|
|
@ -18,10 +19,10 @@ class LoadedWalletActivity : AppCompatActivity() {
|
|||
lateinit var navigator: Navigator
|
||||
|
||||
companion object {
|
||||
fun callingIntent(context: Context, lastTag: Tag, cardInfo: Bundle): Intent {
|
||||
fun callingIntent(context: Context, lastTag: Tag, ctx: TangemContext): Intent {
|
||||
val intent = Intent(context, LoadedWalletActivity::class.java)
|
||||
intent.putExtra(MainActivity.EXTRA_LAST_DISCOVERED_TAG, lastTag)
|
||||
intent.putExtras(cardInfo)
|
||||
ctx.saveToIntent(intent)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,13 +26,15 @@ import android.widget.Toast
|
|||
import com.scottyab.rootbeer.RootBeer
|
||||
import com.tangem.App
|
||||
import com.tangem.data.Logger
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.tangemcard.data.local.PINStorage
|
||||
import com.tangem.data.network.ServerApiCommon
|
||||
import com.tangem.tangemcard.data.DeviceNFCAntennaLocation
|
||||
import com.tangem.tangemcard.data.nfc.DeviceNFCAntennaLocation
|
||||
import com.tangem.tangemcard.tasks.ReadCardInfoTask
|
||||
import com.tangem.di.Navigator
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.data.Firmwares
|
||||
import com.tangem.tangemcard.data.local.Firmwares
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.RootFoundDialog
|
||||
|
|
@ -309,7 +311,6 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
|
|||
}
|
||||
|
||||
override fun onReadProgress(protocol: CardProtocol, progress: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onReadFinish(cardProtocol: CardProtocol?) {
|
||||
|
|
@ -320,7 +321,7 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
|
|||
rlProgressBar.post {
|
||||
rlProgressBar.visibility = View.GONE
|
||||
|
||||
// TODO - ??? remove save and load???
|
||||
// // TODO - ??? remove save and load???
|
||||
val cardInfo = Bundle()
|
||||
cardInfo.putString("UID", cardProtocol.card.uid)
|
||||
val bCard = Bundle()
|
||||
|
|
@ -331,12 +332,19 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
|
|||
val card = TangemCard(uid)
|
||||
card.loadFromBundle(cardInfo.getBundle("Card"))
|
||||
|
||||
val ctx = TangemContext(card)
|
||||
when {
|
||||
card.status == TangemCard.Status.Loaded -> lastTag?.let { navigator.showLoadedWallet(this, it, cardInfo) }
|
||||
card.status == TangemCard.Status.Empty -> navigator.showEmptyWallet(this)
|
||||
card.status == TangemCard.Status.Loaded -> lastTag?.let {
|
||||
val engineCoin = CoinEngineFactory.create(ctx) ?: throw CardProtocol.TangemException("Can't create CoinEngine!")
|
||||
engineCoin.defineWallet()
|
||||
//mCard.setWallet(Blockchain.calculateWalletAddress(mCard, pkUncompressed));
|
||||
|
||||
navigator.showLoadedWallet(this, it, ctx)
|
||||
}
|
||||
card.status == TangemCard.Status.Empty -> navigator.showEmptyWallet(this, ctx)
|
||||
card.status == TangemCard.Status.Purged -> Toast.makeText(this, R.string.erased_wallet, Toast.LENGTH_SHORT).show()
|
||||
card.status == TangemCard.Status.NotPersonalized -> Toast.makeText(this, R.string.not_personalized, Toast.LENGTH_SHORT).show()
|
||||
else -> lastTag?.let { navigator.showLoadedWallet(this, it, cardInfo) }
|
||||
else -> lastTag?.let { navigator.showLoadedWallet(this, it, ctx) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import android.widget.Button
|
|||
import com.tangem.data.fingerprint.StartFingerprintReaderTask
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.data.fingerprint.FingerprintHelper
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.tangemcard.data.local.PINStorage
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_pin_request.*
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import android.widget.Button
|
|||
import android.widget.Toast
|
||||
import com.tangem.data.fingerprint.ConfirmWithFingerprintTask
|
||||
import com.tangem.data.fingerprint.FingerprintHelper
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.tangemcard.data.local.PINStorage
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_pin_save.*
|
||||
import kotlinx.android.synthetic.main.layout_pin_buttons.*
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class PrepareCryptonitOtherApiWithdrawalActivity : AppCompatActivity(), NfcAdapt
|
|||
tvSecret.text = cryptonit!!.secretDescription
|
||||
|
||||
tvCardID.text = ctx.card!!.cidDescription
|
||||
tvWallet.text = ctx.card!!.wallet
|
||||
tvWallet.text = ctx.coinData!!.wallet
|
||||
val engine = CoinEngineFactory.create(ctx)
|
||||
|
||||
tvCurrency.text = engine!!.balanceCurrency
|
||||
|
|
@ -71,7 +71,7 @@ class PrepareCryptonitOtherApiWithdrawalActivity : AppCompatActivity(), NfcAdapt
|
|||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.cryptonit_request_withdrawal)
|
||||
|
||||
cryptonit!!.requestCryptoWithdrawal(ctx.blockchain.currency, dblAmount.toString(), ctx.card!!.wallet)
|
||||
cryptonit!!.requestCryptoWithdrawal(ctx.blockchain.currency, dblAmount.toString(), ctx.coinData!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade
|
|||
etFee.setText(cryptonit!!.fee)
|
||||
|
||||
tvCardID.text = ctx.card!!.cidDescription
|
||||
tvWallet.text = ctx.card!!.wallet
|
||||
tvWallet.text = ctx.coinData!!.wallet
|
||||
val engine = CoinEngineFactory.create(ctx)
|
||||
|
||||
tvCurrency.text = engine!!.balanceCurrency
|
||||
|
|
@ -100,7 +100,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade
|
|||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.cryptonit_request_withdrawal)
|
||||
|
||||
cryptonit!!.requestWithdrawCoins(ctx.blockchain.currency, dblAmount, ctx.card!!.wallet)
|
||||
cryptonit!!.requestWithdrawCoins(ctx.blockchain.currency, dblAmount, ctx.coinData!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa
|
|||
tvSecret.text = kraken!!.secretDescription
|
||||
|
||||
tvCardID.text = ctx.card!!.cidDescription
|
||||
tvWallet.text = ctx.card!!.wallet
|
||||
tvWallet.text = ctx.coinData!!.wallet
|
||||
val engine = CoinEngineFactory.create(ctx)
|
||||
|
||||
tvCurrency.text = engine!!.balanceCurrency
|
||||
|
|
@ -85,7 +85,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa
|
|||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.kraken_request_withdrawal)
|
||||
|
||||
kraken!!.requestWithdrawInfo(ctx.blockchain.currency, dblAmount.toString(), ctx.card!!.wallet)
|
||||
kraken!!.requestWithdrawInfo(ctx.blockchain.currency, dblAmount.toString(), ctx.coinData!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa
|
|||
tvProgressDescription.text = getString(R.string.kraken_request_withdrawal)
|
||||
|
||||
//Toast.makeText(this, String.format("Withdraw %s!",dblAmount.toString()), Toast.LENGTH_LONG).show()
|
||||
kraken!!.requestWithdraw(ctx.blockchain.currency, dblAmount.toString(), ctx.card!!.wallet)
|
||||
kraken!!.requestWithdraw(ctx.blockchain.currency, dblAmount.toString(), ctx.coinData!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
etWallet.error = null
|
||||
}
|
||||
|
||||
if (etWallet.text.toString() == ctx.card!!.wallet) {
|
||||
if (etWallet.text.toString() == ctx.coinData!!.wallet) {
|
||||
etWallet.error = getString(R.string.destination_wallet_address_equal_source_address)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet || ctx.blockchain == Blockchain.Token)
|
||||
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))
|
||||
requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.coinData!!.wallet, tx))
|
||||
else if (ctx.blockchain == Blockchain.BitcoinCash)
|
||||
requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.card!!.wallet, tx))
|
||||
requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.coinData!!.wallet, tx))
|
||||
|
||||
// request electrum listener
|
||||
val electrumBodyListener: ServerApiElectrum.ElectrumRequestDataListener = object : ServerApiElectrum.ElectrumRequestDataListener {
|
||||
|
|
@ -134,7 +134,7 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
|
||||
private fun requestInfura(method: String, contract: String) {
|
||||
if (UtilHelper.isOnline(this)) {
|
||||
serverApiInfura.infura(method, 67, ctx.card!!.wallet, contract, tx)
|
||||
serverApiInfura.infura(method, 67, ctx.coinData!!.wallet, contract, tx)
|
||||
} else
|
||||
finishWithError(getString(R.string.no_connection))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,15 @@ import android.view.KeyEvent
|
|||
import android.view.View
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import com.tangem.tangemcard.tasks.SignPaymentTask
|
||||
import com.tangem.data.nfc.SignPaymentTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.CoinEngine
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.tangemcard.tasks.SignTask
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_sign_payment.*
|
||||
|
|
@ -42,10 +44,11 @@ class SignPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card
|
|||
private var nfcManager: NfcManager? = null
|
||||
private lateinit var ctx: TangemContext
|
||||
|
||||
private var signPaymentTask: SignPaymentTask? = null
|
||||
// private var signPaymentTask: SignPaymentTask? = null
|
||||
private var signPaymentTask: SignTask? = null
|
||||
|
||||
private var amount: CoinEngine.Amount? = null
|
||||
private var fee: CoinEngine.Amount? = null
|
||||
private lateinit var amount: CoinEngine.Amount
|
||||
private lateinit var fee: CoinEngine.Amount
|
||||
private var isIncludeFee = true
|
||||
private var outAddressStr: String? = null
|
||||
private var lastReadSuccess = true
|
||||
|
|
@ -130,7 +133,16 @@ class SignPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card
|
|||
} else {
|
||||
isoDep.timeout = ctx.card!!.pauseBeforePIN2 + 65000
|
||||
}
|
||||
signPaymentTask = SignPaymentTask(this, ctx, nfcManager, isoDep, this, amount, fee, isIncludeFee, outAddressStr)
|
||||
// signPaymentTask = SignPaymentTask(this, ctx, nfcManager, isoDep, this, amount, fee, isIncludeFee, outAddressStr)
|
||||
|
||||
val coinEngine= CoinEngineFactory.create(ctx) ?: throw CardProtocol.TangemException("Can't create CoinEngine!")
|
||||
val paymentToSign = coinEngine.constructPayment(amount, fee, isIncludeFee, outAddressStr)
|
||||
|
||||
// object: SignTask.PaymentToSign {
|
||||
// override fun call(context: String?) { println("Call: $context") }
|
||||
// override fun run(context: String?) { println("Run: $context") }
|
||||
// }
|
||||
signPaymentTask = SignTask(this, ctx.card, nfcManager, isoDep, this, paymentToSign)
|
||||
signPaymentTask!!.start()
|
||||
} else {
|
||||
// Log.d(TAG, "Mismatch card UID (" + sUID + " instead of " + card!!.uid + ")")
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.App
|
|||
import com.tangem.Constant
|
||||
import com.tangem.di.Navigator
|
||||
import com.tangem.domain.wallet.CoinData
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.presentation.fragment.VerifyCard
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -19,13 +20,9 @@ class VerifyCardActivity : AppCompatActivity() {
|
|||
lateinit var navigator: Navigator
|
||||
|
||||
companion object {
|
||||
fun callingIntent(context: Context, card: TangemCard, coinData: CoinData, message: String, error: String): Intent {
|
||||
fun callingIntent(context: Context, ctx: TangemContext): Intent {
|
||||
val intent = Intent(context, VerifyCardActivity::class.java)
|
||||
intent.putExtra(TangemCard.EXTRA_UID, card.uid)
|
||||
intent.putExtra(TangemCard.EXTRA_CARD, card.asBundle)
|
||||
intent.putExtra(Constant.EXTRA_BLOCKCHAIN_DATA, coinData.asBundle())
|
||||
intent.putExtra(Constant.MESSAGE, message)
|
||||
intent.putExtra(Constant.ERROR, error)
|
||||
ctx.saveToIntent(intent)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.tangem.tangemcard.data.LocalStorage
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.tangemcard.data.local.LocalStorage
|
||||
import com.tangem.tangemcard.data.local.PINStorage
|
||||
import com.tangem.data.network.ElectrumRequest
|
||||
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.tangemcard.data.network.model.CardVerifyAndGetInfo
|
||||
import com.tangem.data.network.model.InfuraResponse
|
||||
import com.tangem.tangemcard.tasks.VerifyCardTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
|
|
@ -43,6 +43,8 @@ import com.tangem.presentation.dialog.ShowQRCodeDialog
|
|||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.tangemcard.data.network.Server
|
||||
import com.tangem.tangemcard.data.network.ServerApiTangem
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.util.UtilHelper
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -71,6 +73,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
private var serverApiCommon: ServerApiCommon = ServerApiCommon()
|
||||
private var serverApiInfura: ServerApiInfura = ServerApiInfura()
|
||||
private var serverApiElectrum: ServerApiElectrum = ServerApiElectrum()
|
||||
private var serverApiTangem: ServerApiTangem = ServerApiTangem()
|
||||
|
||||
private var singleToast: Toast? = null
|
||||
private lateinit var ctx: TangemContext
|
||||
|
|
@ -119,8 +122,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
|
||||
startVerify(lastTag)
|
||||
|
||||
tvWallet.text = ctx.card.wallet
|
||||
tvWallet.text = ctx.card.wallet
|
||||
tvWallet.text = ctx.coinData.wallet
|
||||
|
||||
// set listeners
|
||||
srl.setOnRefreshListener { refresh() }
|
||||
|
|
@ -194,7 +196,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
btnDetails.setOnClickListener {
|
||||
if (cardProtocol != null)
|
||||
// openVerifyCard(cardProtocol!!)
|
||||
(activity as LoadedWalletActivity).navigator.showVerifyCard(context as Activity, ctx.card, ctx.coinData, ctx.message, ctx.error)
|
||||
(activity as LoadedWalletActivity).navigator.showVerifyCard(context as Activity, ctx)
|
||||
|
||||
else
|
||||
showSingleToast(R.string.need_attach_card_again)
|
||||
|
|
@ -412,7 +414,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
serverApiInfura.setInfuraResponse(infuraBodyListener)
|
||||
|
||||
// request card verify and get info listener
|
||||
val cardVerifyAndGetInfoListener: ServerApiCommon.CardVerifyAndGetInfoListener = object : ServerApiCommon.CardVerifyAndGetInfoListener {
|
||||
val cardVerifyAndGetInfoListener: ServerApiTangem.CardVerifyAndGetInfoListener = object : ServerApiTangem.CardVerifyAndGetInfoListener {
|
||||
override fun onSuccess(cardVerifyAndGetArtworkResponse: CardVerifyAndGetInfo.Response?) {
|
||||
val result = cardVerifyAndGetArtworkResponse?.results!![0]
|
||||
if (result.error != null) {
|
||||
|
|
@ -438,7 +440,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")
|
||||
serverApiCommon.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), ctx.card!!)
|
||||
serverApiTangem.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), ctx.card!!)
|
||||
updateViews()
|
||||
}
|
||||
// Log.i(TAG, "setCardVerify " + it.results!![0].passed)
|
||||
|
|
@ -448,10 +450,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
|
||||
}
|
||||
}
|
||||
serverApiCommon.setCardVerifyAndGetInfoListener(cardVerifyAndGetInfoListener)
|
||||
serverApiTangem.setCardVerifyAndGetInfoListener(cardVerifyAndGetInfoListener)
|
||||
|
||||
// request artwork listener
|
||||
val artworkListener: ServerApiCommon.ArtworkListener = object : ServerApiCommon.ArtworkListener {
|
||||
val artworkListener: ServerApiTangem.ArtworkListener = object : ServerApiTangem.ArtworkListener {
|
||||
override fun onSuccess(artworkId: String?, inputStream: InputStream?, updateDate: Date?) {
|
||||
localStorage.updateArtwork(artworkId!!, inputStream!!, updateDate!!)
|
||||
ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(ctx.card!!))
|
||||
|
|
@ -461,7 +463,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
|
||||
}
|
||||
}
|
||||
serverApiCommon.setArtworkListener(artworkListener)
|
||||
serverApiTangem.setArtworkListener(artworkListener)
|
||||
|
||||
// request rate info listener
|
||||
serverApiCommon.setRateInfoData {
|
||||
|
|
@ -755,6 +757,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
tvBalanceEquivalent.text = ""
|
||||
} else {
|
||||
val validator = BalanceValidator()
|
||||
// TODO why attest=false?
|
||||
validator.Check(ctx, false)
|
||||
context?.let { ContextCompat.getColor(it, validator.color) }?.let { tvBalanceLine1.setTextColor(it) }
|
||||
tvBalanceLine1.text = validator.firstLine
|
||||
|
|
@ -775,7 +778,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
else -> tvBalance.text = getString(R.string.no_data_string)
|
||||
}
|
||||
|
||||
tvWallet.text = ctx.card!!.wallet
|
||||
tvWallet.text = ctx.coinData!!.wallet
|
||||
|
||||
if (ctx.card!!.tokenSymbol.length > 1) {
|
||||
val html = Html.fromHtml(ctx.card!!.blockchainName)
|
||||
|
|
@ -813,8 +816,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
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))
|
||||
requestElectrum(ElectrumRequest.checkBalance(ctx.coinData!!.wallet))
|
||||
requestElectrum(ElectrumRequest.listUnspent(ctx.coinData!!.wallet))
|
||||
requestRateInfo("bitcoin")
|
||||
}
|
||||
|
||||
|
|
@ -823,8 +826,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
ctx.coinData.setIsBalanceEqual(true)
|
||||
val engine = CoinEngineFactory.create(ctx)
|
||||
|
||||
requestElectrum(ElectrumRequest.checkBalance((engine as BtcCashEngine).convertToLegacyAddress(ctx.card!!.wallet)))
|
||||
requestElectrum(ElectrumRequest.listUnspent(engine.convertToLegacyAddress(ctx.card!!.wallet)))
|
||||
requestElectrum(ElectrumRequest.checkBalance((engine as BtcCashEngine).convertToLegacyAddress(ctx.coinData!!.wallet)))
|
||||
requestElectrum(ElectrumRequest.listUnspent(engine.convertToLegacyAddress(ctx.coinData!!.wallet)))
|
||||
requestRateInfo("bitcoin-cash")
|
||||
}
|
||||
|
||||
|
|
@ -857,7 +860,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
private fun requestInfura(method: String, contract: String) {
|
||||
if (UtilHelper.isOnline(context as Activity)) {
|
||||
requestCounter++
|
||||
serverApiInfura.infura(method, 67, ctx.card!!.wallet, contract, "")
|
||||
serverApiInfura.infura(method, 67, ctx.coinData!!.wallet, contract, "")
|
||||
} else {
|
||||
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
||||
srl?.isRefreshing = false
|
||||
|
|
@ -867,7 +870,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
private fun requestVerifyAndGetInfo() {
|
||||
if (UtilHelper.isOnline(context as Activity)) {
|
||||
if ((ctx.card!!.isOnlineVerified == null || !ctx.card!!.isOnlineVerified)) {
|
||||
serverApiCommon.cardVerifyAndGetInfo(ctx.card)
|
||||
serverApiTangem.cardVerifyAndGetInfo(ctx.card)
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
||||
|
|
@ -945,7 +948,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
Toast.makeText(activity, R.string.copied_clipboard, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
} else {
|
||||
val txtShare = ctx.card.wallet
|
||||
val txtShare = ctx.coinData.wallet
|
||||
val clipboard = activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.primaryClip = ClipData.newPlainText(txtShare, txtShare)
|
||||
Toast.makeText(activity, R.string.copied_clipboard, Toast.LENGTH_LONG).show()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.Toast
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.tangemcard.data.local.PINStorage
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.*
|
||||
import com.tangem.presentation.activity.CreateNewWalletActivity
|
||||
|
|
@ -387,7 +387,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback {
|
|||
imgDeveloperVersion.visibility = View.INVISIBLE
|
||||
|
||||
if (ctx.card!!.status == TangemCard.Status.Loaded) {
|
||||
tvWallet.text = ctx.card!!.shortWalletString
|
||||
tvWallet.text = ctx.coinData!!.shortWalletString
|
||||
if (ctx.card!!.isWalletPublicKeyValid) {
|
||||
tvWalletIdentity.setText(R.string.possession_proved)
|
||||
tvWalletIdentity.setTextColor(ContextCompat.getColor(context!!, R.color.confirmed))
|
||||
|
|
|
|||
|
|
@ -35,19 +35,16 @@ dependencies {
|
|||
implementation 'com.scottyab:rootbeer-lib:0.0.7'
|
||||
|
||||
// implementation 'com.android.support:support-compat:28.0.0'
|
||||
// implementation 'com.android.support:cardview-v7:28.0.0'
|
||||
// implementation 'com.android.support:support-v4:28.0.0'
|
||||
// implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
// implementation 'com.google.zxing:core:3.3.3'
|
||||
// implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
|
||||
// implementation 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||
// implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||
// implementation 'com.skyfishjy.ripplebackground:library:1.0.1'
|
||||
// implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
|
||||
// implementation 'com.google.dagger:dagger:2.16'
|
||||
implementation 'com.google.dagger:dagger:2.16'
|
||||
implementation 'org.bitcoinj:bitcoinj-parent:0.14.7'
|
||||
implementation 'org.bitcoinj:bitcoinj-core:0.14.7'
|
||||
// implementation 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.16'
|
||||
// implementation 'info.hoang8f:android-segmented:1.0.6'
|
||||
// implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
|
||||
// implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application>
|
||||
<application
|
||||
>
|
||||
<!--<provider-->
|
||||
<!--android:name="com.tangem.data.LogFileProvider"-->
|
||||
<!--android:authorities="@string/log_file_provider_authorities"-->
|
||||
|
|
|
|||
24
tangemcard/src/main/java/com/tangem/tangemcard/App.java
Normal file
24
tangemcard/src/main/java/com/tangem/tangemcard/App.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.tangemcard;
|
||||
|
||||
import android.support.v7.app.AppCompatDelegate;
|
||||
|
||||
import com.tangem.tangemcard.di.DaggerNetworkComponent;
|
||||
import com.tangem.tangemcard.di.NetworkComponent;
|
||||
|
||||
public class App {
|
||||
public App() {
|
||||
super();
|
||||
}
|
||||
|
||||
static {
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
||||
networkComponent = DaggerNetworkComponent.create();
|
||||
}
|
||||
|
||||
private static NetworkComponent networkComponent;
|
||||
|
||||
public static NetworkComponent getNetworkComponent() {
|
||||
return networkComponent;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import android.content.Context;
|
|||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.tangem.tangemcard.reader.CardCrypto;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.os.Bundle;
|
|||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.reader.SettingsMask;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
|
|
@ -463,7 +464,9 @@ public class TangemCard {
|
|||
Sign_Hash(0, "sign hash"),
|
||||
Sign_Raw(1, "sign raw tx"),
|
||||
Sign_Hash_Validated_By_Issuer(2, "sign hash validated by issuer"),
|
||||
Sign_Raw_Validated_By_Issuer(3, "sign raw tx validated by issuer");
|
||||
Sign_Raw_Validated_By_Issuer(3, "sign raw tx validated by issuer"),
|
||||
Sign_Hash_Validated_By_Issuer_And_WriteIssuerData(4, "sign hash validated by issuer and write issuer data"),
|
||||
Sign_Raw_Validated_By_Issuer_And_WriteIssuerData(5, "sign raw tx validated by issuer and write issuer data");
|
||||
|
||||
int ID;
|
||||
String mDescription;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tangemcard.data;
|
||||
package com.tangem.tangemcard.data.local;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tangemcard.data
|
||||
package com.tangem.tangemcard.data.local
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
|
|
@ -10,11 +10,11 @@ import android.util.Log
|
|||
import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.tangem.data.network.model.CardVerifyAndGetInfo
|
||||
import com.tangem.tangemcard.data.network.model.CardVerifyAndGetInfo
|
||||
import com.tangem.tangemcard.R
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.tangemcard.reader.CardCrypto
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import java.io.InputStream
|
||||
import java.lang.Exception
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tangemcard.data;
|
||||
package com.tangem.tangemcard.data.local;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.tangemcard.data.network;
|
||||
|
||||
public class Server {
|
||||
/**
|
||||
* https://tangem-webapp.appspot.com/
|
||||
* https://tangem-services.appspot.com/
|
||||
*/
|
||||
public static class ApiTangem {
|
||||
public static final String URL_TANGEM = ServerURL.API_TANGEM;
|
||||
|
||||
public static class Method {
|
||||
static final String VERIFY = URL_TANGEM + "verify";
|
||||
static final String VERIFY_AND_GET_INFO = URL_TANGEM + "card/verify-and-get-info";
|
||||
static final String ARTWORK = URL_TANGEM + "card/artwork";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package com.tangem.tangemcard.data.network;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.App;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.data.network.model.CardVerifyAndGetInfo;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class ServerApiTangem {
|
||||
private static String TAG = ServerApiTangem.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Card verify
|
||||
*/
|
||||
private CardVerifyAndGetInfoListener cardVerifyAndGetInfoListener;
|
||||
|
||||
public interface CardVerifyAndGetInfoListener {
|
||||
void onSuccess(CardVerifyAndGetInfo.Response cardVerifyAndGetArtworkResponse);
|
||||
void onFail(String message);
|
||||
}
|
||||
|
||||
public void setCardVerifyAndGetInfoListener(CardVerifyAndGetInfoListener listener) {
|
||||
cardVerifyAndGetInfoListener = listener;
|
||||
}
|
||||
|
||||
public void cardVerifyAndGetInfo(TangemCard card) {
|
||||
TangemApi tangemApi = App.getNetworkComponent().getRetrofitTangem().create(TangemApi.class);
|
||||
|
||||
List<CardVerifyAndGetInfo.Request.Item> requests = new ArrayList<>();
|
||||
requests.add(new CardVerifyAndGetInfo.Request.Item(Util.bytesToHex(card.getCID()), Util.bytesToHex(card.getCardPublicKey())));
|
||||
|
||||
CardVerifyAndGetInfo.Request requestBody = new CardVerifyAndGetInfo.Request(requests);
|
||||
|
||||
Call<CardVerifyAndGetInfo.Response> call = tangemApi.getCardVerifyAndGetInfo(requestBody);
|
||||
call.enqueue(new Callback<CardVerifyAndGetInfo.Response>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<CardVerifyAndGetInfo.Response> call, @NonNull Response<CardVerifyAndGetInfo.Response> response) {
|
||||
if (response.code() == 200) {
|
||||
CardVerifyAndGetInfo.Response cardVerifyAndGetArtworkResponse = response.body();
|
||||
cardVerifyAndGetInfoListener.onSuccess(cardVerifyAndGetArtworkResponse);
|
||||
Log.i(TAG, "cardVerifyAndGeInfo onResponse " + response.code());
|
||||
} else {
|
||||
cardVerifyAndGetInfoListener.onFail(String.valueOf(response.code()));
|
||||
Log.e(TAG, "cardVerifyAndGetInfo onResponse " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<CardVerifyAndGetInfo.Response> call, @NonNull Throwable t) {
|
||||
cardVerifyAndGetInfoListener.onFail(t.getMessage());
|
||||
Log.e(TAG, "cardVerifyAndGetInfo onFailure " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Last version request from GitHub
|
||||
*/
|
||||
private ArtworkListener artworkListener;
|
||||
|
||||
public interface ArtworkListener {
|
||||
void onSuccess(String artworkId, InputStream inputStream, Date updateDate);
|
||||
void onFail(String message);
|
||||
}
|
||||
|
||||
public void setArtworkListener(ArtworkListener listener) {
|
||||
artworkListener = listener;
|
||||
}
|
||||
|
||||
public void requestArtwork(final String artworkId, final Date updateDate, TangemCard card) {
|
||||
TangemApi tangemApi = App.getNetworkComponent().getRetrofitTangem().create(TangemApi.class);
|
||||
|
||||
Call<ResponseBody> call = tangemApi.getArtwork(artworkId, Util.bytesToHex(card.getCID()), Util.bytesToHex(card.getCardPublicKey()));
|
||||
call.enqueue(new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
|
||||
Log.i(TAG, "getArtwork onResponse " + response.code());
|
||||
if (response.code() == 200) {
|
||||
try {
|
||||
ResponseBody body = response.body();
|
||||
if (body != null) {
|
||||
artworkListener.onSuccess(artworkId, body.byteStream(), updateDate);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
|
||||
artworkListener.onFail(t.getMessage());
|
||||
Log.e(TAG, "getArtwork onFailure " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tangem.tangemcard.data.network;
|
||||
|
||||
class ServerURL {
|
||||
static final String API_TANGEM = "https://verify.tangem.com/";
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.data.network;
|
||||
package com.tangem.tangemcard.data.network;
|
||||
|
||||
import com.tangem.data.network.model.CardVerifyAndGetInfo;
|
||||
import com.tangem.tangemcard.data.network.model.CardVerifyAndGetInfo;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.data.network.model;
|
||||
package com.tangem.tangemcard.data.network.model;
|
||||
|
||||
public class CardVerify {
|
||||
private String CID;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.data.network.model
|
||||
package com.tangem.tangemcard.data.network.model
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tangemcard.data
|
||||
package com.tangem.tangemcard.data.nfc
|
||||
|
||||
import android.os.Build
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tangemcard.data
|
||||
package com.tangem.tangemcard.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),
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.tangemcard.di;
|
||||
|
||||
import com.tangem.tangemcard.data.network.Server;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = {NetworkModule.class})
|
||||
public interface NetworkComponent {
|
||||
|
||||
@Named(Server.ApiTangem.URL_TANGEM)
|
||||
Retrofit getRetrofitTangem();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.tangem.tangemcard.di;
|
||||
|
||||
import com.tangem.tangemcard.data.network.Server;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
@Module
|
||||
class NetworkModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
@Named(Server.ApiTangem.URL_TANGEM)
|
||||
Retrofit provideRetrofitTangem() {
|
||||
return new Retrofit.Builder()
|
||||
.baseUrl(Server.ApiTangem.URL_TANGEM)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.client(createOkHttpClient())
|
||||
.build();
|
||||
}
|
||||
|
||||
private OkHttpClient createOkHttpClient() {
|
||||
return new OkHttpClient.Builder().
|
||||
addInterceptor(createHttpLoggingInterceptor()).
|
||||
build();
|
||||
}
|
||||
|
||||
private HttpLoggingInterceptor createHttpLoggingInterceptor() {
|
||||
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
|
||||
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
return logging;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.presentation.dialog
|
||||
package com.tangem.tangemcard.presentation.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Intent
|
||||
|
|
@ -8,7 +8,7 @@ import android.support.v4.app.DialogFragment
|
|||
|
||||
import android.support.v7.app.AlertDialog
|
||||
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.tangemcard.R
|
||||
|
||||
class NfcEnableDialog : DialogFragment() {
|
||||
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tangemcard.reader;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.util.PBKDF2;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||
|
|
|
|||
|
|
@ -6,17 +6,14 @@ import android.nfc.TagLostException;
|
|||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.data.Issuer;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.data.Firmwares;
|
||||
import com.tangem.tangemcard.data.LocalStorage;
|
||||
import com.tangem.tangemcard.data.local.Firmwares;
|
||||
import com.tangem.tangemcard.data.Manufacturer;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import org.spongycastle.jce.ECNamedCurveTable;
|
||||
import org.spongycastle.jce.interfaces.ECPublicKey;
|
||||
import org.spongycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
|
@ -26,8 +23,6 @@ import java.security.KeyPairGenerator;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.util.Calendar;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.crypto.KeyAgreement;
|
||||
|
||||
|
|
@ -499,7 +494,7 @@ public class CardProtocol {
|
|||
// * @throws Exception if something went wrong
|
||||
// */
|
||||
// public void run_Read() throws Exception {
|
||||
// run_Read1(true);
|
||||
// run_Read(true);
|
||||
// }
|
||||
|
||||
/**
|
||||
|
|
@ -515,7 +510,7 @@ public class CardProtocol {
|
|||
*
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
public void run_Read1() throws Exception {
|
||||
public void run_Read() throws Exception {
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.Read);
|
||||
Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" ")));
|
||||
|
||||
|
|
@ -811,37 +806,44 @@ public class CardProtocol {
|
|||
* See [1] 8.6
|
||||
* @param PIN2 - PIN2 code to confirm operation
|
||||
* @param hashes - array of digests to sign (max 10 digest at a time)
|
||||
* @param UseIssuerValidation - if card need issuer validation before sign (true for SigningMethod=2,4)
|
||||
* @param issuerTransactionSignature - signature of hashes, if card need issuer validation before sign (for SigningMethod=2)
|
||||
* @param issuerData - new issuerData to write on card (only for SigningMethod=4, null for other)
|
||||
* @param issuer - issuer (need only for SigningMethod=2,4)
|
||||
* @param issuerDataSignature - signature of issuerData, if issuerData specified(for SigningMethod=4)
|
||||
* @return TLVList with card answer contained wallet signatures of digests from hashes array (in case of success)
|
||||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
// TODO - change function to run_SignHashes(String PIN2, byte[][] hashes, byte[] issuerData, byte[] issuerTransactionSignature) because normally issuer signature can be obtained only by external server
|
||||
public TLVList run_SignHashes(String PIN2, byte[][] hashes, boolean UseIssuerValidation, byte[] issuerData, Issuer issuer) throws Exception {
|
||||
public TLVList run_SignHashes(String PIN2, byte[][] hashes, byte[] issuerTransactionSignature, byte[] issuerData, byte[] issuerDataSignature) throws Exception {
|
||||
if ( mCard.getSigningMethod()!=TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer && mCard.getSigningMethod()!=TangemCard.SigningMethod.Sign_Hash ){
|
||||
throw new TangemException("Card don't support signing hashes!");
|
||||
}
|
||||
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
if (hashes.length > 10) throw new Exception("To much hashes in one transaction!");
|
||||
if (hashes.length > 10) throw new TangemException("To much hashes in one transaction!");
|
||||
for (int i = 0; i < hashes.length; i++) {
|
||||
if (i != 0 && hashes[0].length != hashes[i].length)
|
||||
throw new Exception("Hashes length must be identical!");
|
||||
throw new TangemException("Hashes length must be identical!");
|
||||
bs.write(hashes[i]);
|
||||
}
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.Sign);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_PIN2, Util.calculateSHA256(PIN2));
|
||||
rqApdu.addTLV_U8(TLV.Tag.TAG_TrOut_HashSize, hashes[0].length);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_TrOut_Hash, bs.toByteArray());
|
||||
if (UseIssuerValidation) {
|
||||
byte[] issuerSignature = CardCrypto.Signature(issuer.getPrivateTransactionKey(), bs.toByteArray());
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Transaction_Signature, issuerSignature);
|
||||
}
|
||||
if (issuerData != null) {
|
||||
if (issuer == null || issuer == Issuer.Unknown())
|
||||
throw new Exception("Need known Issuer to write issuer Data");
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Data, issuerData);
|
||||
byte[] issuerSignature = CardCrypto.Signature(issuer.getPrivateTransactionKey(), issuerData);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Data_Signature, issuerSignature);
|
||||
}
|
||||
if ( mCard.getSigningMethod()!=TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer_And_WriteIssuerData )
|
||||
throw new TangemException("Card don't support simultaneous sign with write issuer data!");
|
||||
|
||||
if (issuerDataSignature == null )
|
||||
throw new TangemException("Card require issuer validation before write issuer data");
|
||||
bs.write(issuerData);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Data, issuerData);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Data_Signature, issuerDataSignature);
|
||||
}
|
||||
if (issuerTransactionSignature!=null) {
|
||||
//byte[] issuerSignature = CardCrypto.Signature(issuer.getPrivateTransactionKey(), bs.toByteArray());
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Transaction_Signature, issuerTransactionSignature);
|
||||
}else if ( mCard.getSigningMethod()==TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer ){
|
||||
throw new TangemException("Card require issuer validation before sign the transaction!");
|
||||
}
|
||||
|
||||
Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" ")));
|
||||
|
||||
|
|
@ -868,19 +870,42 @@ public class CardProtocol {
|
|||
* SIGN raw tx - SigningMethod=1 (see {@link TangemCard.SigningMethod})
|
||||
* See [1] 8.6
|
||||
* @param PIN2 - PIN2 code to confirm operation
|
||||
* @param hashAlgID - name of hash alg, used for signature
|
||||
* @param bTxOutData - part of raw transaction to sign
|
||||
* @param issuerTransactionSignature - signature of hashes, if card need issuer validation before sign (for SigningMethod=2)
|
||||
* @param issuerData - new issuerData to write on card (only for SigningMethod=4, null for other)
|
||||
* @param issuerDataSignature - signature of issuerData, if issuerData specified(for SigningMethod=4)
|
||||
* @return TLVList with card answer contained wallet signatures of bTxOutData(in case of success)
|
||||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
// TODO - change function to run_SignRaw(String PIN2, String hashAlgID, byte[] bTxOutData, byte[] issuerData, byte[] issuerTransactionSignature) to support all signing methods
|
||||
public TLVList run_SignRaw(String PIN2, byte[] bTxOutData) throws Exception {
|
||||
public TLVList run_SignRaw(String PIN2, String hashAlgID, byte[] bTxOutData, byte[] issuerTransactionSignature, byte[] issuerData, byte[] issuerDataSignature) throws Exception {
|
||||
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.Sign);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_PIN2, Util.calculateSHA256(PIN2));
|
||||
rqApdu.addTLV(TLV.Tag.TAG_TrOut_Raw, bTxOutData);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_HashAlgID, "sha-256x2".getBytes("US-ASCII"));
|
||||
rqApdu.addTLV(TLV.Tag.TAG_HashAlgID, hashAlgID.getBytes("US-ASCII"));
|
||||
Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" ")));
|
||||
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
if (bTxOutData.length > 1024) throw new TangemException("Raw transaction size is to big!");
|
||||
bs.write(bTxOutData);
|
||||
|
||||
if (issuerData != null) {
|
||||
if ( mCard.getSigningMethod()!=TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer_And_WriteIssuerData )
|
||||
throw new TangemException("Card don't support simultaneous sign with write issuer data!");
|
||||
|
||||
if (issuerDataSignature == null )
|
||||
throw new TangemException("Card require issuer validation before write issuer data");
|
||||
bs.write(issuerData);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Data, issuerData);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Data_Signature, issuerDataSignature);
|
||||
}
|
||||
if (issuerTransactionSignature!=null) {
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Transaction_Signature, issuerTransactionSignature);
|
||||
}else if ( mCard.getSigningMethod()==TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer ){
|
||||
throw new TangemException("Card require issuer validation before sign the transaction!");
|
||||
}
|
||||
|
||||
ResponseApdu rspApdu = SendAndReceive(rqApdu, false);
|
||||
|
||||
if (rspApdu.isStatus(SW.PROCESS_COMPLETED)) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import android.os.Bundle;
|
|||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.tangem.presentation.dialog.NfcEnableDialog;
|
||||
import com.tangem.tangemcard.presentation.dialog.NfcEnableDialog;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Arrays;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ package com.tangem.tangemcard.reader;
|
|||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
|
|
|||
|
|
@ -6,95 +6,31 @@ import android.util.Log;
|
|||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
public class CreateNewWalletTask extends Thread {
|
||||
public class CreateNewWalletTask extends CustomReadCardTask {
|
||||
public static final String TAG = CreateNewWalletTask.class.getSimpleName();
|
||||
|
||||
private Context mContext;
|
||||
private TangemCard mCard;
|
||||
private NfcManager mNfcManager;
|
||||
private IsoDep mIsoDep;
|
||||
private CardProtocol.Notifications mNotifications;
|
||||
private boolean isCancelled = false;
|
||||
|
||||
public CreateNewWalletTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
mCard = card;
|
||||
mContext = context;
|
||||
mNfcManager = nfcManager;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
super(context, card, nfcManager, isoDep, notifications);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mIsoDep == null) {
|
||||
return;
|
||||
}
|
||||
CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications);
|
||||
mNotifications.onReadStart(protocol);
|
||||
try {
|
||||
// for Samsung's bugs -
|
||||
// Workaround for the Samsung Galaxy S5 (since the
|
||||
// first connection always hangs on transceive).
|
||||
int timeout = mIsoDep.getTimeout();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.close();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.setTimeout(timeout);
|
||||
try {
|
||||
mNotifications.onReadProgress(protocol, 5);
|
||||
public void run_Task() throws Exception {
|
||||
mNotifications.onReadProgress(protocol, 20);
|
||||
protocol.run_VerifyCard();
|
||||
|
||||
Log.i(TAG, "[-- Start create new wallet --]");
|
||||
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
|
||||
|
||||
if (isCancelled) return;
|
||||
protocol.run_VerifyCard();
|
||||
mNotifications.onReadProgress(protocol, 30);
|
||||
if (isCancelled) return;
|
||||
protocol.run_CreateWallet(PINStorage.getPIN2());
|
||||
mNotifications.onReadProgress(protocol, 60);
|
||||
if (isCancelled) return;
|
||||
|
||||
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
|
||||
|
||||
mNotifications.onReadProgress(protocol, 30);
|
||||
if (isCancelled) return;
|
||||
|
||||
// if (mCard.getPauseBeforePIN2() > 0) {
|
||||
// mNotifications.onReadWait(mCard.getPauseBeforePIN2());
|
||||
// }
|
||||
// try {
|
||||
protocol.run_CreateWallet(PINStorage.getPIN2());
|
||||
// } finally {
|
||||
// mNotifications.onReadWait(0);
|
||||
// }
|
||||
mNotifications.onReadProgress(protocol, 60);
|
||||
if (isCancelled) return;
|
||||
|
||||
protocol.run_Read();
|
||||
|
||||
} finally {
|
||||
mNfcManager.ignoreTag(mIsoDep.getTag());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
protocol.setError(e);
|
||||
|
||||
} finally {
|
||||
Log.i(TAG, "[-- Finish create new wallet --]");
|
||||
mNotifications.onReadFinish(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel(Boolean AllowInterrupt) {
|
||||
try {
|
||||
if (isAlive()) {
|
||||
isCancelled = true;
|
||||
join(500);
|
||||
}
|
||||
if (isAlive() && AllowInterrupt) {
|
||||
interrupt();
|
||||
mNotifications.onReadCancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
protocol.run_Read();
|
||||
parseReadResult();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,9 +5,9 @@ import android.nfc.tech.IsoDep;
|
|||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.data.Issuer;
|
||||
import com.tangem.tangemcard.data.LocalStorage;
|
||||
import com.tangem.tangemcard.data.local.LocalStorage;
|
||||
import com.tangem.tangemcard.data.Manufacturer;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
|
|
@ -21,6 +21,7 @@ import org.spongycastle.jce.spec.ECNamedCurveParameterSpec;
|
|||
import org.spongycastle.math.ec.ECPoint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
|
|
@ -112,6 +113,7 @@ public class CustomReadCardTask extends Thread {
|
|||
* @throws CardProtocol.TangemException - if something went wrong
|
||||
*/
|
||||
public void parseReadResult() throws CardProtocol.TangemException {
|
||||
if( mCard==null ) mCard=protocol.getCard();
|
||||
// These tags always present in the parsed response: TAG_Status, TAG_CID, TAG_Manufacture_ID, TAG_Health, TAG_Firmware
|
||||
TLV tlvStatus = protocol.getReadResult().getTLV(TLV.Tag.TAG_Status);
|
||||
mCard.setStatus(TangemCard.Status.fromCode(Util.byteArrayToInt(tlvStatus.Value)));
|
||||
|
|
@ -256,19 +258,6 @@ public class CustomReadCardTask extends Thread {
|
|||
mCard.setWalletPublicKey(pkUncompressed);
|
||||
mCard.setWalletPublicKeyRar(pkCompresses);
|
||||
|
||||
// TODO - store in mCard only public key, not wallet address, move wallet address to coinData
|
||||
// TangemContext ctx = new TangemContext(mCard);
|
||||
// try {
|
||||
// CoinEngine engineCoin = CoinEngineFactory.INSTANCE.create(ctx);
|
||||
// if (engineCoin == null) throw new Exception("Can't create CoinEngine!");
|
||||
// String wallet = engineCoin.calculateAddress(pkUncompressed);
|
||||
// mCard.setWallet(wallet);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// throw new TangemException("Can't define wallet address");
|
||||
// }
|
||||
//mCard.setWallet(Blockchain.calculateWalletAddress(mCard, pkUncompressed));
|
||||
|
||||
mCard.setRemainingSignatures(protocol.getReadResult().getTagAsInt(TLV.Tag.TAG_RemainingSignatures));
|
||||
|
||||
if (protocol.getReadResult() != null && protocol.getReadResult().getTLV(TLV.Tag.TAG_SignedHashes) != null) {
|
||||
|
|
@ -348,7 +337,7 @@ public class CustomReadCardTask extends Thread {
|
|||
if (protocol.getCard().encryptionMode != TangemCard.EncryptionMode.None) {
|
||||
protocol.CreateProtocolKey();
|
||||
}
|
||||
protocol.run_Read1();
|
||||
protocol.run_Read();
|
||||
// After first successful read, data will be parsed into TangemCard object
|
||||
parseReadResult();
|
||||
|
||||
|
|
@ -375,9 +364,9 @@ public class CustomReadCardTask extends Thread {
|
|||
public void run_SecondTimeRead() throws Exception {
|
||||
String PIN = mCard.getPIN();
|
||||
protocol.setPIN(PIN);
|
||||
protocol.run_Read1();
|
||||
protocol.run_Read();
|
||||
PINStorage.setLastUsedPIN(PIN);
|
||||
if (!mCard.getCID().equals(protocol.getReadResult().getTLV(TLV.Tag.TAG_CardID))) {
|
||||
if (!Arrays.equals(mCard.getCID(),protocol.getReadResult().getTLV(TLV.Tag.TAG_CardID).Value)) {
|
||||
throw new CardProtocol.TangemException("Card must be the same. Reading attempt on different card!");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import android.nfc.tech.IsoDep;
|
|||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
public class PurgeTask extends CustomReadCardTask {
|
||||
|
|
@ -22,7 +22,7 @@ public class PurgeTask extends CustomReadCardTask {
|
|||
}
|
||||
protocol.run_PurgeWallet(PINStorage.getPIN2());
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
protocol.run_Read1();
|
||||
protocol.run_Read();
|
||||
mNotifications.onReadProgress(protocol, 100);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.tangemcard.reader.TLVList;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class SignTask extends CustomReadCardTask {
|
||||
public static final String TAG = SignTask.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Payment Engine request/notifications during sign process
|
||||
*/
|
||||
public interface PaymentToSign {
|
||||
boolean isSigningMethodSupported(TangemCard.SigningMethod signingMethod);
|
||||
|
||||
byte[][] getHashesToSign();
|
||||
|
||||
byte[] getRawDataToSign();
|
||||
|
||||
String getHashAlgToSign();
|
||||
|
||||
byte[] getIssuerTransactionSignature(byte[] dataToSignByIssuer);
|
||||
|
||||
void OnSignCompleted(byte[] signature);
|
||||
}
|
||||
|
||||
private PaymentToSign paymentToSign;
|
||||
|
||||
public SignTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications, PaymentToSign paymentToSign) {
|
||||
super(context, card, nfcManager, isoDep, notifications);
|
||||
this.paymentToSign = paymentToSign;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run_Task() throws Exception {
|
||||
protocol.run_VerifyCard();
|
||||
|
||||
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
|
||||
|
||||
mNotifications.onReadProgress(protocol, 30);
|
||||
if (isCancelled) return;
|
||||
|
||||
if (mCard.getPauseBeforePIN2() > 0) {
|
||||
mNotifications.onReadWait(mCard.getPauseBeforePIN2());
|
||||
}
|
||||
|
||||
if (!paymentToSign.isSigningMethodSupported(mCard.getSigningMethod())) {
|
||||
throw new CardProtocol.TangemException("Signing method isn't supported!");
|
||||
}
|
||||
|
||||
TLVList signResult;
|
||||
switch (mCard.getSigningMethod()) {
|
||||
case Sign_Hash:
|
||||
signResult = protocol.run_SignHashes(PINStorage.getPIN2(), paymentToSign.getHashesToSign(), null, null, null);
|
||||
break;
|
||||
case Sign_Hash_Validated_By_Issuer:
|
||||
case Sign_Hash_Validated_By_Issuer_And_WriteIssuerData:
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
byte[][] hashes = paymentToSign.getHashesToSign();
|
||||
if (hashes.length > 10) throw new CardProtocol.TangemException("To much hashes in one transaction!");
|
||||
for (int i = 0; i < hashes.length; i++) {
|
||||
if (i != 0 && hashes[0].length != hashes[i].length)
|
||||
throw new CardProtocol.TangemException("Hashes length must be identical!");
|
||||
bs.write(hashes[i]);
|
||||
}
|
||||
signResult = protocol.run_SignHashes(PINStorage.getPIN2(), hashes, paymentToSign.getIssuerTransactionSignature(bs.toByteArray()), null, null);
|
||||
break;
|
||||
case Sign_Raw:
|
||||
signResult = protocol.run_SignRaw(PINStorage.getPIN2(), paymentToSign.getHashAlgToSign(), paymentToSign.getRawDataToSign(), null, null, null);
|
||||
break;
|
||||
case Sign_Raw_Validated_By_Issuer:
|
||||
case Sign_Raw_Validated_By_Issuer_And_WriteIssuerData:
|
||||
byte[] txOut = paymentToSign.getRawDataToSign();
|
||||
signResult = protocol.run_SignRaw(PINStorage.getPIN2(), paymentToSign.getHashAlgToSign(), txOut, paymentToSign.getIssuerTransactionSignature(txOut), null, null);
|
||||
break;
|
||||
default:
|
||||
throw new CardProtocol.TangemException("Signing method isn't supported!");
|
||||
}
|
||||
|
||||
paymentToSign.OnSignCompleted(signResult.getTLV(TLV.Tag.TAG_Signature).Value);
|
||||
mNotifications.onReadProgress(protocol, 100);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2,105 +2,40 @@ package com.tangem.tangemcard.tasks;
|
|||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.local.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
public class SwapPINTask extends Thread {
|
||||
public class SwapPINTask extends CustomReadCardTask {
|
||||
public static final String TAG = SwapPINTask.class.getSimpleName();
|
||||
|
||||
private Context mContext;
|
||||
private TangemCard mCard;
|
||||
private NfcManager mNfcManager;
|
||||
private String newPIN, newPIN2;
|
||||
private IsoDep mIsoDep;
|
||||
private CardProtocol.Notifications mNotifications;
|
||||
private boolean isCancelled = false;
|
||||
|
||||
public SwapPINTask(Context context, TangemCard card, NfcManager nfcManager, String newPIN, String newPIN2, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
super(context, card, nfcManager, isoDep, notifications);
|
||||
this.newPIN = newPIN;
|
||||
this.newPIN2 = newPIN2;
|
||||
mCard = card;
|
||||
mContext = context;
|
||||
mNfcManager = nfcManager;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mIsoDep == null) {
|
||||
return;
|
||||
public void run_Task() throws Exception {
|
||||
|
||||
if (mCard.getPauseBeforePIN2() > 0) {
|
||||
mNotifications.onReadWait(mCard.getPauseBeforePIN2());
|
||||
}
|
||||
CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications);
|
||||
|
||||
mNotifications.onReadStart(protocol);
|
||||
try {
|
||||
protocol.run_SetPIN(PINStorage.getPIN2(), newPIN, newPIN2, false);
|
||||
protocol.setPIN(newPIN);
|
||||
mCard.setPIN(newPIN);
|
||||
|
||||
// for Samsung's bugs -
|
||||
// Workaround for the Samsung Galaxy S5 (since the
|
||||
// first connection always hangs on transceive).
|
||||
int timeout = mIsoDep.getTimeout();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.close();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.setTimeout(timeout);
|
||||
try {
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
|
||||
mNotifications.onReadProgress(protocol, 5);
|
||||
protocol.run_Read();
|
||||
|
||||
Log.i(TAG, "[-- Start swap pin --]");
|
||||
mNotifications.onReadProgress(protocol, 100);
|
||||
|
||||
if (isCancelled) return;
|
||||
|
||||
if (mCard.getPauseBeforePIN2() > 0) {
|
||||
mNotifications.onReadWait(mCard.getPauseBeforePIN2());
|
||||
}
|
||||
|
||||
// try {
|
||||
protocol.run_SetPIN(PINStorage.getPIN2(), newPIN, newPIN2, false);
|
||||
protocol.setPIN(newPIN);
|
||||
mCard.setPIN(newPIN);
|
||||
// } finally {
|
||||
// mNotifications.onReadWait(0);
|
||||
// }
|
||||
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
|
||||
protocol.run_Read();
|
||||
|
||||
mNotifications.onReadProgress(protocol, 100);
|
||||
|
||||
} finally {
|
||||
mNfcManager.ignoreTag(mIsoDep.getTag());
|
||||
mNotifications.onReadWait(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
protocol.setError(e);
|
||||
|
||||
} finally {
|
||||
Log.i(TAG, "[-- Finish purge --]");
|
||||
mNotifications.onReadFinish(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel(Boolean AllowInterrupt) {
|
||||
try {
|
||||
if (isAlive()) {
|
||||
isCancelled = true;
|
||||
join(500);
|
||||
}
|
||||
if (isAlive() && AllowInterrupt) {
|
||||
interrupt();
|
||||
mNotifications.onReadCancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -5,9 +5,8 @@ import android.nfc.tech.IsoDep;
|
|||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.data.Firmwares;
|
||||
import com.tangem.tangemcard.data.local.Firmwares;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
package com.tangem.tangemcard.reader;
|
||||
package com.tangem.tangemcard.util;
|
||||
|
||||
import org.spongycastle.crypto.CipherParameters;
|
||||
import org.spongycastle.crypto.digests.SHA256Digest;
|
||||
|
Before Width: | Height: | Size: 536 B After Width: | Height: | Size: 536 B |
|
|
@ -1,3 +1,8 @@
|
|||
<resources>
|
||||
<string name="app_name">tangemcard</string>
|
||||
<string name="dialog_ok">OK</string>
|
||||
<string name="dialog_quit">Quit</string>
|
||||
<string name="nfc_disabled">Enable NFC?</string>
|
||||
<string name="enable_nfc">This app is useless when NFC is disabled. Reader mode depends on it. Hit OK to go to Settings, where you can enable NFC.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue