From bae8bd0e6ca8fdbdcc0f2b92698a04f0207c0a66 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 26 Oct 2018 10:59:36 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/data/nfc/SignPaymentTask.java | 23 +- .../domain/cardReader/CardProtocol.java | 6 +- .../domain/wallet/BalanceValidator.java | 81 +--- .../com/tangem/domain/wallet/Blockchain.java | 2 +- .../tangem/domain/wallet/BtcCashEngine.java | 342 ++++++++++------ .../com/tangem/domain/wallet/BtcData.java | 123 ++++++ .../com/tangem/domain/wallet/BtcEngine.java | 385 +++++++++++------- .../com/tangem/domain/wallet/CoinData.java | 175 ++++++++ .../com/tangem/domain/wallet/CoinEngine.java | 148 +++++-- .../domain/wallet/CoinEngineFactory.java | 38 +- .../com/tangem/domain/wallet/EthData.java | 114 ++++++ .../com/tangem/domain/wallet/EthEngine.java | 84 +++- .../com/tangem/domain/wallet/TangemCard.java | 381 ++--------------- .../tangem/domain/wallet/TangemContext.java | 114 ++++++ .../com/tangem/domain/wallet/TokenEngine.java | 18 +- .../activity/ConfirmPaymentActivity.kt | 100 ++--- .../activity/CreateNewWalletActivity.kt | 16 +- .../activity/EmptyWalletActivity.kt | 48 +-- .../presentation/activity/MainActivity.kt | 1 + ...pareCryptonitOtherAPIWithdrawalActivity.kt | 46 +-- .../PrepareCryptonitWithdrawalActivity.kt | 35 +- .../PrepareKrakenWithdrawalActivity.kt | 49 +-- .../activity/PreparePaymentActivity.kt | 84 ++-- .../presentation/activity/PurgeActivity.kt | 14 +- .../activity/SendTransactionActivity.kt | 33 +- .../activity/SignPaymentActivity.kt | 16 +- .../presentation/fragment/LoadedWallet.kt | 303 +++++++------- .../presentation/fragment/VerifyCard.kt | 169 ++++---- .../main/java/com/tangem/util/BTCUtils.java | 6 +- app/src/main/java/com/tangem/util/Util.java | 8 +- 30 files changed, 1686 insertions(+), 1276 deletions(-) create mode 100644 app/src/main/java/com/tangem/domain/wallet/BtcData.java create mode 100644 app/src/main/java/com/tangem/domain/wallet/CoinData.java create mode 100644 app/src/main/java/com/tangem/domain/wallet/EthData.java create mode 100644 app/src/main/java/com/tangem/domain/wallet/TangemContext.java diff --git a/app/src/main/java/com/tangem/data/nfc/SignPaymentTask.java b/app/src/main/java/com/tangem/data/nfc/SignPaymentTask.java index 6ed7228db8..e6e62646fd 100644 --- a/app/src/main/java/com/tangem/data/nfc/SignPaymentTask.java +++ b/app/src/main/java/com/tangem/data/nfc/SignPaymentTask.java @@ -11,6 +11,7 @@ import com.tangem.domain.wallet.Blockchain; import com.tangem.domain.wallet.CoinEngine; import com.tangem.domain.wallet.CoinEngineFactory; import com.tangem.domain.wallet.TangemCard; +import com.tangem.domain.wallet.TangemContext; import com.tangem.presentation.activity.SendTransactionActivity; import com.tangem.presentation.activity.SignPaymentActivity; import com.tangem.util.BTCUtils; @@ -32,14 +33,14 @@ public class SignPaymentTask extends Thread { private String txOutAddress; private Activity mContext; - private TangemCard mCard; + private TangemContext mCtx; private NfcManager mNfcManager; private IsoDep mIsoDep; private CardProtocol.Notifications mNotifications; private boolean isCancelled = false; - public SignPaymentTask(Activity context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications, String amount, String fee, Boolean IncFee, String outAddress) { - mCard = card; + public SignPaymentTask(Activity context, TangemContext ctx, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications, String amount, String fee, Boolean IncFee, String outAddress) { + mCtx=ctx; mContext = context; mNfcManager = nfcManager; mIsoDep = isoDep; @@ -53,7 +54,7 @@ public class SignPaymentTask extends Thread { if (mIsoDep == null) { return; } - CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications); + CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCtx.getCard(), mNotifications); mNotifications.onReadStart(protocol); try { @@ -86,15 +87,15 @@ public class SignPaymentTask extends Thread { // SignBTC_TX(protocol); // } - CoinEngine engine = CoinEngineFactory.create(mCard.getBlockchain()); + CoinEngine engine = CoinEngineFactory.create(mCtx.getCard().getBlockchain()); if (engine != null) { - if (mCard.getPauseBeforePIN2() > 0) { - mNotifications.onReadWait(mCard.getPauseBeforePIN2()); + if (mCtx.getCard().getPauseBeforePIN2() > 0) { + mNotifications.onReadWait(mCtx.getCard().getPauseBeforePIN2()); } byte[] tx = null; try { - tx = engine.sign(txFee, txAmount, txIncFee, txOutAddress, mCard, protocol); + tx = engine.sign(txFee, txAmount, txIncFee, txOutAddress, protocol); } catch (IOException e) { e.printStackTrace(); @@ -104,14 +105,14 @@ public class SignPaymentTask extends Thread { } if (tx != null) { + // TODO - move to engine!!! String txStr = BTCUtils.toHex(tx); - if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet || mCard.getBlockchain() == Blockchain.Token) { + if (mCtx.getBlockchain() == Blockchain.Ethereum || mCtx.getBlockchain() == Blockchain.EthereumTestNet || mCtx.getBlockchain() == Blockchain.Token) { txStr = String.format("0x%s", txStr); } Intent intent = new Intent(mContext, SendTransactionActivity.class); - intent.putExtra(TangemCard.EXTRA_UID, mCard.getUID()); - intent.putExtra(TangemCard.EXTRA_CARD, mCard.getAsBundle()); + mCtx.saveToBundle(intent.getExtras()); intent.putExtra(SendTransactionActivity.EXTRA_TX, txStr); mContext.startActivityForResult(intent, SignPaymentActivity.REQUEST_CODE_SEND_PAYMENT); } diff --git a/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java b/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java index ca1f364178..72fe570e28 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java +++ b/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java @@ -12,6 +12,7 @@ import com.tangem.domain.wallet.Issuer; import com.tangem.domain.wallet.LocalStorage; import com.tangem.domain.wallet.TangemCard; import com.tangem.domain.wallet.Manufacturer; +import com.tangem.domain.wallet.TangemContext; import com.tangem.util.Util; import org.spongycastle.jce.ECNamedCurveTable; @@ -584,8 +585,9 @@ public class CardProtocol { mCard.setWalletPublicKey(pkUncompressed); mCard.setWalletPublicKeyRar(pkCompresses); - CoinEngine engineCoin = CoinEngineFactory.create(mCard.getBlockchain()); - String wallet = engineCoin.calculateAddress(mCard, pkUncompressed); + TangemContext ctx=new TangemContext(mCard); + CoinEngine engineCoin = CoinEngineFactory.create(ctx); + String wallet = engineCoin.calculateAddress(pkUncompressed); mCard.setWallet(wallet); //mCard.setWallet(Blockchain.calculateWalletAddress(mCard, pkUncompressed)); diff --git a/app/src/main/java/com/tangem/domain/wallet/BalanceValidator.java b/app/src/main/java/com/tangem/domain/wallet/BalanceValidator.java index 7f8519e143..155bb7e7e1 100644 --- a/app/src/main/java/com/tangem/domain/wallet/BalanceValidator.java +++ b/app/src/main/java/com/tangem/domain/wallet/BalanceValidator.java @@ -13,6 +13,10 @@ public class BalanceValidator { return firstLine; } + public void setFirstLine(String value) { + firstLine=value; + } + public String getSecondLine(Boolean recommend) { if (!recommend) return secondLine; if (score > 89) { @@ -26,6 +30,14 @@ public class BalanceValidator { } } + public void setSecondLine(String value) { + secondLine=value; + } + + public void setScore(int score) { + this.score = score; + } + public int getColor() { if (score > 89) { return R.color.confirmed; @@ -38,73 +50,14 @@ public class BalanceValidator { } } - public void Check(TangemCard card, Boolean attest) { + public void Check(TangemContext ctx, Boolean attest) { firstLine = "Verification failed"; secondLine = ""; + TangemCard card=ctx.getCard(); + CoinEngine engine=CoinEngineFactory.create(ctx); - if (card.getBlockchain() == Blockchain.Bitcoin || card.getBlockchain() == Blockchain.BitcoinTestNet) { - - if (((card.getOfflineBalance() == null) && !card.isBalanceReceived()) || (!card.isBalanceReceived() && (card.getRemainingSignatures() != card.getMaxSignatures()))) { - score = 0; - firstLine = "Unknown balance"; - secondLine = "Balance cannot be verified. Swipe down to refresh."; - return; - } - - // Workaround before new back-end -// if (card.getRemainingSignatures() == card.getMaxSignatures()) { -// firstLine = "Verified balance"; -// secondLine = "Balance confirmed in blockchain. "; -// secondLine += "Verified note identity. "; -// return; -// } - - if (card.getBalanceUnconfirmed() != 0) { - score = 0; - firstLine = "Transaction in progress"; - secondLine = "Wait for confirmation in blockchain"; - return; - } - - if (card.isBalanceReceived() && card.isBalanceEqual()) { - score = 100; - firstLine = "Verified balance"; - secondLine = "Balance confirmed in blockchain"; - if (card.getBalance() == 0) { - firstLine = "Empty wallet"; - secondLine = ""; - } - } - - // rule 4 TODO: need to check SignedHashed against number of outputs in blockchain -// if((card.getRemainingSignatures() != card.getMaxSignatures()) && card.getBalance() != 0) -// { -// score = 80; -// firstLine = "Unguaranteed balance"; -// secondLine = "Potential unsent transaction. Redeem immediately if accept. "; -// return; -// } - - if ((card.getOfflineBalance() != null) && !card.isBalanceReceived() && (card.getRemainingSignatures() == card.getMaxSignatures()) && card.getBalance() != 0) { - score = 80; - firstLine = "Verified offline balance"; - secondLine = "Can't obtain balance from blockchain. Restore internet connection to be more confident. "; - } - -// if(card.getFailedBalanceRequestCounter()!=0) { -// score -= 5 * card.getFailedBalanceRequestCounter(); -// secondLine += "Not all nodes have returned balance. Swipe down or tap again. "; -// if(score <= 0) -// return; -// } - - // -// if(card.isBalanceReceived() && !card.isBalanceEqual()) { -// score = 0; -// firstLine = "Disputed balance"; -// secondLine += " Cannot obtain trusted balance at the moment. Try to tap and check this banknote later."; -// return; -// } + if (ctx.getBlockchain() == Blockchain.Bitcoin || ctx.getBlockchain() == Blockchain.BitcoinTestNet) { + if( !engine.validateBalance(this) ) return; } else if ((card.getBlockchain() == Blockchain.Ethereum) || (card.getBlockchain() == Blockchain.Token)) { if (card.getBalance() == null) { diff --git a/app/src/main/java/com/tangem/domain/wallet/Blockchain.java b/app/src/main/java/com/tangem/domain/wallet/Blockchain.java index a346758372..112a0ec6c1 100644 --- a/app/src/main/java/com/tangem/domain/wallet/Blockchain.java +++ b/app/src/main/java/com/tangem/domain/wallet/Blockchain.java @@ -84,7 +84,7 @@ public enum Blockchain { return resourceId; } - public int getLogoImageResource(String blockchainID, String symbolName) { + public static int getLogoImageResource(String blockchainID, String symbolName) { switch (blockchainID) { case "BTC": return R.drawable.ic_logo_bitcoin; diff --git a/app/src/main/java/com/tangem/domain/wallet/BtcCashEngine.java b/app/src/main/java/com/tangem/domain/wallet/BtcCashEngine.java index fb531e31e7..60dd904a3c 100644 --- a/app/src/main/java/com/tangem/domain/wallet/BtcCashEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/BtcCashEngine.java @@ -1,105 +1,116 @@ package com.tangem.domain.wallet; import android.net.Uri; +import android.text.InputFilter; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.TLV; import com.tangem.util.BTCUtils; import com.tangem.util.CryptoUtil; +import com.tangem.util.DecimalDigitsInputFilter; import com.tangem.util.DerEncodingUtil; import com.tangem.util.FormatUtil; import com.tangem.util.Util; import java.io.ByteArrayOutputStream; -import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; -import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static com.tangem.util.FormatUtil.GetDecimalFormat; - /** * Created by Ilia on 15.02.2018. */ public class BtcCashEngine extends CoinEngine { - public String getNode(TangemCard mCard) { - return "35.157.238.5"; + public BtcData btcData = null; + + public BtcCashEngine(TangemContext context) throws Exception { + super(context); + if (context.getCoinData() == null) { + btcData = new BtcData(); + context.setCoinData(btcData); + } else if (context.getCoinData() instanceof BtcData) { + btcData = (BtcData) context.getCoinData(); + } else { + throw new Exception("Invalid type of Blockchain data for BtcEngine"); + } } - public int getNodePort(TangemCard mCard) { - return 51001; + public BtcCashEngine() { + } - public void switchNode(TangemCard mCard) { + private void checkBlockchainDataExists() throws Exception { + if (btcData == null) throw new Exception("No blockchain data"); } - public boolean inOutPutVisible() { + @Override + public boolean awaitingConfirmation(){ + if( btcData==null ) return false; + return btcData.getBalanceUnconfirmed() != 0; + } + + @Override + public String getBalanceHTML() { + if (hasBalanceInfo()) { + Amount balance = convertToAmount(btcData.getBalanceInInternalUnits()); + return balance.toString(); + } else { + return ""; + } + } + + @Override + public String getBalanceCurrencyHTML() { + return "mBCH"; + } + + @Override + public boolean isBalanceAlterNotZero() { return true; } - public boolean awaitingConfirmation(TangemCard card) { - return card.getBalanceUnconfirmed() != 0; + + @Override + public boolean isBalanceNotZero() { + if( btcData==null ) return false; + if (btcData.getBalanceInInternalUnits() == null) return false; + return btcData.getBalanceInInternalUnits().notZero(); } - public String getBalanceWithAlter(TangemCard mCard) { - return getBalance(mCard); - } - - public boolean isBalanceAlterNotZero(TangemCard card) { - return true; - } - - public Long getBalanceLong(TangemCard mCard) { - return mCard.getBalance(); - } - - public boolean isBalanceNotZero(TangemCard card) { - return card.getBalance() > 0; - } - - public boolean checkAmount(TangemCard card, String amount) throws Exception { - DecimalFormat decimalFormat = GetDecimalFormat(); - BigDecimal amountValue = (BigDecimal) decimalFormat.parse(amount); - - // Convert Balance to BigDecimal - BigDecimal maxValue = new BigDecimal(getBalanceValue(card)); - maxValue = maxValue.divide(new BigDecimal(1000)); - - //if (use_mCurrency) { - amountValue = amountValue.divide(new BigDecimal(1000)); - //} - - if (amountValue.compareTo(maxValue) > 0) { + @Override + public boolean checkAmount(Amount amount) throws Exception { + checkBlockchainDataExists(); + if (amount.compareTo(convertToAmount(btcData.getBalanceInInternalUnits())) > 0) { return false; } - return true; } - public boolean hasBalanceInfo(TangemCard card) { - return card.hasBalanceInfo(); + @Override + public boolean hasBalanceInfo(){ + if( btcData==null ) return false; + return btcData.hasBalanceInfo(); } - public String getBalanceCurrency(TangemCard card) { + @Override + public boolean checkUnspentTransaction() throws Exception { + checkBlockchainDataExists(); + return btcData.getUnspentTransactions().size() != 0; + } + + @Override + public String getFeeCurrencyHTML() { return "mBCH"; } - public boolean checkUnspentTransaction(TangemCard mCard) { - return mCard.getUnspentTransactions().size() != 0; - } - - public String getFeeCurrency() { - return "mBCH"; - } - - public boolean validateAddress(String address, TangemCard card) { + @Override + public boolean validateAddress(String address) { if (address == null || address.isEmpty()) { return false; } @@ -134,44 +145,46 @@ public class BtcCashEngine extends CoinEngine { return false; } - if (card.getBlockchain() != Blockchain.BitcoinCashTestNet && card.getBlockchain() != Blockchain.BitcoinCash) { + if (ctx.getBlockchain() != Blockchain.BitcoinCashTestNet && ctx.getBlockchain() != Blockchain.BitcoinCash) { return false; } - if (card.getBlockchain() == Blockchain.BitcoinCashTestNet && (address.startsWith("1") || address.startsWith("3"))) { + if (ctx.getBlockchain() == Blockchain.BitcoinCashTestNet && (address.startsWith("1") || address.startsWith("3"))) { return false; } return true; } - - public int getTokenDecimals(TangemCard card) { - return 0; - } - - public String getContractAddress(TangemCard card) { - return ""; - } - + @Override public boolean isNeedCheckNode() { return true; } - public Uri getShareWalletUriExplorer(TangemCard mCard) { - return Uri.parse((mCard.getBlockchain() == Blockchain.BitcoinCash ? "https://bitcoincash.blockexplorer.com/address/" : "https://testnet.blockexplorer.com/address/") + mCard.getWallet()); + @Override + public Uri getShareWalletUriExplorer() { + return Uri.parse((ctx.getBlockchain() == Blockchain.BitcoinCash ? "https://bitcoincash.blockexplorer.com/address/" : "https://testnet.blockexplorer.com/address/") + ctx.getCard().getWallet()); } - public Uri getShareWalletUri(TangemCard mCard) { - return Uri.parse("bitcoincash:" + mCard.getWallet()); + @Override + public Uri getShareWalletUri() { + return Uri.parse("bitcoincash:" + ctx.getCard().getWallet()); } - public boolean checkAmountValue(TangemCard card, String amountValue, String feeValue, Long minFeeInInternalUnits, Boolean incfee) { - Long fee; - Long amount; + @Override + public InputFilter[] getAmountInputFilters() { + return new InputFilter[] { new DecimalDigitsInputFilter(8) }; + } + + @Override + public boolean checkAmountValue(String amountValue, String feeValue, InternalAmount minFeeInInternalUnits, Boolean isIncludeFee) { + InternalAmount fee; + InternalAmount amount; + try { - amount = card.internalUnitsFromString(amountValue); - fee = card.internalUnitsFromString(feeValue); + checkBlockchainDataExists(); + amount = convertToInternalAmount(new Amount(amountValue, ctx.getBlockchain())); + fee = convertToInternalAmount(new Amount(feeValue, ctx.getBlockchain())); } catch (Exception e) { e.printStackTrace(); return false; @@ -180,64 +193,106 @@ public class BtcCashEngine extends CoinEngine { if (fee == null || amount == null) return false; - if (fee == 0 || amount == 0) + if (fee.isZero() || amount.isZero()) return false; - if (incfee && amount > card.getBalance()) + if (isIncludeFee && amount.compareTo(btcData.getBalanceInInternalUnits())>0) return false; - if (!incfee && amount + fee > card.getBalance()) + if (!isIncludeFee && amount.add(fee).compareTo(btcData.getBalanceInInternalUnits())>0) return false; return true; } - public String evaluateFeeEquivalent(TangemCard mCard, String fee) { - return getAmountEquivalentDescriptor(mCard, fee); + @Override + public boolean validateBalance(BalanceValidator balanceValidator) { + if (((ctx.getCard().getOfflineBalance() == null) && !ctx.getCoinData().isBalanceReceived()) || (!ctx.getCoinData().isBalanceReceived() && (ctx.getCard().getRemainingSignatures() != ctx.getCard().getMaxSignatures()))) { + balanceValidator.setScore(0); + balanceValidator.setFirstLine("Unknown balance"); + balanceValidator.setSecondLine("Balance cannot be verified. Swipe down to refresh."); + return false; + } + + // Workaround before new back-end +// if (card.getRemainingSignatures() == card.getMaxSignatures()) { +// firstLine = "Verified balance"; +// secondLine = "Balance confirmed in blockchain. "; +// secondLine += "Verified note identity. "; +// return; +// } + + if (btcData.getBalanceUnconfirmed() != 0) { + balanceValidator.setScore(0); + balanceValidator.setFirstLine("Transaction in progress"); + balanceValidator.setSecondLine("Wait for confirmation in blockchain"); + return false; + } + + if (btcData.isBalanceReceived() && btcData.isBalanceEqual()) { + balanceValidator.setScore(100); + balanceValidator.setFirstLine("Verified balance"); + balanceValidator.setSecondLine("Balance confirmed in blockchain"); + if (btcData.getBalanceInInternalUnits().isZero()) { + balanceValidator.setFirstLine("Empty wallet"); + balanceValidator.setSecondLine(""); + } + } + + // rule 4 TODO: need to check SignedHashed against number of outputs in blockchain +// if((card.getRemainingSignatures() != card.getMaxSignatures()) && card.getBalance() != 0) +// { +// score = 80; +// firstLine = "Unguaranteed balance"; +// secondLine = "Potential unsent transaction. Redeem immediately if accept. "; +// return; +// } + + if ((ctx.getCard().getOfflineBalance() != null) && !btcData.isBalanceReceived() && (ctx.getCard().getRemainingSignatures() == ctx.getCard().getMaxSignatures()) && btcData.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. "); + } + +// if(card.getFailedBalanceRequestCounter()!=0) { +// score -= 5 * card.getFailedBalanceRequestCounter(); +// secondLine += "Not all nodes have returned balance. Swipe down or tap again. "; +// if(score <= 0) +// return; +// } + + // +// if(card.isBalanceReceived() && !card.isBalanceEqual()) { +// score = 0; +// firstLine = "Disputed balance"; +// secondLine += " Cannot obtain trusted balance at the moment. Try to tap and check this banknote later."; +// return; +// } + + return true; } @Override - public String getBalanceEquivalent(TangemCard mCard) { - Double balance = Double.NaN; - try { - Long val = mCard.getBalance(); - balance = mCard.amountFromInternalUnits(val); - } catch (Exception ex) { - mCard.setRate(0); - } - - return mCard.getAmountEquivalentDescription(balance); + public Amount getBalance() { + return convertToAmount(btcData.getBalanceInInternalUnits()); } - public String getBalance(TangemCard mCard) { - if (mCard.hasBalanceInfo()) { - Double balance = mCard.amountFromInternalUnits(mCard.getBalance()); - return mCard.getAmountDescription(balance); - } else { - return ""; - } + @Override + public String evaluateFeeEquivalent(String fee) { + return getAmountEquivalentDescriptor(ctx.getCard(), fee); } - public String getBalanceValue(TangemCard mCard) { - if (mCard.hasBalanceInfo()) { - Double balance = mCard.getBalance() / (mCard.getBlockchain().getMultiplier()); - - String output = FormatUtil.DoubleToString(balance); - //String pattern = "#0.000"; // If you like 4 zeros - //DecimalFormat myFormatter = new DecimalFormat(pattern); - //String output = myFormatter.format(balance); - return output; - - //return Double.toString(balance); - } else { - return "0"; - } + @Override + public String getBalanceEquivalent() { + if( btcData==null ) return ""; + return btcData.getAmountEquivalentDescription(getBalance()); } - public String calculateAddress(TangemCard mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { + @Override + public String calculateAddress(byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { byte netSelectionByte; - switch (mCard.getBlockchain()) { + switch (ctx.getBlockchain()) { case BitcoinCash: netSelectionByte = (byte) 0x00; //0 - MainNet 0x6f - TestNet break; @@ -266,29 +321,49 @@ public class BtcCashEngine extends CoinEngine { BB.put(hash4[3]); return org.bitcoinj.core.Base58.encode(BB.array()); - } @Override - public String convertByteArrayToAmount(TangemCard mCard, byte[] bytes) throws Exception { + public Amount convertToAmount(InternalAmount internalAmount) { + return null; + } + + @Override + public InternalAmount convertToInternalAmount(Amount amount) throws Exception { + return null; + } + + @Override + public InternalAmount convertToInternalAmount(byte[] bytes) { + 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 FormatUtil.DoubleToString(mCard.amountFromInternalUnits(Util.byteArrayToLong(reversed))); + return new InternalAmount(Util.byteArrayToLong(reversed)); } @Override - public byte[] convertAmountToByteArray(TangemCard card, String amount) throws Exception { - byte[] bytes = Util.longToByteArray(card.internalUnitsFromString(amount)); + public byte[] convertToByteArray(InternalAmount internalAmount) throws Exception { + byte[] bytes = Util.longToByteArray(internalAmount.longValueExact()); byte[] reversed = new byte[bytes.length]; for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; return reversed; } @Override - public String getAmountDescription(TangemCard mCard, String amount) throws Exception { - return mCard.getAmountDescription(Double.parseDouble(amount)); + public CoinData createCoinData() { + return new BtcData(); } + @Override + public String getUnspentInputsDescription() { + return btcData.getUnspentInputsDescription(); + } + +// @Override +// public String getAmountDescription(TangemCard mCard, String amount) throws Exception { +// return mCard.getAmountDescription(Double.parseDouble(amount)); +// } + public static String getAmountEquivalentDescriptionBTC(Double amount, float rate) { if ((rate > 0) && (amount > 0)) { return String.format("≈ USD %.2f", amount * rate); @@ -298,18 +373,21 @@ public class BtcCashEngine extends CoinEngine { } public String getAmountEquivalentDescriptor(TangemCard mCard, String value) { - return getAmountEquivalentDescriptionBTC(Double.parseDouble(value), mCard.getRate()); + return getAmountEquivalentDescriptionBTC(Double.parseDouble(value), btcData.getRate()); } - public byte[] sign(String feeValue, String amountValue, boolean IncFee, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception { + @Override + public byte[] sign(String feeValue, String amountValue, boolean IncFee, String toValue, CardProtocol protocol) throws Exception { - String myAddress = mCard.getWallet(); - byte[] pbKey = mCard.getWalletPublicKeyRar(); //ALWAYS USING COMPRESS KEY + checkBlockchainDataExists(); + + String myAddress = ctx.getCard().getWallet(); + byte[] pbKey = ctx.getCard().getWalletPublicKeyRar(); //ALWAYS USING COMPRESS KEY String outputAddress = toValue; String changeAddress = myAddress; // Build script for our address - List rawTxList = mCard.getUnspentTransactions(); + List rawTxList = btcData.getUnspentTransactions(); byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; // Collect unspent @@ -345,7 +423,7 @@ public class BtcCashEngine extends CoinEngine { unspentOutputs.get(i).bodyDoubleHash = doubleHashData; unspentOutputs.get(i).bodyHash = hashData; - if (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + if (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { dataForSign[i] = newTX; } else { dataForSign[i] = doubleHashData; @@ -353,8 +431,8 @@ public class BtcCashEngine extends CoinEngine { } - byte[] signFromCard = null; - if (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + byte[] signFromCard; + if (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { ByteArrayOutputStream bs = new ByteArrayOutputStream(); if (dataForSign.length > 10) throw new Exception("To much hashes in one transaction!"); for (int i = 0; i < dataForSign.length; i++) { @@ -364,20 +442,18 @@ public class BtcCashEngine extends CoinEngine { } signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value; } else { - signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer, null, mCard.getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value; + 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; // TODO slice signFromCard to hashes.length parts } for (int i = 0; i < unspentOutputs.size(); ++i) { - BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)); + BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, i * 64, 32 + i * 64)); BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); s = CryptoUtil.toCanonicalised(s); - byte[] encodingSign = DerEncodingUtil.packSignDerBitcoinCash(r, s, pbKey); - unspentOutputs.get(i).scriptForBuild = encodingSign; + unspentOutputs.get(i).scriptForBuild = DerEncodingUtil.packSignDerBitcoinCash(r, s, pbKey); } - byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); - return realTX; + return BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); } } diff --git a/app/src/main/java/com/tangem/domain/wallet/BtcData.java b/app/src/main/java/com/tangem/domain/wallet/BtcData.java new file mode 100644 index 0000000000..80ab1db1c3 --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/BtcData.java @@ -0,0 +1,123 @@ +package com.tangem.domain.wallet; + +import android.os.Bundle; +import android.util.Log; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public class BtcData extends CoinData { + public BtcData() { + super(); + } + + private Long balanceConfirmed, balanceUnconfirmed; + + public String getUnspentInputsDescription() { + int gatheredUnspents = 0; + for (int i=0; i 1) gatheredUnspents++; + } + return String.valueOf(unspentTransactions.size()) + " unspents (" + String.valueOf(gatheredUnspents) + " received)"; + } + + public static class UnspentTransaction { + public String txID; + public Integer Amount; + public Integer Height; + public String Raw = ""; + + public Bundle getAsBundle() { + Bundle B = new Bundle(); + B.putString("txID", txID); + B.putInt("Amount", Amount); + B.putInt("Height", Height); + B.putString("Raw", Raw); + return B; + } + + public void loadFromBundle(Bundle B) { + txID = B.getString("txID"); + Amount = B.getInt("Amount"); + Height = B.getInt("Height"); + Raw = B.getString("Raw"); + } + } + + private List unspentTransactions = null; + + public List getUnspentTransactions() { + if (unspentTransactions == null) unspentTransactions = new ArrayList<>(); + return unspentTransactions; + } + + @Override + public void loadFromBundle(Bundle B) { + super.loadFromBundle(B); + + if (B.containsKey("BalanceConfirmed")) balanceConfirmed = B.getLong("BalanceConfirmed"); + else balanceConfirmed = null; + if (B.containsKey("BalanceUnconfirmed")) + balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); + else balanceUnconfirmed = null; + if (B.containsKey("UnspentTransactions")) { + unspentTransactions = new ArrayList<>(); + Bundle BB = B.getBundle("UnspentTransactions"); + Integer i = 0; + while (BB.containsKey(i.toString())) { + UnspentTransaction t = new UnspentTransaction(); + t.loadFromBundle(BB.getBundle(i.toString())); + unspentTransactions.add(t); + i++; + } + } + } + + @Override + public void saveToBundle(Bundle B) { + super.saveToBundle(B); + try { + if (unspentTransactions != null) { + Bundle BB = new Bundle(); + for (Integer i = 0; i < unspentTransactions.size(); i++) { + BB.putBundle(i.toString(), unspentTransactions.get(i).getAsBundle()); + } + B.putBundle("UnspentTransactions", BB); + } + if (balanceConfirmed != null) B.putLong("BalanceConfirmed", balanceConfirmed); + if (balanceUnconfirmed != null) B.putLong("BalanceUnconfirmed", balanceUnconfirmed); + } catch (Exception e) { + Log.e("Can't save to bundle ", e.getMessage()); + } + } + + @Override + public void clearInfo() { + super.clearInfo(); + balanceConfirmed = null; + balanceUnconfirmed = null; + unspentTransactions = null; + } + + public CoinEngine.InternalAmount getBalanceInInternalUnits() { + return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceConfirmed).add(BigDecimal.valueOf(balanceUnconfirmed))); + } + + public Long getBalanceUnconfirmed() { + return balanceUnconfirmed; + } + + public void setBalanceConfirmed(Long balance) { + this.balanceConfirmed = balance; + } + + public void setBalanceUnconfirmed(Long balance) { + this.balanceUnconfirmed = balance; + } + + public boolean hasBalanceInfo() { + return balanceConfirmed != null || balanceUnconfirmed != null; + } + +} diff --git a/app/src/main/java/com/tangem/domain/wallet/BtcEngine.java b/app/src/main/java/com/tangem/domain/wallet/BtcEngine.java index 5fb4329b4a..4dab3d3756 100644 --- a/app/src/main/java/com/tangem/domain/wallet/BtcEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/BtcEngine.java @@ -1,6 +1,7 @@ package com.tangem.domain.wallet; import android.net.Uri; +import android.text.InputFilter; import com.tangem.domain.BitcoinNode; import com.tangem.domain.BitcoinNodeTestNet; @@ -8,12 +9,12 @@ import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.TLV; import com.tangem.util.BTCUtils; import com.tangem.util.CryptoUtil; +import com.tangem.util.DecimalDigitsInputFilter; import com.tangem.util.DerEncodingUtil; import com.tangem.util.FormatUtil; import com.tangem.util.Util; import java.io.ByteArrayOutputStream; -import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.security.NoSuchAlgorithmException; @@ -21,12 +22,27 @@ import java.security.NoSuchProviderException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Locale; - -import static com.tangem.util.FormatUtil.stringToBigDecimal; public class BtcEngine extends CoinEngine { + public BtcData btcData = null; + + public BtcEngine(TangemContext context) throws Exception { + super(context); + if (context.getCoinData() == null) { + btcData = new BtcData(); + context.setCoinData(btcData); + } else if (context.getCoinData() instanceof BtcData) { + btcData = (BtcData) context.getCoinData(); + } else { + throw new Exception("Invalid type of Blockchain data for BtcEngine"); + } + } + + public BtcEngine() { + super(); + } + private static String[] getBitcoinServiceHosts() { return new String[]{ BitcoinNode.n1.getHost(), @@ -79,80 +95,70 @@ public class BtcEngine extends CoinEngine { static int serviceIndex = 0; - public String getNode(TangemCard card) { - switch (card.getBlockchain()) { - case Bitcoin: - return getBitcoinServiceHosts()[serviceIndex]; // + private void checkBlockchainDataExists() throws Exception { + if (btcData == null) throw new Exception("No blockchain data"); + } + + @Override + public boolean awaitingConfirmation(){ + if( btcData==null ) return false; + return btcData.getBalanceUnconfirmed() != 0; + } + + @Override + public String getBalanceHTML() { + if (hasBalanceInfo()) { + Amount balance = convertToAmount(btcData.getBalanceInInternalUnits()); + return balance.toString(); + } else { + return ""; } - return null; } - public int getNodePort(TangemCard card) { - switch (card.getBlockchain()) { - case Bitcoin: - return getBitcoinServicePorts()[serviceIndex];//8080; - } - return 8080; - } - - public void switchNode(TangemCard card) { - serviceIndex++; - if (serviceIndex > getBitcoinServiceHosts().length - 1) serviceIndex = 0; - } - - public boolean inOutPutVisible() { - return true; - } - - public boolean awaitingConfirmation(TangemCard card) { - return card.getBalanceUnconfirmed() != 0; - } - - public String getBalanceWithAlter(TangemCard card) { - return getBalance(card); - } - - public boolean isBalanceAlterNotZero(TangemCard card) { - return true; - } - - public Long getBalanceLong(TangemCard card) { - return card.getBalance(); - } - - public boolean isBalanceNotZero(TangemCard card) { - if (card.getBalance() == null) return false; - return card.getBalance() > 0; - } - - public boolean checkAmount(TangemCard card, String amount) throws Exception { -// DecimalFormat decimalFormat = GetDecimalFormat(); -// BigDecimal amountValue = (BigDecimal) decimalFormat.parse(amount); - BigDecimal amountValue = stringToBigDecimal(amount, Locale.US); - BigDecimal maxValue = stringToBigDecimal(getBalanceValue(card), Locale.US); - if (amountValue.compareTo(maxValue) > 0) { - return false; - } - return true; - } - - public boolean hasBalanceInfo(TangemCard card) { - return card.hasBalanceInfo(); - } - - public String getBalanceCurrency(TangemCard card) { + @Override + public String getBalanceCurrencyHTML() { return "BTC"; } - public boolean checkUnspentTransaction(TangemCard card) { - return card.getUnspentTransactions().size() != 0; + @Override + public String getOfflineBalanceHTML() { + InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance()); + Amount offlineAmount = convertToAmount(offlineInternalAmount); + return offlineAmount.toString(); } - public String getFeeCurrency() { + @Override + public boolean isBalanceAlterNotZero() { + return true; + } + + @Override + public boolean isBalanceNotZero() { + if( btcData==null ) return false; + if (btcData.getBalanceInInternalUnits() == null) return false; + return btcData.getBalanceInInternalUnits().notZero(); + } + + @Override + public boolean hasBalanceInfo(){ + if( btcData==null ) return false; + return btcData.hasBalanceInfo(); + } + + + @Override + public boolean checkUnspentTransaction() throws Exception { + checkBlockchainDataExists(); + return btcData.getUnspentTransactions().size() != 0; + } + + @Override + public String getFeeCurrencyHTML() { return "BTC"; } - public boolean validateAddress(String address, TangemCard card) { + @Override + public boolean validateAddress(String address) { if (address == null || address.isEmpty()) { return false; } @@ -187,11 +193,11 @@ public class BtcEngine extends CoinEngine { return false; } - if (card.getBlockchain() != Blockchain.BitcoinTestNet && card.getBlockchain() != Blockchain.Bitcoin) { + if (ctx.getBlockchain() != Blockchain.BitcoinTestNet && ctx.getBlockchain() != Blockchain.Bitcoin) { return false; } - if (card.getBlockchain() == Blockchain.BitcoinTestNet && (address.startsWith("1") || address.startsWith("3"))) { + if (ctx.getBlockchain() == Blockchain.BitcoinTestNet && (address.startsWith("1") || address.startsWith("3"))) { return false; } @@ -199,37 +205,48 @@ public class BtcEngine extends CoinEngine { } - public int getTokenDecimals(TangemCard card) { - return 0; - } - - public String getContractAddress(TangemCard card) { - return ""; - } - + @Override public boolean isNeedCheckNode() { return true; } - public Uri getShareWalletUriExplorer(TangemCard card) { - return Uri.parse((card.getBlockchain() == Blockchain.Bitcoin ? "https://blockchain.info/address/" : "https://testnet.blockchain.info/address/") + card.getWallet()); + @Override + public Uri getShareWalletUriExplorer() { + return Uri.parse((ctx.getBlockchain() == Blockchain.Bitcoin ? "https://blockchain.info/address/" : "https://testnet.blockchain.info/address/") + ctx.getCard().getWallet()); } - public Uri getShareWalletUri(TangemCard card) { - if (card.getDenomination() != null) { - return Uri.parse("bitcoin:" + card.getWallet() + "?amount=" + BTCUtils.satoshiToBtc(card.getDenomination())); + @Override + public Uri getShareWalletUri() { + if (ctx.getCard().getDenomination() != null) { + return Uri.parse("bitcoin:" + ctx.getCard().getWallet() + "?amount=" + BTCUtils.satoshiToBtc(ctx.getCard().getDenomination())); } else { - return Uri.parse("bitcoin:" + card.getWallet()); + return Uri.parse("bitcoin:" + ctx.getCard().getWallet()); } } + @Override + public InputFilter[] getAmountInputFilters() { + return new InputFilter[] { new DecimalDigitsInputFilter(8) }; + } + + @Override + public boolean checkNewTransactionAmount(Amount amount){ + if( btcData==null ) return false; + if (amount.compareTo(convertToAmount(btcData.getBalanceInInternalUnits())) > 0) { + return false; + } + return true; + } + + @Override + public boolean checkNewTransactionAmountAndFee(Amount amountValue, Amount feeValue, Boolean isIncludeFee, InternalAmount minFeeInInternalUnits) { + InternalAmount fee; + InternalAmount amount; - public boolean checkAmountValue(TangemCard card, String amountValue, String feeValue, Long minFeeInInternalUnits, Boolean isIncludeFee) { - Long fee; - Long amount; try { - amount = card.internalUnitsFromString(amountValue); - fee = card.internalUnitsFromString(feeValue); + checkBlockchainDataExists(); + amount = convertToInternalAmount(amountValue); + fee = convertToInternalAmount(feeValue); } catch (Exception e) { e.printStackTrace(); return false; @@ -238,63 +255,105 @@ public class BtcEngine extends CoinEngine { if (fee == null || amount == null) return false; - if (fee == 0 || amount == 0) + if (fee.isZero() || amount.isZero()) return false; - if (isIncludeFee && amount > card.getBalance()) + if (isIncludeFee && amount.compareTo(btcData.getBalanceInInternalUnits())>0) return false; - if (!isIncludeFee && amount + fee > card.getBalance()) + if (!isIncludeFee && amount.add(fee).compareTo(btcData.getBalanceInInternalUnits())>0) return false; return true; } - public String evaluateFeeEquivalent(TangemCard card, String fee) { - return getAmountEquivalentDescriptor(card, fee); + @Override + public boolean validateBalance(BalanceValidator balanceValidator) { + if (((ctx.getCard().getOfflineBalance() == null) && !ctx.getCoinData().isBalanceReceived()) || (!ctx.getCoinData().isBalanceReceived() && (ctx.getCard().getRemainingSignatures() != ctx.getCard().getMaxSignatures()))) { + balanceValidator.setScore(0); + balanceValidator.setFirstLine("Unknown balance"); + balanceValidator.setSecondLine("Balance cannot be verified. Swipe down to refresh."); + return false; + } + + // Workaround before new back-end +// if (card.getRemainingSignatures() == card.getMaxSignatures()) { +// firstLine = "Verified balance"; +// secondLine = "Balance confirmed in blockchain. "; +// secondLine += "Verified note identity. "; +// return; +// } + + if (btcData.getBalanceUnconfirmed() != 0) { + balanceValidator.setScore(0); + balanceValidator.setFirstLine("Transaction in progress"); + balanceValidator.setSecondLine("Wait for confirmation in blockchain"); + return false; + } + + if (btcData.isBalanceReceived() && btcData.isBalanceEqual()) { + balanceValidator.setScore(100); + balanceValidator.setFirstLine("Verified balance"); + balanceValidator.setSecondLine("Balance confirmed in blockchain"); + if (btcData.getBalanceInInternalUnits().isZero()) { + balanceValidator.setFirstLine("Empty wallet"); + balanceValidator.setSecondLine(""); + } + } + + // rule 4 TODO: need to check SignedHashed against number of outputs in blockchain +// if((card.getRemainingSignatures() != card.getMaxSignatures()) && card.getBalance() != 0) +// { +// score = 80; +// firstLine = "Unguaranteed balance"; +// secondLine = "Potential unsent transaction. Redeem immediately if accept. "; +// return; +// } + + if ((ctx.getCard().getOfflineBalance() != null) && !btcData.isBalanceReceived() && (ctx.getCard().getRemainingSignatures() == ctx.getCard().getMaxSignatures()) && btcData.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. "); + } + +// if(card.getFailedBalanceRequestCounter()!=0) { +// score -= 5 * card.getFailedBalanceRequestCounter(); +// secondLine += "Not all nodes have returned balance. Swipe down or tap again. "; +// if(score <= 0) +// return; +// } + + // +// if(card.isBalanceReceived() && !card.isBalanceEqual()) { +// score = 0; +// firstLine = "Disputed balance"; +// secondLine += " Cannot obtain trusted balance at the moment. Try to tap and check this banknote later."; +// return; +// } + + return true; } @Override - public String getBalanceEquivalent(TangemCard card) { - Double balance = Double.NaN; - try { - Long val = card.getBalance(); - balance = card.amountFromInternalUnits(val); - } catch (Exception ex) { - card.setRate(0); - } - - return card.getAmountEquivalentDescription(balance); + public Amount getBalance() { + return convertToAmount(btcData.getBalanceInInternalUnits()); } - public String getBalance(TangemCard card) { - if (card.hasBalanceInfo()) { - Double balance = card.amountFromInternalUnits(card.getBalance()); - return card.getAmountDescription(balance); - } else { - return ""; - } + @Override + public String evaluateFeeEquivalent(String fee) { + return getAmountEquivalentDescriptor(ctx.getCard(), fee); } - public String getBalanceValue(TangemCard card) { - if (card.hasBalanceInfo()) { - Double balance = card.getBalance() / (card.getBlockchain().getMultiplier()); - - String output = FormatUtil.DoubleToString(balance); - //String pattern = "#0.000"; // If you like 4 zeros - //DecimalFormat myFormatter = new DecimalFormat(pattern); - //String output = myFormatter.format(balance); - return output; - - //return Double.toString(balance); - } else { - return "0"; - } + @Override + public String getBalanceEquivalent() { + if( btcData==null ) return ""; + return btcData.getAmountEquivalentDescription(getBalance()); } - public String calculateAddress(TangemCard card, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { + @Override + public String calculateAddress(byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { byte netSelectionByte; - switch (card.getBlockchain()) { + switch (ctx.getBlockchain()) { case Bitcoin: netSelectionByte = (byte) 0x00; //0 - MainNet 0x6f - TestNet break; @@ -326,26 +385,54 @@ public class BtcEngine extends CoinEngine { } @Override - public String convertByteArrayToAmount(TangemCard card, byte[] bytes) throws Exception { - if (bytes == null) return ""; - byte[] reversed = new byte[bytes.length]; - for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; - return FormatUtil.DoubleToString(card.amountFromInternalUnits(Util.byteArrayToLong(reversed))); + public Amount convertToAmount(InternalAmount internalAmount) { + //TODO + return null; } @Override - public byte[] convertAmountToByteArray(TangemCard card, String amount) throws Exception { - byte[] bytes = Util.longToByteArray(card.internalUnitsFromString(amount)); + public Amount convertToAmount(String strAmount) { + //TODO + return null; + } + + @Override + public InternalAmount convertToInternalAmount(Amount amount) throws Exception { + //TODO + return null; + } + + @Override + public InternalAmount convertToInternalAmount(byte[] bytes) { + 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)); + } + + @Override + public byte[] convertToByteArray(InternalAmount internalAmount) throws Exception { + byte[] bytes = Util.longToByteArray(internalAmount.longValueExact()); byte[] reversed = new byte[bytes.length]; for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; return reversed; } @Override - public String getAmountDescription(TangemCard card, String amount) throws Exception { - return card.getAmountDescription(Double.parseDouble(amount)); + public CoinData createCoinData() { + return new BtcData(); } + @Override + public String getUnspentInputsDescription() { + return btcData.getUnspentInputsDescription(); + } + +// @Override +// public String getAmountDescription(TangemCard card, String amount) throws Exception { +// return card.getAmountDescription(Double.parseDouble(amount)); +// } + public static String getAmountEquivalentDescriptionBTC(Double amount, float rate) { if ((rate > 0) && (amount > 0)) { return String.format("≈ USD %.2f", amount * rate); @@ -355,18 +442,22 @@ public class BtcEngine extends CoinEngine { } public String getAmountEquivalentDescriptor(TangemCard card, String value) { - return getAmountEquivalentDescriptionBTC(Double.parseDouble(value), card.getRate()); + + return getAmountEquivalentDescriptionBTC(Double.parseDouble(value), btcData.getRate()); } - public byte[] sign(String feeValue, String amountValue, boolean IncFee, String toValue, TangemCard card, CardProtocol protocol) throws Exception { + @Override + public byte[] sign(String feeValue, String amountValue, boolean IncFee, String toValue, CardProtocol protocol) throws Exception { - String myAddress = card.getWallet(); - byte[] pbKey = card.getWalletPublicKey(); + checkBlockchainDataExists(); + + String myAddress = ctx.getCard().getWallet(); + byte[] pbKey = ctx.getCard().getWalletPublicKey(); String outputAddress = toValue; String changeAddress = myAddress; // Build script for our address - List rawTxList = card.getUnspentTransactions(); + List rawTxList = btcData.getUnspentTransactions(); byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; // Collect unspent @@ -402,7 +493,7 @@ public class BtcEngine extends CoinEngine { unspentOutputs.get(i).bodyDoubleHash = doubleHashData; unspentOutputs.get(i).bodyHash = hashData; - if (card.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || card.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + if (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { dataForSign[i] = newTX; } else { dataForSign[i] = doubleHashData; @@ -410,7 +501,7 @@ public class BtcEngine extends CoinEngine { } byte[] signFromCard; - if (card.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || card.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + if (ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || ctx.getCard().getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { ByteArrayOutputStream bs = new ByteArrayOutputStream(); if (dataForSign.length > 10) throw new Exception("To much hashes in one transaction!"); for (int i = 0; i < dataForSign.length; i++) { @@ -420,21 +511,19 @@ public class BtcEngine extends CoinEngine { } signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value; } else { - signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, card.getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer, null, card.getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value; + 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; // TODO slice signFromCard to hashes.length parts } for (int i = 0; i < unspentOutputs.size(); ++i) { - BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)); + BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, i * 64, 32 + i * 64)); BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); s = CryptoUtil.toCanonicalised(s); - byte[] encodingSign = DerEncodingUtil.packSignDer(r, s, pbKey); - unspentOutputs.get(i).scriptForBuild = encodingSign; + unspentOutputs.get(i).scriptForBuild = DerEncodingUtil.packSignDer(r, s, pbKey); } - byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); - return realTX; + return BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/CoinData.java b/app/src/main/java/com/tangem/domain/wallet/CoinData.java new file mode 100644 index 0000000000..c23e6fb16f --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/CoinData.java @@ -0,0 +1,175 @@ +package com.tangem.domain.wallet; + +import android.os.Bundle; +import android.util.Log; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicInteger; + +public class CoinData { + + public CoinData() { + } + + public boolean isBalanceReceived() { + return balanceReceived; + } + + private boolean balanceReceived = false; + + public void setBalanceReceived(boolean value) { + balanceReceived = value; + } + + public void loadFromBundle(Bundle B) { + if (B.containsKey("balanceReceived")) setBalanceReceived(B.getBoolean("balanceReceived")); + + validationNodeDescription = B.getString("validationNodeDescription"); + + if (B.containsKey("FailedBalance")) + failedBalanceRequestCounter = new AtomicInteger(B.getInt("FailedBalance")); + + if (B.containsKey("isBalanceEqual")) setIsBalanceEqual(B.getBoolean("isBalanceEqual")); + + if (B.containsKey("rate")) + rate = B.getFloat("rate"); + if (B.containsKey("rateAlter")) + rateAlter = B.getFloat("rateAlter"); + } + + public void saveToBundle(Bundle B) { + try { + if (balanceEqual != null) B.putBoolean("isBalanceEqual", balanceEqual); + + if (failedBalanceRequestCounter != null) + B.putInt("FailedBalance", failedBalanceRequestCounter.get()); + + B.putFloat("rate", rate); + B.putFloat("rateAlter", rateAlter); + + B.putBoolean("balanceReceived", balanceReceived); + B.putString("validationNodeDescription", validationNodeDescription); + } catch (Exception e) { + Log.e("Can't save to bundle ", e.getMessage()); + } + + } + + public Bundle asBundle() { + Bundle bundle = new Bundle(); + saveToBundle(bundle); + return bundle; + } + + public static CoinData fromBundle(Blockchain blockchain, Bundle bundle) { + CoinEngine engine=CoinEngineFactory.create(blockchain); + if( engine==null ) return null; + CoinData result = engine.createCoinData(); + result.loadFromBundle(bundle); + return result; + } + + //TODO - move all to special engines + private float rate = 0; + private float rateAlter = 0; + + public float getRate() { + return rate; + } + + public float getRateAlter() { + return rateAlter; + } + + public void setRate(float rate) { + this.rate = rate; + } + + public void setRateAlter(float rate) { + this.rateAlter = rate; + } + +// public Double amountFromInternalUnits(Long internalAmount) { +// // TODO java.lang.NullPointerException: Attempt to invoke virtual method 'long java.lang.Long.longValue()' on a null object reference +// return ((double) internalAmount) / +// getBlockchain().getMultiplier(); +// } +// +// public Double amountFromInternalUnits(Integer internalAmount) { +// return ((double) internalAmount) / getBlockchain().getMultiplier(); +// } +// +// // TODO разобраться с балансами, привести к единому интерфейсу +// public Long internalUnitsFromString(String caption) { +// try { +// return FormatUtil.ConvertStringToLong(caption); +// } catch (Exception e) { +// return null; +// } +// } +// +// public String getAmountDescription(Double amount) { +// String output = FormatUtil.DoubleToString(amount); +// return output + " " + getBlockchain().getCurrency(); +// } + + public String getAmountEquivalentDescription(CoinEngine.Amount amount) { + if (getBlockchain() == Blockchain.Ethereum || getBlockchain() == Blockchain.EthereumTestNet || getBlockchain() == Blockchain.Token) { + return EthEngine.getAmountEquivalentDescriptionETH(amount, rate); + } + + return BtcEngine.getAmountEquivalentDescriptionBTC(amount.doubleValue(), rate); + } + + public boolean getAmountEquivalentDescriptionAvailable() { + return rate > 0; + } + + + public void clearInfo() { + setIsBalanceEqual(false); + } + + private AtomicInteger failedBalanceRequestCounter; + + public int incFailedBalanceRequestCounter() { + if (failedBalanceRequestCounter == null) + failedBalanceRequestCounter = new AtomicInteger(0); + return failedBalanceRequestCounter.incrementAndGet(); + } + + public void resetFailedBalanceRequestCounter() { + failedBalanceRequestCounter = new AtomicInteger(0); + } + + public int getFailedBalanceRequestCounter() { + if (failedBalanceRequestCounter == null) + return 0; + return failedBalanceRequestCounter.get(); + } + + private Boolean balanceEqual; + + public Boolean isBalanceEqual() { + return balanceEqual; + } + + public void setIsBalanceEqual(boolean isEqual) { + balanceEqual = isEqual; + } + + private String validationNodeDescription = ""; + + public String getValidationNodeDescription() { + return validationNodeDescription; + } + + public void setValidationNodeDescription(String validationNodeDescription) { + this.validationNodeDescription = validationNodeDescription; + } + + + + +} diff --git a/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java index 0dd9d64afa..d7ac0a517f 100644 --- a/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java @@ -1,9 +1,13 @@ package com.tangem.domain.wallet; import android.net.Uri; +import android.text.InputFilter; import com.tangem.domain.cardReader.CardProtocol; +import org.jetbrains.annotations.Nullable; + +import java.math.BigDecimal; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; @@ -13,66 +17,150 @@ import java.security.NoSuchProviderException; public abstract class CoinEngine { - public abstract String getNode(TangemCard card); + @Nullable + public static final String EXTRA_ENGINE = "CoinEngine"; - public abstract int getNodePort(TangemCard card); + public static class InternalAmount extends BigDecimal { + public InternalAmount() { + super(0); + } - public abstract void switchNode(TangemCard card); + public InternalAmount(String amountString) { + super(amountString); + } - public abstract boolean awaitingConfirmation(TangemCard card); + public InternalAmount(long amount) { + super(amount); + } - public abstract boolean hasBalanceInfo(TangemCard card); + public InternalAmount(BigDecimal amount) { + super(amount.unscaledValue(), amount.scale()); + } - public abstract boolean isBalanceNotZero(TangemCard card); + public boolean notZero() + { + return compareTo(BigDecimal.ZERO)>0; + } - public abstract boolean isBalanceAlterNotZero(TangemCard card); + public boolean isZero() { + return compareTo(BigDecimal.ZERO)==0; + } + } - public abstract boolean checkAmount(TangemCard card, String amount) throws Exception; + public static class Amount extends BigDecimal { + private Blockchain blockchain; - public abstract int getTokenDecimals(TangemCard card); + public Amount() { + super(0); + blockchain = Blockchain.Unknown; + } - public abstract String getContractAddress(TangemCard card); + public Amount(String amountString, Blockchain blockchain) { + super(amountString); + this.blockchain = blockchain; + } - public abstract byte[] sign(String feeValue, String amountValue, boolean IncFee, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception; + public Amount(Long amount, Blockchain blockchain) { + super(amount); + this.blockchain=blockchain; + } - public abstract boolean checkUnspentTransaction(TangemCard card); + public String getCurrency() { + return blockchain.getCurrency(); + } - public abstract Uri getShareWalletUriExplorer(TangemCard card); + @Override + public String toString() { + return super.toString() + " " + blockchain.getCurrency(); + } - public abstract Long getBalanceLong(TangemCard card); + public boolean notZero() + { + return compareTo(BigDecimal.ZERO)>0; + } - public abstract Uri getShareWalletUri(TangemCard card); + public String getStringToEdit() { + return super.toString(); + } - public abstract String evaluateFeeEquivalent(TangemCard card, String fee); + } - public abstract boolean checkAmountValue(TangemCard card, String amount, String fee, Long minFeeInInternalUnits, Boolean incfee); + protected TangemContext ctx; - public abstract boolean inOutPutVisible(); + public CoinEngine() { - public abstract String getBalance(TangemCard card); + } - public abstract String getBalanceWithAlter(TangemCard card); + public CoinEngine(TangemContext ctx) { + this.ctx = ctx; + } - public abstract String getBalanceCurrency(TangemCard card); + public abstract boolean awaitingConfirmation(); - public abstract String getFeeCurrency(); + public abstract boolean hasBalanceInfo(); + + public abstract boolean isBalanceNotZero(); + + public abstract boolean isBalanceAlterNotZero(); + + public abstract byte[] sign(String feeValue, String amountValue, boolean IncFee, String toValue, CardProtocol protocol) throws Exception; + + public abstract boolean checkUnspentTransaction() throws Exception; + + public abstract Uri getShareWalletUriExplorer(); + + public abstract Uri getShareWalletUri(); + +// public abstract Long getBalanceLong(TangemCard card); + + public abstract boolean checkNewTransactionAmount(Amount amount); + + // TODO - move minFeeInInternalUnits to CoinData + public abstract boolean checkNewTransactionAmountAndFee(Amount amount, Amount fee, Boolean isFeeIncluded, InternalAmount minFeeInInternalUnits); + + public abstract boolean validateBalance(BalanceValidator balanceValidator); + + public abstract Amount getBalance(); + + public abstract String getBalanceHTML(); + + public abstract String getBalanceCurrencyHTML(); + + public abstract InputFilter[] getAmountInputFilters(); + + public abstract String getOfflineBalanceHTML(); + + public abstract String evaluateFeeEquivalent(String fee); + + public abstract String getFeeCurrencyHTML(); public abstract boolean isNeedCheckNode(); - public abstract String getBalanceEquivalent(TangemCard card); + public abstract String getBalanceEquivalent(); - public abstract String getBalanceValue(TangemCard card); +// public abstract String getBalanceValue(TangemCard card); - public abstract String getAmountDescription(TangemCard card, String amount) throws Exception; +// public abstract String getAmountDescription(TangemCard card, String amount) throws Exception; - public abstract String getAmountEquivalentDescriptor(TangemCard card, String value); +// public abstract String getAmountEquivalentDescriptor(TangemCard card, String value); - public abstract boolean validateAddress(String address, TangemCard card); + public abstract boolean validateAddress(String address); - public abstract String calculateAddress(TangemCard card, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException; + public abstract String calculateAddress(byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException; - public abstract String convertByteArrayToAmount(TangemCard card, byte[] bytes) throws Exception; + public abstract Amount convertToAmount(InternalAmount internalAmount); + public abstract Amount convertToAmount(String strAmount); - public abstract byte[] convertAmountToByteArray(TangemCard card, String amount) throws Exception; + public abstract InternalAmount convertToInternalAmount(Amount amount) throws Exception; + public abstract InternalAmount convertToInternalAmount(byte[] bytes) throws Exception; + + public abstract byte[] convertToByteArray(InternalAmount internalAmount) throws Exception; + + +// public abstract CoinEngine swithToBaseEngine(); + + public abstract CoinData createCoinData(); + + public abstract String getUnspentInputsDescription(); } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.java b/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.java index 35693043a2..18d87dbd2a 100644 --- a/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.java +++ b/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.java @@ -5,17 +5,37 @@ package com.tangem.domain.wallet; */ public class CoinEngineFactory { - public static CoinEngine create(Blockchain chain) { - if (Blockchain.BitcoinCash == chain || Blockchain.BitcoinCashTestNet == chain) { - return new BtcCashEngine(); - } else if (Blockchain.Bitcoin == chain || Blockchain.BitcoinTestNet == chain) { - return new BtcEngine(); //TODO: ВРЕМЕНГГО!!!! - } else if (Blockchain.Ethereum == chain || Blockchain.EthereumTestNet == chain) { - return new EthEngine(); - } else if (Blockchain.Token == chain) { - return new TokenEngine(); + public static CoinEngine create(Blockchain blockchain) { + switch (blockchain) { + case Bitcoin: + case BitcoinTestNet: + return new BtcEngine(); + case BitcoinCash: + case BitcoinCashTestNet: + 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; + if (Blockchain.BitcoinCash == context.getBlockchain() || Blockchain.BitcoinCashTestNet == 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; } + return result; } } diff --git a/app/src/main/java/com/tangem/domain/wallet/EthData.java b/app/src/main/java/com/tangem/domain/wallet/EthData.java new file mode 100644 index 0000000000..ea3b052066 --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/EthData.java @@ -0,0 +1,114 @@ +package com.tangem.domain.wallet; + +import android.os.Bundle; +import android.util.Log; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class EthData extends CoinData +{ + private CoinEngine.InternalAmount balance=null; + private CoinEngine.InternalAmount balanceAlter=null; + + private BigInteger countConfirmedTX = null; + private BigInteger countUnconfirmedTX = BigInteger.valueOf(0); + + public BigInteger getConfirmedTXCount() { + if (countConfirmedTX == null) { + countConfirmedTX = BigInteger.valueOf(0); + } + return countConfirmedTX; + } + + public void setConfirmedTXCount(BigInteger count) { + countConfirmedTX = count; + } + + public BigInteger getUnconfirmedTXCount() { + if (countUnconfirmedTX == null) { + countUnconfirmedTX = BigInteger.valueOf(0); + } + return countUnconfirmedTX; + } + + public void setUnconfirmedTXCount(BigInteger count) { + countUnconfirmedTX = count; + } + + public String getAmountInGwei(String amount) { + BigInteger d = new BigInteger(amount, 10); + BigInteger m = d.divide(BigInteger.valueOf(1000000000L)); + return m.toString(10); + } + + @Override + public void clearInfo() { + super.clearInfo(); + balance = null; + balanceAlter = null; + } + + public CoinEngine.InternalAmount getBalanceInInternalUnits() { + return balance; + + } + public CoinEngine.InternalAmount getBalanceAlterInInternalUnits() { + return balanceAlter; + + } + + public void setBalanceInInternalUnits(CoinEngine.InternalAmount value) { + balance = value; + } + + public void setBalanceAlterInInternalUnits(CoinEngine.InternalAmount value) { + balanceAlter = value; + } + + public Long getBalanceETH() { + + BigDecimal b = null; + if (balance != null) { + b = balance; // Returns ETH / token balance + } else if (balanceAlter != null) { + b = balanceAlter; // or ETH balance if there're no tokens on Token card + } + + if (b != null) { + return b.longValue(); // Will leave only lower 64 bits for ETH and Tokens + } else { + return null; + } + } + + @Override + public void loadFromBundle(Bundle B) { + super.loadFromBundle(B); + + balance = new CoinEngine.InternalAmount(B.getString("BalanceDecimal")); + balanceAlter =new CoinEngine.InternalAmount(B.getString("BalanceDecimalAlter")); + + if (B.containsKey("confirmTx")) + countConfirmedTX = new BigInteger(B.getString("confirmTx"), 16); + if (B.containsKey("unconfirmTx")) + countUnconfirmedTX = new BigInteger(B.getString("unconfirmTx"), 16); + } + + @Override + public void saveToBundle(Bundle B) { + try { + B.putString("BalanceDecimal", balance.toString()); + B.putString("BalanceDecimalAlter", balance.toString()); + + B.putString("confirmTx", getConfirmedTXCount().toString(16)); + B.putString("unconfirmTx", getUnconfirmedTXCount().toString(16)); + + } catch (Exception e) { + Log.e("Can't save to bundle ", e.getMessage()); + } + + } + + +} diff --git a/app/src/main/java/com/tangem/domain/wallet/EthEngine.java b/app/src/main/java/com/tangem/domain/wallet/EthEngine.java index c72b28a461..c05855dd34 100644 --- a/app/src/main/java/com/tangem/domain/wallet/EthEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/EthEngine.java @@ -1,12 +1,14 @@ package com.tangem.domain.wallet; import android.net.Uri; +import android.text.InputFilter; import android.util.Log; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.TLV; import com.tangem.util.BTCUtils; import com.tangem.util.CryptoUtil; +import com.tangem.util.DecimalDigitsInputFilter; import org.bitcoinj.core.ECKey; @@ -17,7 +19,6 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.text.DecimalFormat; import java.util.Arrays; -import java.util.Date; import static com.tangem.util.FormatUtil.GetDecimalFormat; @@ -27,30 +28,68 @@ import static com.tangem.util.FormatUtil.GetDecimalFormat; public class EthEngine extends CoinEngine { - public String getNode(TangemCard mCard) { - return "abc1.hsmiths.com"; + public EthData ethData = null; + + public EthEngine(TangemContext ctx) throws Exception { + super(ctx); + if (ctx.getCoinData() == null) { + ethData = new EthData(); + ctx.setCoinData(ethData); + } else if (ctx.getCoinData() instanceof BtcData) { + ethData = (EthData) ctx.getCoinData(); + } else { + throw new Exception("Invalid type of Blockchain data for BtcEngine"); + } } - public int getNodePort(TangemCard mCard) { - return 60001; + public EthEngine() { + super(); } - public void switchNode(TangemCard mCard) { - } - public boolean inOutPutVisible() { + @Override + public boolean awaitingConfirmation(){ return false; } - public String getBalanceCurrency(TangemCard card) { + @Override + public String getBalanceHTML() { + if (hasBalanceInfo()) { + Amount balance = convertToAmount(ethData.getBalanceInInternalUnits()); + return balance.toString(); + } else { + return ""; + } + } + + @Override + public String getBalanceCurrencyHTML() { return "ETH"; } - public boolean awaitingConfirmation(TangemCard card) { - return false; + @Override + public String getOfflineBalanceHTML() { + InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance()); + Amount offlineAmount = convertToAmount(offlineInternalAmount); + return offlineAmount.toString(); } - public String getFeeCurrency() { + + @Override + public boolean isBalanceAlterNotZero() { + return true; + } + + + @Override + public boolean isBalanceNotZero() { + if( ethData==null ) return false; + if (ethData.getBalanceInInternalUnits() == null) return false; + return ethData.getBalanceInInternalUnits().notZero(); + } + + @Override + public String getFeeCurrencyHTML() { return "Gwei"; } @@ -66,10 +105,6 @@ public class EthEngine extends CoinEngine { return d; } - public int getTokenDecimals(TangemCard card) { - return 0; - } - public String getContractAddress(TangemCard card) { return ""; } @@ -151,7 +186,7 @@ public class EthEngine extends CoinEngine { return mCard.getBalance(); } - public String getBalanceWithAlter(TangemCard mCard) { + public String getBalanceHTML(TangemCard mCard) { return getBalance(mCard); } @@ -215,8 +250,9 @@ public class EthEngine extends CoinEngine { return true; } - public boolean hasBalanceInfo(TangemCard card) { - return card.hasBalanceInfo(); + @Override + public boolean hasBalanceInfo() { + return ethData.hasBalanceInfo(); } public Uri getShareWalletUri(TangemCard mCard) { @@ -239,6 +275,12 @@ public class EthEngine extends CoinEngine { } + @Override + public InputFilter[] getAmountInputFilters() { + return new InputFilter[] { new DecimalDigitsInputFilter(18) }; + } + + public boolean checkAmountValue(TangemCard mCard, String amountValue, String feeValue, Long minFeeInInternalUnits, Boolean incfee) { // Long fee = null; // Long amount = null; @@ -263,7 +305,7 @@ public class EthEngine extends CoinEngine { try { BigDecimal tmpFee = new BigDecimal(feeValue); BigDecimal tmpAmount = new BigDecimal(amountValue); - BigDecimal cardBalance = new BigDecimal(mCard.getDecimalBalance()); + BigDecimal cardBalance = new BigDecimal(ethData.getDecimalBalance()); tmpAmount = tmpAmount.multiply(new BigDecimal("1000000000")); cardBalance = cardBalance.divide(new BigDecimal("1000000000")); //if (tmpFee.compareTo(tmpAmount) > 0) @@ -311,7 +353,7 @@ public class EthEngine extends CoinEngine { public byte[] sign(String feeValue, String amountValue, boolean IncFee, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception { - BigInteger nonceValue = mCard.getConfirmedTXCount(); + BigInteger nonceValue = ethData.getConfirmedTXCount(); byte[] pbKey = mCard.getWalletPublicKey(); boolean flag = (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer); Issuer issuer = mCard.getIssuer(); diff --git a/app/src/main/java/com/tangem/domain/wallet/TangemCard.java b/app/src/main/java/com/tangem/domain/wallet/TangemCard.java index 3bd6ad86a3..7ccdd26107 100644 --- a/app/src/main/java/com/tangem/domain/wallet/TangemCard.java +++ b/app/src/main/java/com/tangem/domain/wallet/TangemCard.java @@ -5,15 +5,9 @@ import android.util.Log; import com.google.common.base.Strings; import com.tangem.domain.cardReader.SettingsMask; -import com.tangem.util.FormatUtil; import com.tangem.util.Util; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; import java.util.Date; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; /** * Created by dvol on 16.07.2017. @@ -28,11 +22,6 @@ public class TangemCard { private Status status; private String wallet; private String UID; - private String error; - private String message; - private String balanceDecimal; - private String balanceDecimalAlter = ""; - private Long balanceConfirmed, balanceUnconfirmed; private String blockchainID; private Manufacturer manufacturer = Manufacturer.Unknown; private boolean manufacturerConfirmed = false; @@ -43,49 +32,6 @@ public class TangemCard { private byte[] pbCardKey = null; private byte[] pbWalletKeyRar = null; private Date dtPersonalization = null; - private float rate = 0; - private float rateAlter = 0; - - private BigInteger countConfirmedTX = null; - private BigInteger countUnconfirmedTX = BigInteger.valueOf(0); - - public BigInteger getConfirmedTXCount() { - if (countConfirmedTX == null) { - countConfirmedTX = BigInteger.valueOf(0); - } - return countConfirmedTX; - } - - public void setConfirmedTXCount(BigInteger count) { - countConfirmedTX = count; - } - - public BigInteger getUnconfirmedTXCount() { - if (countUnconfirmedTX == null) { - countUnconfirmedTX = BigInteger.valueOf(0); - } - return countUnconfirmedTX; - } - - public void setUnconfirmedTXCount(BigInteger count) { - countUnconfirmedTX = count; - } - - public float getRate() { - return rate; - } - - public float getRateAlter() { - return rateAlter; - } - - public void setRate(float rate) { - this.rate = rate; - } - - public void setRateAlter(float rate) { - this.rateAlter = rate; - } public String getBlockchainID() { return blockchainID; @@ -95,6 +41,10 @@ public class TangemCard { return Blockchain.fromId(blockchainID); } + public void setBlockchain(Blockchain blockchain) { + blockchainID=blockchain.getID(); + } + public void setBlockchainID(String blockchainID) { this.blockchainID = blockchainID; } @@ -106,17 +56,12 @@ public class TangemCard { String oldName = getBlockchain().getOfficialName(); //String newName = String.format("%s - %s ERC20 token", token, oldName); String newName = token + "
" + oldName + " ERC20 token"; - setBlockchainName(newName); + blockchainName=newName; } private String blockchainName = ""; - public void setBlockchainName(String name) { - blockchainName = name; - } - - public String getBlockchainName() { if (Strings.isNullOrEmpty(blockchainName)) return getBlockchain().getOfficialName(); @@ -180,47 +125,6 @@ public class TangemCard { return cardPublicKeyValid; } - public Double amountFromInternalUnits(Long internalAmount) { - // TODO java.lang.NullPointerException: Attempt to invoke virtual method 'long java.lang.Long.longValue()' on a null object reference - return ((double) internalAmount) / - getBlockchain().getMultiplier(); - } - - public Double amountFromInternalUnits(Integer internalAmount) { - return ((double) internalAmount) / getBlockchain().getMultiplier(); - } - - // TODO разобраться с балансами, привести к единому интерфейсу - public Long internalUnitsFromString(String caption) { - try { - return FormatUtil.ConvertStringToLong(caption); - } catch (Exception e) { - return null; - } - } - - public String getAmountDescription(Double amount) { - String output = FormatUtil.DoubleToString(amount); - return output + " " + getBlockchain().getCurrency(); - } - - public String getAmountEquivalentDescription(Double amount) { - if (getBlockchain() == Blockchain.Ethereum || getBlockchain() == Blockchain.EthereumTestNet || getBlockchain() == Blockchain.Token) { - return EthEngine.getAmountEquivalentDescriptionETH(amount, rate); - } - - return BtcEngine.getAmountEquivalentDescriptionBTC(amount, rate); - } - - public boolean getAmountEquivalentDescriptionAvailable() { - return rate > 0; - } - - public String getAmountInGwei(String amount) { - BigInteger d = new BigInteger(amount, 10); - BigInteger m = d.divide(BigInteger.valueOf(1000000000L)); - return m.toString(10); - } public Manufacturer getManufacturer() { return manufacturer; @@ -285,13 +189,7 @@ public class TangemCard { this.PIN = PIN; } - public void clearInfo() { - balanceConfirmed = null; - balanceUnconfirmed = null; - unspentTransactions = null; - balanceDecimal = null; - balanceDecimalAlter = null; - setIsBalanceEqual(false); + public void switchToInitialBlockchain() { if (tokenSymbol.length() > 1) blockchainID = Blockchain.Token.getID(); // Reset blockchain to Token from ETH for token cards with zero token balance on it } @@ -306,7 +204,6 @@ public class TangemCard { public String getPersonalizationDateTimeDescription() { return Util.formatDate(dtPersonalization); - } private int health = 0; @@ -418,34 +315,6 @@ public class TangemCard { return pauseBeforePIN2; } - private AtomicInteger failedBalanceRequestCounter; - - public int incFailedBalanceRequestCounter() { - if (failedBalanceRequestCounter == null) - failedBalanceRequestCounter = new AtomicInteger(0); - return failedBalanceRequestCounter.incrementAndGet(); - } - - public void resetFailedBalanceRequestCounter() { - failedBalanceRequestCounter = new AtomicInteger(0); - } - - public int getFailedBalanceRequestCounter() { - if (failedBalanceRequestCounter == null) - return 0; - return failedBalanceRequestCounter.get(); - } - - private Boolean balanceEqual; - - public Boolean isBalanceEqual() { - return balanceEqual; - } - - public void setIsBalanceEqual(boolean isEqual) { - balanceEqual = isEqual; - } - private Integer settingsMask = null; public void setSettingsMask(int settingsMask) { @@ -591,16 +460,6 @@ public class TangemCard { return batch; } - private String validationNodeDescription = ""; - - public String getValidationNodeDescription() { - return validationNodeDescription; - } - - public void setValidationNodeDescription(String validationNodeDescription) { - this.validationNodeDescription = validationNodeDescription; - } - public enum SigningMethod { Sign_Hash(0, "sign hash"), Sign_Raw(1, "sign raw tx"), @@ -638,40 +497,32 @@ public class TangemCard { return signingMethod; } - public static class UnspentTransaction { - public String txID; - public Integer Amount; - public Integer Height; - public String Raw = ""; - - public Bundle getAsBundle() { - Bundle B = new Bundle(); - B.putString("txID", txID); - B.putInt("Amount", Amount); - B.putInt("Height", Height); - B.putString("Raw", Raw); - return B; - } - - public void loadFromBundle(Bundle B) { - txID = B.getString("txID"); - Amount = B.getInt("Amount"); - Height = B.getInt("Height"); - Raw = B.getString("Raw"); - } - } - - private List unspentTransactions = null; - - public List getUnspentTransactions() { - if (unspentTransactions == null) unspentTransactions = new ArrayList<>(); - return unspentTransactions; - } - public TangemCard(String UID) { this.UID = UID; } + + public enum Status { + NotPersonalized(0), Empty(1), Loaded(2), Purged(3); + + Status(int Code) { + mCode = Code; + } + + private int mCode; + + public int getCode() { + return mCode; + } + + public static Status fromCode(int code) { + for (Status s : values()) { + if (s.getCode() == code) return s; + } + return null; + } + } + public void setStatus(Status status) { this.status = status; } @@ -721,58 +572,6 @@ public class TangemCard { this.UID = UID; } - public Long getBalance() { - - BigDecimal balance = null; - - if ((this.getBlockchain() == Blockchain.Bitcoin || this.getBlockchain() == Blockchain.BitcoinCash || this.getBlockchain() == Blockchain.BitcoinTestNet || this.getBlockchain() == Blockchain.BitcoinCashTestNet) && balanceConfirmed != null && balanceUnconfirmed != null) { - balance = BigDecimal.valueOf(balanceConfirmed + balanceUnconfirmed); - } else if (this.getBlockchain() == Blockchain.Ethereum || this.getBlockchain() == Blockchain.EthereumTestNet || this.getBlockchain() == Blockchain.Token) { - if (balanceDecimal != null) { - balance = new BigDecimal(balanceDecimal); // Returns ETH / token balance - } else if (balanceDecimalAlter != null) { - balance = new BigDecimal(balanceDecimalAlter); // or ETH balance if there're no tokens on Token card - } - } - - if (balance != null) { - return balance.longValue(); // Will leave only lower 64 bits for ETH and Tokens - } else { - return null; - } - } - - public Long getBalanceUnconfirmed() { - return balanceUnconfirmed; - } - - public void setBalanceConfirmed(Long balance) { - this.balanceConfirmed = balance; - } - - public void setBalanceUnconfirmed(Long balance) { - this.balanceUnconfirmed = balance; - } - - public boolean hasBalanceInfo() { - return balanceConfirmed != null || balanceUnconfirmed != null || balanceDecimal != "" || balanceDecimalAlter != ""; - } - - public String getDecimalBalance() { - return balanceDecimal; - } - - public String getDecimalBalanceAlter() { - return balanceDecimalAlter; - } - - public void setDecimalBalance(String value) { - balanceDecimal = value; - } - - public void setDecimalBalanceAlter(String value) { - balanceDecimalAlter = value; - } private byte[] offlineBalance; @@ -799,7 +598,10 @@ public class TangemCard { public void setDenomination(byte[] denomination) { this.Denomination = denomination; try { - this.DenominationText = CoinEngineFactory.create(getBlockchain()).convertByteArrayToAmount(this, denomination); + CoinEngine engine=CoinEngineFactory.create(getBlockchain()); + CoinEngine.InternalAmount internalAmount=engine.convertToInternalAmount(denomination); + CoinEngine.Amount amount=engine.convertToAmount(internalAmount); + this.DenominationText = amount.toString(); } catch (Exception e) { e.printStackTrace(); this.DenominationText = "N/A"; @@ -834,43 +636,6 @@ public class TangemCard { DenominationText = null; } - public void setError(String error) { - this.error = error; - } - - public String getError() { - return error; - } - - public void setMessage(String value) { - this.message = value; - } - - public String getMessage() { - return message; - } - - public enum Status { - NotPersonalized(0), Empty(1), Loaded(2), Purged(3); - - Status(int Code) { - mCode = Code; - } - - private int mCode; - - public int getCode() { - return mCode; - } - - public static Status fromCode(int code) { - for (Status s : values()) { - if (s.getCode() == code) return s; - } - return null; - } - } - public Bundle getAsBundle() { Bundle B = new Bundle(); saveToBundle(B); @@ -889,7 +654,6 @@ public class TangemCard { B.putInt("TokensDecimal", tokensDecimal); B.putString("TokenSymbol", tokenSymbol); B.putString("ContractAddress", contractAddress); - B.putString("validationNodeDescription", validationNodeDescription); if (dtPersonalization != null) B.putLong("dtPersonalization", dtPersonalization.getTime()); B.putInt("RemainingSignatures", remainingSignatures); B.putInt("MaxSignatures", maxSignatures); @@ -902,26 +666,18 @@ public class TangemCard { if (issuer != null) B.putString("Issuer", issuer.getID()); if (issuerPublicDataKey != null) B.putByteArray("IssuerPublicDataKey", issuerPublicDataKey); if (firmwareVersion != null) B.putString("FirmwareVersion", firmwareVersion); - if (balanceEqual != null) B.putBoolean("isBalanceEqual", balanceEqual); if (batch != null) B.putString("Batch", batch); - B.putString("BalanceDecimal", balanceDecimal); - B.putString("BalanceDecimalAlter", balanceDecimalAlter); B.putBoolean("ManufacturerConfirmed", manufacturerConfirmed); B.putBoolean("CardPublicKeyValid", isCardPublicKeyValid()); B.putByteArray("CardPublicKey", getCardPublicKey()); - if (failedBalanceRequestCounter != null) - B.putInt("FailedBalance", failedBalanceRequestCounter.get()); B.putInt("SignedHashes", getSignedHashes()); B.putString("Wallet", wallet); - B.putString("Error", error); B.putBoolean("WalletPublicKeyValid", isWalletPublicKeyValid()); if (pbWalletKey != null) B.putByteArray("PublicKey", pbWalletKey); if (pbWalletKeyRar != null) B.putByteArray("PublicKeyRar", pbWalletKeyRar); - if (balanceConfirmed != null) B.putLong("BalanceConfirmed", balanceConfirmed); - if (balanceUnconfirmed != null) B.putLong("BalanceUnconfirmed", balanceUnconfirmed); if (getOfflineBalance() != null) B.putByteArray("OfflineBalance", getOfflineBalance()); @@ -933,18 +689,6 @@ public class TangemCard { B.putBoolean("NeedWriteIssuerData", getNeedWriteIssuerData()); } - if (unspentTransactions != null) { - Bundle BB = new Bundle(); - for (Integer i = 0; i < unspentTransactions.size(); i++) { - BB.putBundle(i.toString(), unspentTransactions.get(i).getAsBundle()); - } - B.putBundle("UnspentTransactions", BB); - } - B.putFloat("rate", rate); - B.putFloat("rateAlter", rateAlter); - B.putString("confirmTx", getConfirmedTXCount().toString(16)); - B.putString("unconfirmTx", getUnconfirmedTXCount().toString(16)); - if (codeConfirmed != null) B.putBoolean("codeConfirmed", codeConfirmed); @@ -954,13 +698,9 @@ public class TangemCard { if (onlineVerified != null) B.putBoolean("onlineVerified", onlineVerified); - B.putBoolean("balanceReceived", balanceReceived); - - if (onlineValidated != null) B.putBoolean("onlineValidated", onlineValidated); - if (codeConfirmed != null) B.putBoolean("codeConfirmed", codeConfirmed); @@ -978,16 +718,6 @@ public class TangemCard { } - public boolean isBalanceReceived() { - return balanceReceived; - } - - private boolean balanceReceived = false; - - public void setBalanceReceived(boolean value) { - balanceReceived = value; - } - public void loadFromBundle(Bundle B) { UID = B.getString("UID"); CID = B.getByteArray("CID"); @@ -995,19 +725,15 @@ public class TangemCard { PIN2 = PIN2_Mode.valueOf(B.getString("PIN2")); status = Status.valueOf(B.getString("Status")); wallet = B.getString("Wallet"); - error = B.getString("Error"); blockchainID = B.getString("Blockchain"); tokensDecimal = B.getInt("TokensDecimal", 18); tokenSymbol = B.getString("TokenSymbol", ""); contractAddress = B.getString("ContractAddress", ""); if (B.containsKey("BlockchainName")) blockchainName = B.getString("BlockchainName", ""); - validationNodeDescription = B.getString("validationNodeDescription"); if (B.containsKey("dtPersonalization")) { dtPersonalization = new Date(B.getLong("dtPersonalization")); } - balanceDecimal = B.getString("BalanceDecimal"); - balanceDecimalAlter = B.getString("BalanceDecimalAlter"); remainingSignatures = B.getInt("RemainingSignatures"); maxSignatures = B.getInt("MaxSignatures"); health = B.getInt("health"); @@ -1025,8 +751,6 @@ public class TangemCard { if (B.containsKey("SignedHashes")) setSignedHashes(B.getInt("SignedHashes")); - if (B.containsKey("FailedBalance")) - failedBalanceRequestCounter = new AtomicInteger(B.getInt("FailedBalance")); if (B.containsKey("Issuer")) issuer = Issuer.FindIssuer(B.getString("Issuer")); if (B.containsKey("IssuerPublicDataKey")) issuerPublicDataKey = B.getByteArray("IssuerPublicDataKey"); @@ -1034,17 +758,9 @@ public class TangemCard { if (B.containsKey("FirmwareVersion")) firmwareVersion = B.getString("FirmwareVersion"); if (B.containsKey("Batch")) batch = B.getString("Batch"); - if (B.containsKey("isBalanceEqual")) setIsBalanceEqual(B.getBoolean("isBalanceEqual")); cardPublicKeyValid = B.getBoolean("CardPublicKeyValid"); if (B.containsKey("CardPublicKey")) setCardPublicKey(B.getByteArray("CardPublicKey")); - if (B.containsKey("balanceReceived")) setBalanceReceived(B.getBoolean("balanceReceived")); - if (B.containsKey("BalanceConfirmed")) balanceConfirmed = B.getLong("BalanceConfirmed"); - else balanceConfirmed = null; - if (B.containsKey("BalanceUnconfirmed")) - balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); - else balanceUnconfirmed = null; - if (B.containsKey("OfflineBalance")) setOfflineBalance(B.getByteArray("OfflineBalance")); else clearOfflineBalance(); @@ -1066,26 +782,6 @@ public class TangemCard { pbWalletKeyRar = B.getByteArray("PublicKeyRar"); } - if (B.containsKey("UnspentTransactions")) { - unspentTransactions = new ArrayList<>(); - Bundle BB = B.getBundle("UnspentTransactions"); - Integer i = 0; - while (BB.containsKey(i.toString())) { - UnspentTransaction t = new UnspentTransaction(); - t.loadFromBundle(BB.getBundle(i.toString())); - unspentTransactions.add(t); - i++; - } - } - if (B.containsKey("rate")) - rate = B.getFloat("rate"); - if (B.containsKey("rateAlter")) - rateAlter = B.getFloat("rateAlter"); - if (B.containsKey("confirmTx")) - countConfirmedTX = new BigInteger(B.getString("confirmTx"), 16); - if (B.containsKey("unconfirmTx")) - countUnconfirmedTX = new BigInteger(B.getString("unconfirmTx"), 16); - if (B.containsKey("codeConfirmed")) codeConfirmed = B.getBoolean("codeConfirmed"); @@ -1096,19 +792,6 @@ public class TangemCard { onlineValidated = B.getBoolean("onlineValidated"); } - private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); - - public static String bytesToHex(byte[] bytes) { - if (bytes == null) return ""; - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - public enum EncryptionMode { None((byte) 0x0), Fast((byte) 0x1), Strong((byte) 0x2); diff --git a/app/src/main/java/com/tangem/domain/wallet/TangemContext.java b/app/src/main/java/com/tangem/domain/wallet/TangemContext.java new file mode 100644 index 0000000000..b9b070ceb6 --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/TangemContext.java @@ -0,0 +1,114 @@ +package com.tangem.domain.wallet; + +import android.content.Context; +import android.os.Bundle; + + +public class TangemContext { + private static final String EXTRA_BLOCKCHAIN_DATA = "BLOCKCHAIN_DATA"; + private Context context; + private TangemCard card; + private CoinData coinData; + private String error; + private String message; + + + public TangemContext() { + + } + + public TangemContext(TangemCard card) { + this.card = card; + } + + public Blockchain getBlockchain() { + if (card == null) return Blockchain.Unknown; + return card.getBlockchain(); + } + + public void setBlockchain(Blockchain blockchain) { + if (card == null) return; + card.setBlockchain(blockchain); + } + + public Context getContext() { + return context; + } + + public void setContext(Context context) { + this.context = context; + } + + public TangemCard getCard() { + return card; + } + + public void setCard(TangemCard card) { + this.card = card; + } + + public CoinData getCoinData() { + return coinData; + } + + public void setCoinData(CoinData coinData) { + this.coinData = coinData; + } + + public void setError(String error) { + this.error = error; + } + + public String getError() { + return error; + } + + public void setMessage(String value) { + this.message = value; + } + + public String getMessage() { + return message; + } + + + public static TangemContext loadFromBundle(Context context, Bundle bundle) { + TangemContext tangemContext = new TangemContext(); + tangemContext.setContext(context); + + if (bundle.containsKey(TangemCard.EXTRA_UID)) { + tangemContext.card = new TangemCard(bundle.getString(TangemCard.EXTRA_UID)); + tangemContext.card.loadFromBundle(bundle.getBundle(TangemCard.EXTRA_CARD)); + } + + if (tangemContext.getBlockchain() != null && bundle.containsKey(EXTRA_BLOCKCHAIN_DATA)) { + tangemContext.coinData=CoinData.fromBundle(tangemContext.getBlockchain(), bundle.getBundle(EXTRA_BLOCKCHAIN_DATA)); + } + + tangemContext.error = bundle.getString("Error"); + tangemContext.message = bundle.getString("Message"); + + return tangemContext; + } + + public void saveToBundle(Bundle bundle) { + + if (card != null) { + bundle.putString(TangemCard.EXTRA_UID, card.getUID()); + bundle.putBundle(TangemCard.EXTRA_CARD, card.getAsBundle()); + } + + if (coinData != null) { + bundle.putBundle(EXTRA_BLOCKCHAIN_DATA, coinData.asBundle()); + } + + bundle.putString("Error", error); + bundle.putString("Message", message); + + } + + public String getString(int stringId) { + if( context!=null ) return getContext().getResources().getString(stringId); + return "context.resources.string["+stringId+"]"; + } +} diff --git a/app/src/main/java/com/tangem/domain/wallet/TokenEngine.java b/app/src/main/java/com/tangem/domain/wallet/TokenEngine.java index 99c1dcfb62..3911020cbb 100644 --- a/app/src/main/java/com/tangem/domain/wallet/TokenEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/TokenEngine.java @@ -8,6 +8,7 @@ import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.TLV; import com.tangem.util.BTCUtils; import com.tangem.util.CryptoUtil; +import com.tangem.wallet.R; import org.bitcoinj.core.ECKey; @@ -28,24 +29,23 @@ import static com.tangem.util.FormatUtil.GetDecimalFormat; public class TokenEngine extends CoinEngine { - public String getNode(TangemCard mCard) { - return "abc1.hsmiths.com"; + @Override + public String getOfflineBalanceHTML() { + return ctx.getString(R.string.not_implemented); } - public int getNodePort(TangemCard mCard) { - return 60001; + public TokenEngine(TangemContext context) { + super(context); } - public void switchNode(TangemCard mCard) { + public TokenEngine() { + } public boolean awaitingConfirmation(TangemCard card) { return false; } - public boolean inOutPutVisible() { - return false; - } public String getBalanceCurrency(TangemCard card) { String currency = card.getTokenSymbol(); @@ -219,7 +219,7 @@ public class TokenEngine extends CoinEngine { } - public String getBalanceWithAlter(TangemCard mCard) { + public String getBalanceHTML(TangemCard mCard) { //return getBalance(mCard) + "\n(" + GetBalanceAlterValue(mCard) + " ETH)"; if (GetBalanceAlterValue(mCard) != "") { return " " + getBalance(mCard) + "
+ " + GetBalanceAlterValue(mCard) + " ETH for gas"; diff --git a/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.kt b/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.kt index 17518b3fbd..32581170ec 100644 --- a/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.kt @@ -40,14 +40,16 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { private var serverApiHelper: ServerApiHelper = ServerApiHelper() private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum() - private var card: TangemCard? = null + //private var card: TangemCard? = null + private lateinit var ctx: TangemContext + private var feeRequestSuccess = false private var balanceRequestSuccess = false private var minFee: String? = null private var maxFee: String? = null private var normalFee: String? = null private var isIncludeFee: Boolean = true - private var minFeeInInternalUnits: Long? = 0L + private var minFeeInInternalUnits: CoinEngine.InternalAmount? = CoinEngine.InternalAmount(0) private var requestPIN2Count = 0 private var nodeCheck = false private var dtVerified: Date? = null @@ -61,18 +63,14 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra("UID")) - card!!.loadFromBundle(intent.extras!!.getBundle("Card")) + ctx = TangemContext.loadFromBundle(this, intent.extras) +// card = TangemCard(intent.getStringExtra("UID")) +// card!!.loadFromBundle(intent.extras!!.getBundle("Card")) +// + val engine = CoinEngineFactory.create(ctx) - val engine = CoinEngineFactory.create(card!!.blockchain) - - val balanceWithAlter = engine!!.getBalanceWithAlter(card).replace(",", ".") - - if (card!!.blockchain == Blockchain.Token) { - val html = Html.fromHtml(balanceWithAlter) + val html = Html.fromHtml(engine!!.balanceHTML) tvBalance.text = html - } else - tvBalance.text = balanceWithAlter isIncludeFee = intent.getBooleanExtra("IncFee", true) @@ -80,14 +78,14 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { tvIncFee.setText(R.string.including_fee) else tvIncFee.setText(R.string.not_including_fee) - if (card!!.blockchain == Blockchain.Token) + if (ctx.blockchain == Blockchain.Token) tvIncFee.visibility = View.INVISIBLE else tvIncFee.visibility = View.VISIBLE etAmount.setText(intent.getStringExtra(SignPaymentActivity.EXTRA_AMOUNT)) - tvCurrency.text = engine.getBalanceCurrency(card) - tvCurrency2.text = engine.feeCurrency - tvCardID.text = card!!.cidDescription + tvCurrency.text = Html.fromHtml(engine.balanceCurrencyHTML) + tvCurrency2.text = Html.fromHtml(engine.feeCurrencyHTML) + tvCardID.text = ctx.card!!.cidDescription etWallet.setText(intent.getStringExtra("Wallet")) etFee.setText("") @@ -95,7 +93,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { feeRequestSuccess = false balanceRequestSuccess = false - if (card!!.blockchain == Blockchain.Ethereum || card!!.blockchain == Blockchain.EthereumTestNet || card!!.blockchain == Blockchain.Token) { + if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet || ctx.blockchain == Blockchain.Token) { rgFee.isEnabled = false requestInfura(ServerApiHelper.INFURA_ETH_GAS_PRICE) @@ -103,7 +101,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { } else { rgFee.isEnabled = true - requestElectrum(card!!, ElectrumRequest.checkBalance(card!!.wallet)) + requestElectrum(ctx.card, ElectrumRequest.checkBalance(ctx.card!!.wallet)) calcSize = 256 try { @@ -112,7 +110,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { Log.e("Build Fee error", ex.message) } - card!!.resetFailedBalanceRequestCounter() + ctx.coinData!!.resetFailedBalanceRequestCounter() progressBar.visibility = View.VISIBLE @@ -128,11 +126,11 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { try { - val engine = CoinEngineFactory.create(card!!.blockchain) - val eqFee = engine!!.evaluateFeeEquivalent(card, etFee!!.text.toString()) + val engine = CoinEngineFactory.create(ctx.blockchain) + val eqFee = engine!!.evaluateFeeEquivalent(etFee!!.text.toString()) tvFeeEquivalent.text = eqFee - if (!card!!.amountEquivalentDescriptionAvailable) { + if (!ctx.coinData!!.amountEquivalentDescriptionAvailable) { tvFeeEquivalent.error = "Service unavailable" tvCurrency2.visibility = View.GONE tvFeeEquivalent.visibility = View.GONE @@ -158,30 +156,30 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { return@setOnClickListener } - val engineCoin = CoinEngineFactory.create(card!!.blockchain) + val engineCoin = CoinEngineFactory.create(ctx) if (engineCoin!!.isNeedCheckNode && !nodeCheck) { Toast.makeText(baseContext, getString(R.string.cannot_reach_current_active_blockchain_node_try_again), Toast.LENGTH_LONG).show() return@setOnClickListener } - val txFee = etFee.text.toString() - val txAmount = etAmount.text.toString() + val txFee = engineCoin.convertToAmount(etFee.text.toString()) + val txAmount = engineCoin.convertToAmount(etAmount.text.toString()) - if (!engineCoin.hasBalanceInfo(card)) { + if (!engineCoin.hasBalanceInfo()) { finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_check_balance_no_connection_with_blockchain_nodes)) return@setOnClickListener - } else if (!engineCoin.isBalanceNotZero(card)) { + } else if (!engineCoin.isBalanceNotZero) { finishWithError(Activity.RESULT_CANCELED, getString(R.string.the_wallet_is_empty)) return@setOnClickListener - } else if (!engineCoin.checkUnspentTransaction(card)) { + } else if (!engineCoin.checkUnspentTransaction()) { finishWithError(Activity.RESULT_CANCELED, getString(R.string.please_wait_for_confirmation_of_incoming_transaction)) return@setOnClickListener } - if (!engineCoin.checkAmountValue(card, txAmount, txFee, minFeeInInternalUnits, isIncludeFee)) { + if (!engineCoin.checkNewTransactionAmountAndFee(txAmount, txFee, isIncludeFee, minFeeInInternalUnits)) { finishWithError(Activity.RESULT_CANCELED, getString(R.string.not_enough_funds_on_your_card)) return@setOnClickListener } @@ -189,8 +187,9 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { requestPIN2Count = 0 val intent = Intent(baseContext, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) - intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) intent.putExtra("IncFee", isIncludeFee) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2) } @@ -201,7 +200,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { if (electrumRequest!!.isMethod(ElectrumRequest.METHOD_GetBalance)) { try { etFee.setText(getString(R.string.empty)) - if ((electrumRequest.result.getInt("confirmed") + electrumRequest.result.getInt("unconfirmed")) / card!!.blockchain.multiplier * 1000000.0 < java.lang.Float.parseFloat(etAmount.text.toString())) { + if ((electrumRequest.result.getInt("confirmed") + electrumRequest.result.getInt("unconfirmed")) / ctx.blockchain.multiplier * 1000000.0 < java.lang.Float.parseFloat(etAmount.text.toString())) { etFee.error = getString(R.string.not_enough_funds) } else { etFee.error = null @@ -214,7 +213,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { } } catch (e: JSONException) { e.printStackTrace() - requestElectrum(card!!, ElectrumRequest.checkBalance(card!!.wallet)) + requestElectrum(ctx.card!!, ElectrumRequest.checkBalance(ctx.card!!.wallet)) } } } @@ -236,10 +235,10 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { // rounding gas price to integer gwei val l = BigInteger(gasPrice, 16).divide(BigInteger.valueOf(1000000000L)).multiply(BigInteger.valueOf(1000000000L)) - val m = if (card!!.blockchain == Blockchain.Token) BigInteger.valueOf(60000) else BigInteger.valueOf(21000) - val minFeeInGwei = card!!.getAmountInGwei(l.multiply(m).toString()) - val normalFeeInGwei = card!!.getAmountInGwei(l.multiply(BigInteger.valueOf(12)).divide(BigInteger.valueOf(10)).multiply(m).toString()) - val maxFeeInGwei = card!!.getAmountInGwei(l.multiply(BigInteger.valueOf(15)).divide(BigInteger.valueOf(10)).multiply(m).toString()) + val m = if (ctx.blockchain == Blockchain.Token) BigInteger.valueOf(60000) else BigInteger.valueOf(21000) + val minFeeInGwei = (ctx.coinData!! as EthData).getAmountInGwei(l.multiply(m).toString()) + val normalFeeInGwei = (ctx.coinData!! as EthData).getAmountInGwei(l.multiply(BigInteger.valueOf(12)).divide(BigInteger.valueOf(10)).multiply(m).toString()) + val maxFeeInGwei = (ctx.coinData!! as EthData).getAmountInGwei(l.multiply(BigInteger.valueOf(15)).divide(BigInteger.valueOf(10)).multiply(m).toString()) minFee = minFeeInGwei normalFee = normalFeeInGwei @@ -250,7 +249,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { feeRequestSuccess = true balanceRequestSuccess = true dtVerified = Date() - minFeeInInternalUnits = card!!.internalUnitsFromString(normalFeeInGwei) + minFeeInInternalUnits = CoinEngine.InternalAmount(normalFeeInGwei) } } } @@ -293,7 +292,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { when (blockCount) { ServerApiHelper.ESTIMATE_FEE_MINIMAL -> { minFee = strFee - minFeeInInternalUnits = card!!.internalUnitsFromString(strFee) + minFeeInInternalUnits = CoinEngine.InternalAmount(strFee) } ServerApiHelper.ESTIMATE_FEE_NORMAL -> { @@ -343,15 +342,16 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { if (data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) { val updatedCard = TangemCard(data.getStringExtra("UID")) updatedCard.loadFromBundle(data.getBundleExtra("Card")) - card = updatedCard + ctx.card = updatedCard } } if (resultCode == SignPaymentActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { requestPIN2Count++ val intent = Intent(baseContext, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra("UID", card!!.uid) +// intent.putExtra("Card", card!!.asBundle) intent.putExtra("IncFee", isIncludeFee) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2) return @@ -361,8 +361,9 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { } else if (requestCode == REQUEST_CODE_REQUEST_PIN2) { if (resultCode == Activity.RESULT_OK) { val intent = Intent(baseContext, SignPaymentActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra("UID", card!!.uid) +// intent.putExtra("Card", card!!.asBundle) intent.putExtra("Wallet", etWallet!!.text.toString()) intent.putExtra(SignPaymentActivity.EXTRA_AMOUNT, etAmount.text.toString()) intent.putExtra("Fee", etFee.text.toString()) @@ -393,14 +394,15 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { } } + // TODO - move to BtcEngine @Throws(Exception::class) internal fun buildSize(outputAddress: String, outFee: String, outAmount: String): Int { - val myAddress = card!!.wallet - val pbKey = card!!.walletPublicKey - val pbComprKey = card!!.walletPublicKeyRar + val myAddress = ctx.card!!.wallet + val pbKey = ctx.card!!.walletPublicKey + val pbComprKey = ctx.card!!.walletPublicKeyRar // build script for our address - val rawTxList = card!!.unspentTransactions + val rawTxList = (ctx.coinData!! as BtcData).unspentTransactions val outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes // collect unspent @@ -466,7 +468,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { private fun requestInfura(method: String) { if (UtilHelper.isOnline(this)) { - serverApiHelper.infura(method, 67, card!!.wallet, "", "") + serverApiHelper.infura(method, 67, ctx.card!!.wallet, "", "") } else finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain)) } diff --git a/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.kt b/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.kt index 38bb69401e..262a5b5fa1 100644 --- a/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.kt @@ -16,6 +16,7 @@ import com.tangem.data.nfc.CreateNewWalletTask import com.tangem.domain.cardReader.CardProtocol import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog import com.tangem.presentation.dialog.WaitSecurityDelayDialog import com.tangem.util.Util @@ -30,7 +31,7 @@ class CreateNewWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, const val RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER } - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var nfcManager: NfcManager? = null private var createNewWalletTask: CreateNewWalletTask? = null @@ -46,10 +47,9 @@ class CreateNewWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx = TangemContext.loadFromBundle(this, intent.extras) - tvCardId.text = card!!.cidDescription + tvCardId.text = ctx.card!!.cidDescription progressBar = findViewById(R.id.progressBar) progressBar!!.progressTintList = ColorStateList.valueOf(Color.DKGRAY) @@ -65,13 +65,13 @@ class CreateNewWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, val sUID = Util.byteArrayToHexString(uid) // Log.v(TAG, "UID: " + sUID); - if (sUID == card!!.uid) { + if (sUID == ctx.card!!.uid) { if (lastReadSuccess) { - isoDep.timeout = card!!.pauseBeforePIN2 + 5000 + isoDep.timeout = ctx.card!!.pauseBeforePIN2 + 5000 } else { - isoDep.timeout = card!!.pauseBeforePIN2 + 65000 + isoDep.timeout = ctx.card!!.pauseBeforePIN2 + 65000 } - createNewWalletTask = CreateNewWalletTask(this, card, nfcManager, isoDep, this) + createNewWalletTask = CreateNewWalletTask(this, ctx.card, nfcManager, isoDep, this) createNewWalletTask!!.start() } else { // Log.d(TAG, "Mismatch card UID (" + sUID + " instead of " + mCard.getUID() + ")"); diff --git a/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.kt b/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.kt index 292517e750..9827abea2a 100644 --- a/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.kt @@ -16,6 +16,7 @@ import com.tangem.data.nfc.VerifyCardTask import com.tangem.domain.cardReader.CardProtocol import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog import com.tangem.presentation.dialog.WaitSecurityDelayDialog import com.tangem.util.Util @@ -33,7 +34,7 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card } private var nfcManager: NfcManager? = null - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var lastReadSuccess = true private var verifyCardTask: VerifyCardTask? = null private var requestPIN2Count = 0 @@ -46,21 +47,20 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx = TangemContext.loadFromBundle(this, intent.extras) - tvIssuer.text = card!!.issuerDescription - //tvBlockchain.text = card!!.blockchainName - if (card!!.tokenSymbol.length > 1) { - val html = Html.fromHtml(card!!.blockchainName) + tvIssuer.text = ctx.card!!.issuerDescription + //tvBlockchain.text = ctx.card!!.blockchainName + if (ctx.card!!.tokenSymbol.length > 1) { + val html = Html.fromHtml(ctx.card!!.blockchainName) tvBlockchain.text = html } else - tvBlockchain.text = card!!.blockchainName + tvBlockchain.text = ctx.card!!.blockchainName - tvCardID.text = card!!.cidDescription - imgBlockchain.setImageResource(card!!.blockchain.getImageResource(this, card!!.tokenSymbol)) + tvCardID.text = ctx.card!!.cidDescription + imgBlockchain.setImageResource(ctx.card!!.blockchain.getImageResource(this, ctx.card!!.tokenSymbol)) - if (card!!.useDefaultPIN1()!!) { + if (ctx.card!!.useDefaultPIN1()!!) { imgPIN.setImageResource(R.drawable.unlock_pin1) imgPIN.setOnClickListener { Toast.makeText(this@EmptyWalletActivity, R.string.this_banknote_protected_default_PIN1_code, Toast.LENGTH_LONG).show() } } else { @@ -68,11 +68,11 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card imgPIN.setOnClickListener { Toast.makeText(this@EmptyWalletActivity, R.string.this_banknote_protected_user_PIN1_code, Toast.LENGTH_LONG).show() } } - if (card!!.pauseBeforePIN2 > 0 && (card!!.useDefaultPIN2()!! || !card!!.useSmartSecurityDelay())) { + if (ctx.card!!.pauseBeforePIN2 > 0 && (ctx.card!!.useDefaultPIN2()!! || !ctx.card!!.useSmartSecurityDelay())) { imgPIN2orSecurityDelay.setImageResource(R.drawable.timer) - imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(this@EmptyWalletActivity, String.format(getString(R.string.this_banknote_will_enforce), card!!.pauseBeforePIN2 / 1000.0), Toast.LENGTH_LONG).show() } + imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(this@EmptyWalletActivity, String.format(getString(R.string.this_banknote_will_enforce), ctx.card!!.pauseBeforePIN2 / 1000.0), Toast.LENGTH_LONG).show() } - } else if (card!!.useDefaultPIN2()!!) { + } else if (ctx.card!!.useDefaultPIN2()!!) { imgPIN2orSecurityDelay.setImageResource(R.drawable.unlock_pin2) imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(this@EmptyWalletActivity, R.string.this_banknote_protected_default_PIN2_code, Toast.LENGTH_LONG).show() } } else { @@ -80,7 +80,7 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(this@EmptyWalletActivity, R.string.this_banknote_protected_user_PIN2_code, Toast.LENGTH_LONG).show() } } - if (card!!.useDevelopersFirmware()!!) { + if (ctx.card!!.useDevelopersFirmware()!!) { imgDeveloperVersion.setImageResource(R.drawable.ic_developer_version) imgDeveloperVersion.visibility = View.VISIBLE imgDeveloperVersion.setOnClickListener { Toast.makeText(this@EmptyWalletActivity, R.string.unlocked_banknote_only_development_use, Toast.LENGTH_LONG).show() } @@ -92,8 +92,8 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card requestPIN2Count = 0 val intent = Intent(baseContext, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + intent.putExtra("UID", ctx.card!!.uid) + intent.putExtra("Card", ctx.card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2) } } @@ -127,14 +127,14 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card if (data != null && data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) { val updatedCard = TangemCard(data.getStringExtra("UID")) updatedCard.loadFromBundle(data.getBundleExtra("Card")) - card = updatedCard + ctx.card = updatedCard } if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { requestPIN2Count++ val intent = Intent(baseContext, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + intent.putExtra("UID", ctx.card!!.uid) + intent.putExtra("Card", ctx.card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2) return } @@ -154,7 +154,7 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card ?: throw CardProtocol.TangemException(getString(R.string.wrong_tag_err)) val uid = tag.id val sUID = Util.byteArrayToHexString(uid) - if (card!!.uid != sUID) { + if (ctx.card!!.uid != sUID) { // Log.d(TAG, "Invalid UID: " + sUID); nfcManager!!.ignoreTag(isoDep.tag) return @@ -168,7 +168,7 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card isoDep.timeout = 65000 } //lastTag = tag; - verifyCardTask = VerifyCardTask(this, card, nfcManager, isoDep, this) + verifyCardTask = VerifyCardTask(this, ctx.card, nfcManager, isoDep, this) verifyCardTask!!.start() } catch (e: Exception) { e.printStackTrace() @@ -254,8 +254,8 @@ class EmptyWalletActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card private fun doCreateNewWallet() { val intent = Intent(this, CreateNewWalletActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + intent.putExtra("UID", ctx.card!!.uid) + intent.putExtra("Card", ctx.card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_CREATE_NEW_WALLET_ACTIVITY) } diff --git a/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt b/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt index b249e75d1a..9164b0bd32 100644 --- a/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/MainActivity.kt @@ -306,6 +306,7 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco rlProgressBar.post { rlProgressBar.visibility = View.GONE + // TODO - ??? remove save and load??? val cardInfo = Bundle() cardInfo.putString("UID", cardProtocol.card.uid) val bCard = Bundle() diff --git a/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitOtherAPIWithdrawalActivity.kt b/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitOtherAPIWithdrawalActivity.kt index da2d6b7aaf..ff58b3a8ee 100644 --- a/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitOtherAPIWithdrawalActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitOtherAPIWithdrawalActivity.kt @@ -8,6 +8,7 @@ import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Bundle import android.support.v7.app.AppCompatActivity +import android.text.Html import android.text.InputFilter import android.view.View import com.tangem.data.network.Cryptonit_OtherAPI @@ -15,6 +16,7 @@ import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.Blockchain import com.tangem.domain.wallet.CoinEngineFactory import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.util.DecimalDigitsInputFilter import com.tangem.wallet.R import kotlinx.android.synthetic.main.activity_prepare_cryptonit_other_api_withdrawal.* @@ -30,7 +32,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt private const val REQUEST_CODE_SCAN_QR_USER_ID = 3 } - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var nfcManager: NfcManager? = null private var cryptonit: Cryptonit_OtherAPI? = null @@ -44,8 +46,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx = TangemContext.loadFromBundle(this, intent.extras) cryptonit = Cryptonit_OtherAPI(this) @@ -53,33 +54,14 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt tvUserID.text = cryptonit!!.userId tvSecret.text = cryptonit!!.secretDescription - tvCardID.text = card!!.cidDescription - tvWallet.text = card!!.wallet - val engine = CoinEngineFactory.create(card!!.blockchain) + tvCardID.text = ctx.card!!.cidDescription + tvWallet.text = ctx.card!!.wallet + val engine = CoinEngineFactory.create(ctx) - when (card!!.blockchain) { - Blockchain.Ethereum, Blockchain.EthereumTestNet -> { - tvCurrency.text = engine.getBalanceCurrency(card) - } - Blockchain.Bitcoin, Blockchain.BitcoinTestNet, Blockchain.BitcoinCash, Blockchain.BitcoinCashTestNet -> { - tvCurrency.text = card!!.blockchain.currency - } - else -> { - tvCurrency.text = engine.getBalanceCurrency(card) - } - } + tvCurrency.text = Html.fromHtml(engine.balanceCurrencyHTML) - etAmount.setText(engine.convertByteArrayToAmount(card!!, card!!.denomination)) - when (card!!.blockchain) { - Blockchain.Bitcoin -> - etAmount.filters = arrayOf(DecimalDigitsInputFilter(5)) - Blockchain.BitcoinCash -> - etAmount.filters = arrayOf(DecimalDigitsInputFilter(8)) - Blockchain.Ethereum -> - etAmount.filters = arrayOf(DecimalDigitsInputFilter(18)) - else -> { - } - } + etAmount.setText(engine.convertToAmount(engine.convertToInternalAmount(ctx.card!!.denomination)).toString()) + etAmount.filters=engine.amountInputFilters // set listeners btnLoad.setOnClickListener { @@ -93,7 +75,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt rlProgressBar.visibility = View.VISIBLE tvProgressDescription.text = getString(R.string.cryptonit_request_withdrawal) - cryptonit!!.requestCryptoWithdrawal(card!!.blockchain.currency, dblAmount.toString(), card!!.wallet) + cryptonit!!.requestCryptoWithdrawal(ctx.blockchain.currency, dblAmount.toString(), ctx.card!!.wallet) } catch (e: Exception) { etAmount.error = getString(R.string.unknown_amount_format) } @@ -122,7 +104,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt ivRefreshBalance.setOnClickListener { doRequestBalance() } cryptonit!!.setBalanceListener { response -> - when (card!!.blockchain) { + when (ctx.blockchain) { Blockchain.Ethereum, Blockchain.EthereumTestNet -> { tvBalance.text = response.eth_available } @@ -133,7 +115,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt } } - tvBalanceCurrency.text = card!!.blockchain.currency + tvBalanceCurrency.text = ctx.blockchain.currency tvBalance.setTextColor(Color.BLACK) rlProgressBar.visibility = View.INVISIBLE btnLoad.isActivated = true @@ -161,7 +143,7 @@ class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapt rlProgressBar.visibility = View.VISIBLE tvProgressDescription.text = getString(R.string.cryptonit_request_balance) tvError.visibility = View.INVISIBLE - cryptonit!!.requestBalance(card!!.blockchain.currency, "USD") + cryptonit!!.requestBalance(ctx.blockchain.currency, "USD") } else { tvError.visibility = View.VISIBLE tvError.text = getString(R.string.cryptonit_not_enough_account_data) diff --git a/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitWithdrawalActivity.kt b/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitWithdrawalActivity.kt index def2b6ba31..bf8201f324 100644 --- a/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitWithdrawalActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/PrepareCryptonitWithdrawalActivity.kt @@ -7,6 +7,7 @@ import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Bundle import android.support.v7.app.AppCompatActivity +import android.text.Html import android.text.InputFilter import android.view.View import android.view.inputmethod.EditorInfo @@ -17,6 +18,7 @@ import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.Blockchain import com.tangem.domain.wallet.CoinEngineFactory import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.util.DecimalDigitsInputFilter import com.tangem.wallet.R import kotlinx.android.synthetic.main.activity_prepare_cryptonit_withdrawal.* @@ -29,7 +31,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade val TAG: String = PrepareCryptonitWithdrawalActivity::class.java.simpleName } - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var nfcManager: NfcManager? = null private var cryptonit: Cryptonit? = null @@ -43,8 +45,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx = TangemContext.loadFromBundle(this, intent.extras) cryptonit = Cryptonit(this) @@ -52,24 +53,16 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade etPassword.setText(cryptonit!!.password) etFee.setText(cryptonit!!.fee) - tvCardID.text = card!!.cidDescription - tvWallet.text = card!!.wallet - val engine = CoinEngineFactory.create(card!!.blockchain) + tvCardID.text = ctx.card!!.cidDescription + tvWallet.text = ctx.card!!.wallet + val engine = CoinEngineFactory.create(ctx) - when (card!!.blockchain) { - Blockchain.Ethereum -> { - tvCurrency.text = engine.getBalanceCurrency(card) - } - Blockchain.Bitcoin, Blockchain.BitcoinCash -> { - tvCurrency.text = card!!.blockchain.currency - } - else -> { - tvCurrency.text = engine.getBalanceCurrency(card) - } - } + tvCurrency.text = Html.fromHtml(engine.balanceCurrencyHTML) tvFeeCurrency.text = tvCurrency.text - etAmount.setText(engine.convertByteArrayToAmount(card!!, card!!.denomination)) + etAmount.setText(engine.convertToAmount(engine.convertToInternalAmount(ctx.card!!.denomination)).toString()) + etAmount.filters=engine.amountInputFilters + etAmount.setOnEditorActionListener { lv, actionId, event -> if (actionId == EditorInfo.IME_ACTION_DONE) { val imm = lv.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager @@ -79,7 +72,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade false } } - when (card!!.blockchain) { + when (ctx.blockchain) { Blockchain.Bitcoin -> { etAmount.filters = arrayOf(DecimalDigitsInputFilter(5)) etFee.filters = arrayOf(DecimalDigitsInputFilter(5)) @@ -109,7 +102,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade rlProgressBar.visibility = View.VISIBLE tvProgressDescription.text = getString(R.string.cryptonit_request_withdrawal) - cryptonit!!.requestWithdrawCoins(card!!.blockchain.currency, dblAmount, card!!.wallet) + cryptonit!!.requestWithdrawCoins(ctx.blockchain.currency, dblAmount, ctx.card!!.wallet) } catch (e: Exception) { etAmount.error = getString(R.string.unknown_amount_format) } @@ -154,7 +147,7 @@ class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.Reade rlProgressBar.visibility = View.VISIBLE tvProgressDescription.text = getString(R.string.cryptonit_request_balance) tvError.visibility = View.INVISIBLE - cryptonit!!.requestBalance(card!!.blockchain.currency) + cryptonit!!.requestBalance(ctx.card!!.blockchain.currency) } else { tvError.visibility = View.VISIBLE tvError.text = getString(R.string.cryptonit_not_enough_account_data) diff --git a/app/src/main/java/com/tangem/presentation/activity/PrepareKrakenWithdrawalActivity.kt b/app/src/main/java/com/tangem/presentation/activity/PrepareKrakenWithdrawalActivity.kt index 3928c1196a..329489ba25 100644 --- a/app/src/main/java/com/tangem/presentation/activity/PrepareKrakenWithdrawalActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/PrepareKrakenWithdrawalActivity.kt @@ -11,6 +11,7 @@ import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Bundle import android.support.v7.app.AppCompatActivity +import android.text.Html import android.text.InputFilter import android.view.View import android.view.inputmethod.EditorInfo @@ -21,6 +22,7 @@ import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.Blockchain import com.tangem.domain.wallet.CoinEngineFactory import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.util.DecimalDigitsInputFilter import com.tangem.wallet.R import kotlinx.android.synthetic.main.activity_prepare_kraken_withdrawal.* @@ -37,7 +39,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa private const val REQUEST_CODE_SCAN_QR = 1 } - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var nfcManager: NfcManager? = null private var kraken: Kraken? = null private var fee: BigDecimal? = null @@ -51,42 +53,21 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx = TangemContext.loadFromBundle(this, intent.extras) kraken = Kraken(this) tvKey.text = kraken!!.key tvSecret.text = kraken!!.secretDescription - tvCardID.text = card!!.cidDescription - tvWallet.text = card!!.wallet - val engine = CoinEngineFactory.create(card!!.blockchain) + tvCardID.text = ctx.card!!.cidDescription + tvWallet.text = ctx.card!!.wallet + val engine = CoinEngineFactory.create(ctx) - when (card!!.blockchain) { - Blockchain.Ethereum, Blockchain.EthereumTestNet -> { - tvCurrency.text = engine.getBalanceCurrency(card) + tvCurrency.text = Html.fromHtml(engine.balanceCurrencyHTML) - } - Blockchain.Bitcoin, Blockchain.BitcoinTestNet, Blockchain.BitcoinCash, Blockchain.BitcoinCashTestNet -> { - tvCurrency.text = card!!.blockchain.currency - } - else -> { - tvCurrency.text = engine.getBalanceCurrency(card) - } - } - - etAmount.setText(engine.convertByteArrayToAmount(card!!, card!!.denomination)) - when (card!!.blockchain) { - Blockchain.Bitcoin -> - etAmount.filters = arrayOf(DecimalDigitsInputFilter(5)) - Blockchain.BitcoinCash -> - etAmount.filters = arrayOf(DecimalDigitsInputFilter(8)) - Blockchain.Ethereum -> - etAmount.filters = arrayOf(DecimalDigitsInputFilter(18)) - else -> { - } - } + etAmount.setText(engine.convertToAmount(engine.convertToInternalAmount(ctx.card!!.denomination)).toString()) + etAmount.filters=engine.amountInputFilters etAmount.setOnEditorActionListener { lv, actionId, event -> if (actionId == EditorInfo.IME_ACTION_DONE) { @@ -108,7 +89,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa rlProgressBar.visibility = View.VISIBLE tvProgressDescription.text = getString(R.string.kraken_request_withdrawal) - kraken!!.requestWithdrawInfo(card!!.blockchain.currency, dblAmount.toString(), card!!.wallet) + kraken!!.requestWithdrawInfo(ctx.blockchain.currency, dblAmount.toString(), ctx.card!!.wallet) } catch (e: Exception) { etAmount.error = getString(R.string.unknown_amount_format) } @@ -126,7 +107,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa tvError.visibility = View.VISIBLE tvError.text = Arrays.toString(response.error) } else { - when (card!!.blockchain) { + when (ctx.blockchain) { Blockchain.Ethereum -> { tvBalance.text = response.result.XETH.trimEnd('0') } @@ -140,7 +121,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa tvBalance.text = "???" } } - tvBalanceCurrency.text = card!!.blockchain.currency + tvBalanceCurrency.text = ctx.blockchain.currency tvBalance.setTextColor(Color.BLACK) btnLoad.visibility = View.VISIBLE } @@ -190,7 +171,7 @@ class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCa builder.setTitle("Please confirm withdraw") // Set a message for alert dialog - builder.setMessage(String.format("Continue with fee %s %s?", fee!!.toString().trimEnd('0'), card!!.blockchain.currency)) + builder.setMessage(String.format("Continue with fee %s %s?", fee!!.toString().trimEnd('0'), ctx.blockchain.currency)) // On click listener for dialog buttons val dialogClickListener = DialogInterface.OnClickListener { _, which -> @@ -207,7 +188,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(card!!.blockchain.currency, dblAmount.toString(), card!!.wallet) + kraken!!.requestWithdraw(ctx.blockchain.currency, dblAmount.toString(), ctx.card!!.wallet) } catch (e: Exception) { etAmount.error = getString(R.string.unknown_amount_format) } diff --git a/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.kt b/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.kt index 2a2603331e..8ebddcfd2b 100644 --- a/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.kt @@ -17,6 +17,7 @@ import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.Blockchain import com.tangem.domain.wallet.CoinEngineFactory import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.util.DecimalDigitsInputFilter import com.tangem.util.FormatUtil import com.tangem.wallet.R @@ -32,8 +33,7 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { private const val REQUEST_CODE_SEND_PAYMENT = 2 } - private var useCurrency: Boolean = false - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var nfcManager: NfcManager? = null @SuppressLint("SetTextI18n") @@ -45,59 +45,29 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx= TangemContext.loadFromBundle(this, intent.extras) - tvCardID.text = card!!.cidDescription - val engine = CoinEngineFactory.create(card!!.blockchain) + tvCardID.text = ctx.card!!.cidDescription + val engine = CoinEngineFactory.create(ctx) - if (card!!.blockchain == Blockchain.Token) { - val html = Html.fromHtml(engine!!.getBalanceWithAlter(card)) - tvBalance.text = html + val html = Html.fromHtml(engine!!.balanceHTML) + tvBalance.text = html + + //TODO - to engine + if (ctx.card!!.blockchain == Blockchain.Token) { rgIncFee!!.visibility = View.INVISIBLE } else { - tvBalance.text = engine!!.getBalanceWithAlter(card) rgIncFee!!.visibility = View.VISIBLE } - if (card!!.remainingSignatures < 2) + if (ctx.card!!.remainingSignatures < 2) etAmount.isEnabled = false - // Ethereum EthereumTestNet - if (card!!.blockchain == Blockchain.Ethereum || card!!.blockchain == Blockchain.EthereumTestNet) { - tvCurrency.text = engine.getBalanceCurrency(card) - useCurrency = false - etAmount.setText(engine.getBalanceValue(card)) - } - - // Bitcoin BitcoinTestNet - else if (card!!.blockchain == Blockchain.Bitcoin || card!!.blockchain == Blockchain.BitcoinTestNet) { - val balance = engine.getBalanceLong(card)!! / (card!!.blockchain.multiplier) - tvCurrency.text = card!!.blockchain.currency - useCurrency = true - val output = FormatUtil.DoubleToString(balance) - etAmount.setText(output) - } - - // BitcoinCash BitcoinCashTestNet - else if (card!!.blockchain == Blockchain.BitcoinCash || card!!.blockchain == Blockchain.BitcoinCashTestNet) { - val balance = engine.getBalanceLong(card)!! / (card!!.blockchain.multiplier) - tvCurrency.text = card!!.blockchain.currency - useCurrency = true - val output = FormatUtil.DoubleToString(balance) - } else { - tvCurrency.text = engine.getBalanceCurrency(card) - useCurrency = false - etAmount.setText(engine.getBalanceValue(card)) - } + tvCurrency.text = engine.balance.currency + etAmount.setText(engine.balance.stringToEdit) // limit number of symbols after comma - if (card!!.blockchain == Blockchain.Bitcoin) - etAmount.filters = arrayOf(DecimalDigitsInputFilter(8)) - if (card!!.blockchain == Blockchain.BitcoinCash) - etAmount.filters = arrayOf(DecimalDigitsInputFilter(8)) - if (card!!.blockchain == Blockchain.Ethereum) - etAmount.filters = arrayOf(DecimalDigitsInputFilter(18)) + etAmount.filters = engine.amountInputFilters // set listeners etAmount.setOnEditorActionListener { lv, actionId, event -> @@ -111,12 +81,14 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { } } btnVerify.setOnClickListener { - val strAmount: String = etAmount.text.toString().replace(",", ".") - val engine1 = CoinEngineFactory.create(card!!.blockchain) + val engine1 = CoinEngineFactory.create(ctx.card!!.blockchain) + + val strAmount: String = etAmount.text.toString().replace(",", ".") + val amount=engine1.convertToAmount(etAmount.text.toString()) try { - if (!engine.checkAmount(card, etAmount.text.toString())) + if (!engine.checkNewTransactionAmount(amount)) etAmount.error = getString(R.string.not_enough_funds_on_your_card) } catch (e: Exception) { etAmount.error = getString(R.string.unknown_amount_format) @@ -124,7 +96,7 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { var checkAddress = false if (engine1 != null) - checkAddress = engine1.validateAddress(etWallet.text.toString(), card) + checkAddress = engine1.validateAddress(etWallet.text.toString()) // check wallet address if (!checkAddress) { @@ -132,20 +104,20 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { return@setOnClickListener } - if (etWallet.text.toString() == card!!.wallet) { + if (etWallet.text.toString() == ctx.card!!.wallet) { etWallet.error = getString(R.string.destination_wallet_address_equal_source_address) return@setOnClickListener } // check enough funds - if (etAmount.text.toString().replace(",", ".").toDouble() > engine.getBalanceValue(card).replace(",", ".").toDouble()) { - etAmount.error = getString(R.string.not_enough_funds_on_your_card) - return@setOnClickListener - } + // TODO - double with engin.checkAmount +// if (etAmount.text.toString().replace(",", ".").toDouble() > engine.getBalanceValue(card).replace(",", ".").toDouble()) { +// etAmount.error = getString(R.string.not_enough_funds_on_your_card) +// return@setOnClickListener +// } val intent = Intent(baseContext, ConfirmPaymentActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) intent.putExtra("Wallet", etWallet!!.text.toString()) intent.putExtra("IncFee", (rgIncFee!!.checkedRadioButtonId == R.id.rbFeeIn)) intent.putExtra(SignPaymentActivity.EXTRA_AMOUNT, strAmount) @@ -176,7 +148,7 @@ class PreparePaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_SCAN_QR && resultCode == Activity.RESULT_OK && data != null && data.extras!!.containsKey("QRCode")) { var code = data.getStringExtra("QRCode") - when (card!!.blockchain) { + when (ctx.card!!.blockchain) { Blockchain.Bitcoin -> { if (code.contains("bitcoin:")) { val tmp = code.split("bitcoin:".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() diff --git a/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.kt b/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.kt index 841c1e6959..63493ba6b9 100644 --- a/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.kt @@ -16,6 +16,7 @@ import com.tangem.data.nfc.PurgeTask import com.tangem.domain.cardReader.CardProtocol import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog import com.tangem.presentation.dialog.WaitSecurityDelayDialog import com.tangem.util.Util @@ -29,7 +30,7 @@ class PurgeActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoc const val RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER } - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var nfcManager: NfcManager? = null private var purgeTask: PurgeTask? = null @@ -43,10 +44,9 @@ class PurgeActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoc MainActivity.commonInit(applicationContext) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx = TangemContext.loadFromBundle(this, intent.extras) - tvCardID.text = card!!.cidDescription + tvCardID.text = ctx.card!!.cidDescription progressBar.progressTintList = ColorStateList.valueOf(Color.DKGRAY) progressBar.visibility = View.INVISIBLE } @@ -82,9 +82,9 @@ class PurgeActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoc val sUID = Util.byteArrayToHexString(uid) // Log.v(TAG, "UID: $sUID") - if (sUID == card!!.uid) { - isoDep.timeout = card!!.pauseBeforePIN2 + 65000 - purgeTask = PurgeTask(this, card, nfcManager, isoDep, this) + if (sUID == ctx.card!!.uid) { + isoDep.timeout = ctx.card!!.pauseBeforePIN2 + 65000 + purgeTask = PurgeTask(this, ctx.card, nfcManager, isoDep, this) purgeTask!!.start() } else { // this Log.d(TAG, "Mismatch card UID (" + sUID + " instead of " + card.getUID() + ")"); diff --git a/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.kt b/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.kt index 35dfcbfe9a..7d61bc589b 100644 --- a/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.kt @@ -12,9 +12,7 @@ import com.tangem.data.network.ServerApiHelper import com.tangem.data.network.ServerApiHelperElectrum import com.tangem.data.network.model.InfuraResponse import com.tangem.domain.cardReader.NfcManager -import com.tangem.domain.wallet.Blockchain -import com.tangem.domain.wallet.CoinEngineFactory -import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.* import com.tangem.util.UtilHelper import com.tangem.wallet.R import org.json.JSONException @@ -30,7 +28,7 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { private var serverApiHelper: ServerApiHelper = ServerApiHelper() private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum() - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var tx: String? = null private var nfcManager: NfcManager? = null @@ -42,19 +40,18 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { nfcManager = NfcManager(this, this) - val intent = intent - card = TangemCard(getIntent().getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + + ctx=TangemContext.loadFromBundle(this, intent.extras) tx = intent.getStringExtra(EXTRA_TX) - val engine = CoinEngineFactory.create(card!!.blockchain) + val engine = CoinEngineFactory.create(ctx) - if (card!!.blockchain == Blockchain.Ethereum || card!!.blockchain == Blockchain.EthereumTestNet || card!!.blockchain == Blockchain.Token) + if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet || ctx.blockchain == Blockchain.Token) requestInfura(ServerApiHelper.INFURA_ETH_SEND_RAW_TRANSACTION, "") - else if (card!!.blockchain == Blockchain.Bitcoin || card!!.blockchain == Blockchain.BitcoinTestNet) - requestElectrum(card!!, ElectrumRequest.broadcast(card!!.wallet, tx)) - else if (card!!.blockchain == Blockchain.BitcoinCash || card!!.blockchain == Blockchain.BitcoinCashTestNet) - requestElectrum(card!!, ElectrumRequest.broadcast(card!!.wallet, tx)) + 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 || ctx.blockchain == Blockchain.BitcoinCashTestNet) + requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.card!!.wallet, tx)) // request electrum listener val electrumBodyListener: ServerApiHelperElectrum.ElectrumRequestDataListener = object : ServerApiHelperElectrum.ElectrumRequestDataListener { @@ -69,11 +66,11 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { finishWithSuccess() } catch (e: Exception) { e.printStackTrace() - requestElectrum(card!!, ElectrumRequest.broadcast(card!!.wallet, tx)) + requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.card!!.wallet, tx)) } } catch (e: JSONException) { e.printStackTrace() - requestElectrum(card!!, ElectrumRequest.broadcast(card!!.wallet, tx)) + requestElectrum(ctx.card!!, ElectrumRequest.broadcast(ctx.card!!.wallet, tx)) } } } @@ -104,9 +101,9 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { hashTX = hashTX.substring(2) } - val nonce = card!!.confirmedTXCount + val nonce = (ctx.coinData!! as EthData).confirmedTXCount nonce.add(BigInteger.valueOf(1)) - card!!.confirmedTXCount = nonce + (ctx.coinData!! as EthData).confirmedTXCount = nonce finishWithSuccess() } catch (e: Exception) { @@ -163,7 +160,7 @@ class SendTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { private fun requestInfura(method: String, contract: String) { if (UtilHelper.isOnline(this)) { - serverApiHelper.infura(method, 67, card!!.wallet, contract, tx) + serverApiHelper.infura(method, 67, ctx.card!!.wallet, contract, tx) } else finishWithError(getString(R.string.no_connection)) } diff --git a/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt b/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt index f29b6063b6..7916cd31c6 100644 --- a/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt +++ b/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.kt @@ -17,6 +17,7 @@ import com.tangem.data.nfc.SignPaymentTask import com.tangem.domain.cardReader.CardProtocol import com.tangem.domain.cardReader.NfcManager import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.TangemContext import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog import com.tangem.presentation.dialog.WaitSecurityDelayDialog import com.tangem.util.Util @@ -36,7 +37,7 @@ class SignPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card } private var nfcManager: NfcManager? = null - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var signPaymentTask: SignPaymentTask? = null @@ -56,15 +57,14 @@ class SignPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card nfcManager = NfcManager(this, this) - card = TangemCard(intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(intent.extras!!.getBundle(TangemCard.EXTRA_CARD)) + ctx=TangemContext.loadFromBundle(this, intent.extras) amountStr = intent.getStringExtra(EXTRA_AMOUNT) feeStr = intent.getStringExtra("Fee") isIncludeFee = intent.getBooleanExtra("IncFee", true) outAddressStr = intent.getStringExtra("Wallet") - tvCardID.text = card!!.cidDescription + tvCardID.text = ctx.card!!.cidDescription progressBar = findViewById(R.id.progressBar) progressBar!!.progressTintList = ColorStateList.valueOf(Color.DKGRAY) @@ -121,13 +121,13 @@ class SignPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Card val sUID = Util.byteArrayToHexString(uid) // Log.v(TAG, "UID: $sUID") - if (sUID == card!!.uid) { + if (sUID == ctx.card!!.uid) { if (lastReadSuccess) { - isoDep.timeout = card!!.pauseBeforePIN2 + 5000 + isoDep.timeout = ctx.card!!.pauseBeforePIN2 + 5000 } else { - isoDep.timeout = card!!.pauseBeforePIN2 + 65000 + isoDep.timeout = ctx.card!!.pauseBeforePIN2 + 65000 } - signPaymentTask = SignPaymentTask(this, card, nfcManager, isoDep, this, amountStr, feeStr, isIncludeFee, outAddressStr) + signPaymentTask = SignPaymentTask(this, ctx, nfcManager, isoDep, this, amountStr, feeStr, isIncludeFee, outAddressStr) signPaymentTask!!.start() } else { // Log.d(TAG, "Mismatch card UID (" + sUID + " instead of " + card!!.uid + ")") diff --git a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt index 29808b59d9..1395b7f021 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt +++ b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt @@ -62,7 +62,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific private var serverApiHelperElectrum: ServerApiHelperElectrum = ServerApiHelperElectrum() private var singleToast: Toast? = null - private var card: TangemCard? = null + //private var card: TangemCard? = null + //private var engine: CoinEngine? = null + private lateinit var ctx: TangemContext + private var lastTag: Tag? = null private var lastReadSuccess = true private var verifyCardTask: VerifyCardTask? = null @@ -81,8 +84,12 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific super.onCreate(savedInstanceState) nfcManager = NfcManager(activity, this) - card = TangemCard(activity.intent.getStringExtra(TangemCard.EXTRA_UID)) - card!!.loadFromBundle(activity.intent.extras.getBundle(TangemCard.EXTRA_CARD)) + 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) @@ -96,13 +103,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - if (card!!.blockchain == Blockchain.Token) + if (ctx.blockchain == Blockchain.Token) tvBalance.setSingleLine(false) - ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!)) - - val engine = CoinEngineFactory.create(card!!.blockchain) - val visibleFlag = engine?.inOutPutVisible() ?: true + ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(ctx.card!!)) btnExtract.isEnabled = false btnExtract.backgroundTintList = inactiveColor @@ -111,13 +115,13 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific startVerify(lastTag) - tvWallet.text = card!!.wallet + tvWallet.text = ctx.card!!.wallet // set listeners srl!!.setOnRefreshListener { refresh() } btnLookup.setOnClickListener { - val engineClick = CoinEngineFactory.create(card!!.blockchain) - val browserIntent = Intent(Intent.ACTION_VIEW, engineClick.getShareWalletUriExplorer(card)) + val engine=CoinEngineFactory.create(ctx) + val browserIntent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUriExplorer) startActivity(browserIntent) } btnCopy.setOnClickListener { doShareWallet(false) } @@ -132,7 +136,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific when (items[which]) { getString(R.string.in_app) -> { try { - val intent = Intent(Intent.ACTION_VIEW, CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card)) + val engine=CoinEngineFactory.create(ctx) + val intent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUri) intent.addCategory(Intent.CATEGORY_DEFAULT) startActivity(intent) } catch (e: ActivityNotFoundException) { @@ -143,24 +148,27 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific doShareWallet(true) } getString(R.string.load_via_qr) -> { - ShowQRCodeDialog.show(activity, engine.getShareWalletUri(card).toString()) + val engine=CoinEngineFactory.create(ctx) + ShowQRCodeDialog.show(activity, engine!!.shareWalletUri.toString()) } // getString(R.string.via_cryptonit2) -> { -// val intent = Intent(context, 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) // } getString(R.string.via_cryptonit) -> { val intent = Intent(activity, PrepareCryptonitWithdrawalActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra("UID", card!!.uid) +// intent.putExtra("Card", card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT) } getString(R.string.via_kraken) -> { val intent = Intent(activity, PrepareKrakenWithdrawalActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra("UID", card!!.uid) +// intent.putExtra("Card", card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT) } else -> { @@ -173,7 +181,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific dlg.window.attributes = wlp } else { try { - val intent = Intent(Intent.ACTION_VIEW, CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card)) + val engine=CoinEngineFactory.create(ctx) + val intent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUri) intent.addCategory(Intent.CATEGORY_DEFAULT) startActivity(intent) } catch (e: ActivityNotFoundException) { @@ -192,23 +201,25 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific startActivity(intent) } btnExtract.setOnClickListener { + val engine=CoinEngineFactory.create(ctx) if (UtilHelper.isOnline(activity)) { - if (!card!!.hasBalanceInfo()) { + if (!engine!!.hasBalanceInfo()) { showSingleToast(R.string.cannot_obtain_data_from_blockchain) - } else if (!engine.isBalanceNotZero(card)) + } else if (!engine!!.isBalanceNotZero) showSingleToast(R.string.wallet_empty) - else if (!engine.isBalanceAlterNotZero(card)) + else if (!engine!!.isBalanceAlterNotZero) showSingleToast(R.string.not_enough_eth_for_gas) - else if (engine.awaitingConfirmation(card)) + else if (engine!!.awaitingConfirmation()) showSingleToast(R.string.please_wait_while_previous) - else if (!engine.checkUnspentTransaction(card)) + else if (!engine!!.checkUnspentTransaction()) showSingleToast(R.string.please_wait_for_confirmation) - else if (card!!.remainingSignatures == 0) + else if (ctx.card!!.remainingSignatures == 0) showSingleToast(R.string.card_has_no_remaining_signature) else { val intent = Intent(activity, PreparePaymentActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra("UID", card!!.uid) +// intent.putExtra("Card", card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_SEND_PAYMENT) } } else @@ -223,11 +234,11 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific val walletAddress = electrumRequest.params.getString(0) val confBalance = electrumRequest.result.getLong("confirmed") val unconfirmedBalance = electrumRequest.result.getLong("unconfirmed") - card!!.isBalanceReceived = true - card!!.setBalanceConfirmed(confBalance) - card!!.balanceUnconfirmed = unconfirmedBalance - card!!.decimalBalance = confBalance.toString() - card!!.validationNodeDescription = serverApiHelperElectrum.validationNodeDescription + ctx.coinData!!.isBalanceReceived = true + (ctx.coinData!! as BtcData).setBalanceConfirmed(confBalance) + (ctx.coinData!! as BtcData).balanceUnconfirmed = unconfirmedBalance + (ctx.coinData!! as BtcData).decimalBalance = confBalance.toString() + (ctx.coinData!! as BtcData).validationNodeDescription = serverApiHelperElectrum.validationNodeDescription } catch (e: JSONException) { e.printStackTrace() Log.e(TAG, "FAIL METHOD_GetBalance JSONException") @@ -239,14 +250,14 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific val walletAddress = electrumRequest.params.getString(0) val jsUnspentArray = electrumRequest.resultArray try { - card!!.unspentTransactions.clear() + (ctx.coinData!! as BtcData).unspentTransactions.clear() for (i in 0 until jsUnspentArray.length()) { val jsUnspent = jsUnspentArray.getJSONObject(i) - val trUnspent = TangemCard.UnspentTransaction() + val trUnspent = BtcData.UnspentTransaction() trUnspent.txID = jsUnspent.getString("tx_hash") trUnspent.Amount = jsUnspent.getInt("value") trUnspent.Height = jsUnspent.getInt("height") - card!!.unspentTransactions.add(trUnspent) + (ctx.coinData!! as BtcData).unspentTransactions.add(trUnspent) } } catch (e: JSONException) { e.printStackTrace() @@ -258,7 +269,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific val height = jsUnspent.getInt("height") val hash = jsUnspent.getString("tx_hash") if (height != -1) { - requestElectrum(card!!, ElectrumRequest.getTransaction(walletAddress, hash)) + requestElectrum(ElectrumRequest.getTransaction(walletAddress, hash)) } } } catch (e: JSONException) { @@ -270,7 +281,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific try { val txHash = electrumRequest.txHash val raw = electrumRequest.resultString - val listTx = card!!.unspentTransactions + val listTx = (ctx.coinData!! as BtcData).unspentTransactions for (tx in listTx) { if (tx.txID == txHash) tx.Raw = raw @@ -304,12 +315,12 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific val d = l.divide(BigInteger("1000000000000000000", 10)) val balance = d.toLong() - card!!.setBalanceConfirmed(balance) - card!!.balanceUnconfirmed = 0L - card!!.isBalanceReceived = true - if (card!!.blockchain != Blockchain.Token) - card!!.decimalBalance = l.toString(10) - card!!.decimalBalanceAlter = l.toString(10) + ctx.coinData!!.setBalanceConfirmed(balance) + ctx.coinData!!.balanceUnconfirmed = 0L + ctx.coinData!!.isBalanceReceived = true + if (ctx.coinData!!.blockchain != Blockchain.Token) + ctx.coinData!!.decimalBalance = l.toString(10) + ctx.coinData!!.decimalBalanceAlter = l.toString(10) // Log.i("$TAG eth_get_balance", balanceCap) } @@ -318,7 +329,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific var nonce = infuraResponse.result nonce = nonce.substring(2) val count = BigInteger(nonce, 16) - card!!.confirmedTXCount = count + ctx.coinData!!.confirmedTXCount = count // Log.i("$TAG eth_getTransCount", nonce) } @@ -327,7 +338,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific var pending = infuraResponse.result pending = pending.substring(2) val count = BigInteger(pending, 16) - card!!.unconfirmedTXCount = count + ctx.coinData!!.unconfirmedTXCount = count // Log.i("$TAG eth_getPendingTxCount", pending) } @@ -339,8 +350,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific val l = BigInteger(balanceCap, 16) val balance = l.toLong() if (l.compareTo(BigInteger.ZERO) == 0) { - card!!.blockchainID = Blockchain.Ethereum.id - card!!.addTokenToBlockchainName() + ctx.card!!.blockchainID = Blockchain.Ethereum.id + ctx.card!!.addTokenToBlockchainName() + + ctx.blockchain=Blockchain.Ethereum requestCounter-- if (requestCounter == 0) srl!!.isRefreshing = false @@ -350,9 +363,9 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific requestInfura(ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT, "") return } - card!!.setBalanceConfirmed(balance) - card!!.balanceUnconfirmed = 0L - card!!.decimalBalance = l.toString(10) + ctx.coinData!!.setBalanceConfirmed(balance) + ctx.coinData!!.balanceUnconfirmed = 0L + ctx.coinData!!.decimalBalance = l.toString(10) // Log.i("$TAG eth_call", balanceCap) @@ -384,9 +397,9 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific Log.e("$TAG TX_RESULT", hashTX) - val nonce = card!!.confirmedTXCount + val nonce = ctx.coinData!!.confirmedTXCount nonce.add(BigInteger.valueOf(1)) - card!!.confirmedTXCount = nonce + ctx.coinData!!.confirmedTXCount = nonce Log.e("$TAG TX_RESULT", hashTX) @@ -410,27 +423,29 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific override fun onSuccess(cardVerifyAndGetArtworkResponse: CardVerifyAndGetInfo.Response?) { val result = cardVerifyAndGetArtworkResponse?.results!![0] if (result.error != null) { - card!!.isOnlineVerified = false + ctx.card!!.isOnlineVerified = false return } - card!!.isOnlineVerified = result.passed + ctx.card!!.isOnlineVerified = result.passed if (requestCounter == 0) updateViews() if (!result.passed) return - if (localStorage.checkBatchInfoChanged(card!!, result)) { + if (localStorage.checkBatchInfoChanged(ctx.card!!, result)) { Log.w(TAG, "Batch ${result.batch} info changed to '$result'") - ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!)) - localStorage.applySubstitution(card!!) - if (card!!.blockchain == Blockchain.Token || card!!.blockchain == Blockchain.Ethereum) { - card!!.setBlockchainIDFromCard(Blockchain.Ethereum.id) + ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(ctx.card!!)) + localStorage.applySubstitution(ctx.card!!) + if (ctx.card!!.blockchain == Blockchain.Token || ctx.card!!.blockchain == Blockchain.Ethereum) { + ctx.card!!.setBlockchainIDFromCard(Blockchain.Ethereum.id) + ctx.blockchain=Blockchain.Ethereum + //engine=engine!!.swithToOtherEngine(Blockchain.Ethereum) } refresh() } 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(), card!!) + serverApiHelper.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), ctx.card!!) updateViews() } // Log.i(TAG, "setCardVerify " + it.results!![0].passed) @@ -446,7 +461,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific val artworkListener: ServerApiHelper.ArtworkListener = object : ServerApiHelper.ArtworkListener { override fun onSuccess(artworkId: String?, inputStream: InputStream?, updateDate: Date?) { localStorage.updateArtwork(artworkId!!, inputStream!!, updateDate!!) - ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!)) + ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(ctx.card!!)) } override fun onFail(message: String?) { @@ -458,8 +473,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific // request rate info listener serverApiHelper.setRateInfoData { val rate = it.priceUsd.toFloat() - card!!.rate = rate - card!!.rateAlter = rate + ctx.coinData!!.rate = rate + ctx.coinData!!.rateAlter = rate } } @@ -504,8 +519,9 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific if (data.extras != null && data.extras!!.containsKey("confirmPIN")) { val intent = Intent(activity, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) - intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) newPIN = data.getStringExtra("newPIN") startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) } else { @@ -521,8 +537,9 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific if (data.extras != null && data.extras!!.containsKey("confirmPIN2")) { val intent = Intent(activity, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) - intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) newPIN2 = data.getStringExtra("newPIN2") startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) } else { @@ -535,7 +552,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific } REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) { if (newPIN == "") - newPIN = card!!.pin + newPIN = ctx.card!!.pin if (newPIN2 == "") newPIN2 = PINStorage.getPIN2() @@ -554,8 +571,9 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific REQUEST_CODE_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) { if (data == null) { data = Intent() - data.putExtra(TangemCard.EXTRA_UID, card!!.uid) - data.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(data.extras) +// data.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// data.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) data.putExtra("modification", "delete") } else data.putExtra("modification", "update") @@ -568,33 +586,36 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific if (data != null && data.extras != null && data.extras!!.containsKey(TangemCard.EXTRA_UID) && data.extras!!.containsKey(TangemCard.EXTRA_CARD)) { val updatedCard = TangemCard(data.getStringExtra(TangemCard.EXTRA_UID)) updatedCard.loadFromBundle(data.getBundleExtra(TangemCard.EXTRA_CARD)) - card = updatedCard + ctx.card = updatedCard } if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { requestPIN2Count++ val intent = Intent(activity, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra("UID", card!!.uid) +// intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) return } else { if (data != null && data.extras!!.containsKey("message")) { - card!!.error = data.getStringExtra("message") + ctx.error = data.getStringExtra("message") } } } REQUEST_CODE_REQUEST_PIN2_FOR_PURGE -> if (resultCode == Activity.RESULT_OK) { val intent = Intent(activity, PurgeActivity::class.java) - intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) - intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_PURGE) } REQUEST_CODE_PURGE -> if (resultCode == Activity.RESULT_OK) { if (data == null) { data = Intent() - data.putExtra(TangemCard.EXTRA_UID, card!!.uid) - data.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(data.extras) +// data.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// data.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) data.putExtra("modification", "delete") } else { data.putExtra("modification", "update") @@ -607,26 +628,28 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific if (data != null && data.extras != null && data.extras!!.containsKey(TangemCard.EXTRA_UID) && data.extras!!.containsKey(TangemCard.EXTRA_CARD)) { val updatedCard = TangemCard(data.getStringExtra(TangemCard.EXTRA_UID)) updatedCard.loadFromBundle(data.getBundleExtra(TangemCard.EXTRA_CARD)) - card = updatedCard + ctx.card = updatedCard } if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { requestPIN2Count++ val intent = Intent(activity, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) - intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_PURGE) return } else { if (data != null && data.extras!!.containsKey("message")) { - card!!.error = data.getStringExtra("message") + ctx.error = data.getStringExtra("message") } } updateViews() } REQUEST_CODE_SEND_PAYMENT, REQUEST_CODE_RECEIVE_PAYMENT -> { if (resultCode == Activity.RESULT_OK) { - card!!.clearInfo() + ctx.coinData!!.clearInfo() + ctx.card.clearInfo(); srl!!.postDelayed({ this.refresh() }, 5000) srl!!.isRefreshing = true updateViews() @@ -636,13 +659,13 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific if (data.extras!!.containsKey(TangemCard.EXTRA_UID) && data.extras!!.containsKey(TangemCard.EXTRA_CARD)) { val updatedCard = TangemCard(data.getStringExtra(TangemCard.EXTRA_UID)) updatedCard.loadFromBundle(data.getBundleExtra(TangemCard.EXTRA_CARD)) - card = updatedCard + ctx.card = updatedCard } if (data.extras!!.containsKey("message")) { if (resultCode == Activity.RESULT_OK) { - card!!.message = data.getStringExtra("message") + ctx.message = data.getStringExtra("message") } else { - card!!.error = data.getStringExtra("message") + ctx.error = data.getStringExtra("message") } } updateViews() @@ -732,24 +755,22 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific timerHideErrorAndMessage = null } - if (card!!.error == null || card!!.error.isEmpty()) { + if (ctx.error == null || ctx.error.isEmpty()) { tvError.visibility = View.GONE tvError.text = "" } else { tvError.visibility = View.VISIBLE - tvError.text = card!!.error + tvError.text = ctx.error } - if (card!!.message == null || card!!.message.isEmpty()) { + if (ctx.message == null || ctx.message.isEmpty()) { tvMessage!!.text = "" tvMessage!!.visibility = View.GONE } else { - tvMessage!!.text = card!!.message + tvMessage!!.text = ctx.message tvMessage!!.visibility = View.VISIBLE } - val engine = CoinEngineFactory.create(card!!.blockchain) - if (srl!!.isRefreshing) { tvBalanceLine1.setTextColor(resources.getColor(R.color.primary)) tvBalanceLine1.text = getString(R.string.verifying_in_blockchain) @@ -758,39 +779,34 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific tvBalanceEquivalent.text = "" } else { val validator = BalanceValidator() - validator.Check(card, false) + validator.Check(ctx.card, false) tvBalanceLine1.setTextColor(ContextCompat.getColor(activity, validator.color)) tvBalanceLine1.text = validator.firstLine tvBalanceLine2.text = validator.getSecondLine(false) } - if (engine!!.hasBalanceInfo(card) || card!!.offlineBalance == null) { - if ((card!!.blockchain == Blockchain.Token) && (engine.getBalanceWithAlter(card) != null)) { - val html = Html.fromHtml(engine.getBalanceWithAlter(card)) - tvBalance.text = html - } else { -// tvBalance.text = engine.getBalanceWithAlter(card) - tvBalance.text = engine.getBalance(card) - tvBalanceEquivalent.text = engine.getBalanceEquivalent(card) - } + 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 { - val offlineAmount = engine.convertByteArrayToAmount(card, card!!.offlineBalance) - if (card!!.blockchain == Blockchain.Token) { - tvBalance.setText(R.string.not_implemented) - } else - tvBalance.text = engine.getAmountDescription(card, offlineAmount) + // TODO + val html = Html.fromHtml(engine!!.offlineBalanceHTML) + tvBalance.text = html } - tvWallet.text = card!!.wallet + tvWallet.text = ctx.card!!.wallet // tvBlockchain.text = card!!.blockchainName - if (card!!.tokenSymbol.length > 1) { - val html = Html.fromHtml(card!!.blockchainName) + if (ctx.card!!.tokenSymbol.length > 1) { + val html = Html.fromHtml(ctx.card!!.blockchainName) tvBlockchain.text = html } else - tvBlockchain.text = card!!.blockchainName + tvBlockchain.text = ctx.card!!.blockchainName - if (card!!.hasBalanceInfo()) { + if (engine!!.hasBalanceInfo()) { btnExtract.isEnabled = true btnExtract.backgroundTintList = activeColor } else { @@ -798,8 +814,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific btnExtract.backgroundTintList = inactiveColor } - card!!.error = null - card!!.message = null + ctx.error = null + ctx.message = null } catch (e: Exception) { e.printStackTrace() @@ -807,41 +823,41 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific } private fun refresh() { - if ((srl == null) || (card == null)) return; + if ((srl == null) || (ctx.card == null)) return; try { // clear all card data and request again srl!!.isRefreshing = true - card!!.clearInfo() - card!!.error = null - card!!.message = null + ctx.coinData.clearInfo(); + ctx.card!!.clearInfo() + //engine=engine!!.swithToBaseEngine() + ctx.error = null + ctx.message = null requestCounter = 0 updateViews() - val engine = CoinEngineFactory.create(card!!.blockchain) - requestVerifyAndGetInfo() // Bitcoin - if (card!!.blockchain == Blockchain.Bitcoin || card!!.blockchain == Blockchain.BitcoinTestNet) { - card!!.setIsBalanceEqual(true) + if (ctx.blockchain == Blockchain.Bitcoin || ctx.blockchain == Blockchain.BitcoinTestNet) { + ctx.coinData.setIsBalanceEqual(true) - requestElectrum(card!!, ElectrumRequest.checkBalance(card!!.wallet)) - requestElectrum(card!!, ElectrumRequest.listUnspent(card!!.wallet)) + requestElectrum(ElectrumRequest.checkBalance(ctx.card!!.wallet)) + requestElectrum(ElectrumRequest.listUnspent(ctx.card!!.wallet)) requestRateInfo("bitcoin") } // BitcoinCash - else if (card!!.blockchain == Blockchain.BitcoinCash || card!!.blockchain == Blockchain.BitcoinCashTestNet) { - card!!.setIsBalanceEqual(true) + else if (ctx.blockchain == Blockchain.BitcoinCash || ctx.blockchain == Blockchain.BitcoinCashTestNet) { + ctx.coinData.setIsBalanceEqual(true) - requestElectrum(card!!, ElectrumRequest.checkBalance(card!!.wallet)) - requestElectrum(card!!, ElectrumRequest.listUnspent(card!!.wallet)) + requestElectrum(ElectrumRequest.checkBalance(ctx.card!!.wallet)) + requestElectrum(ElectrumRequest.listUnspent(ctx.card!!.wallet)) requestRateInfo("bitcoin-cash") } // Ethereum - else if (card!!.blockchain == Blockchain.Ethereum || card!!.blockchain == Blockchain.EthereumTestNet) { + 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, "") @@ -849,8 +865,9 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific } // Token - else if (card!!.blockchain == Blockchain.Token) { - requestInfura(ServerApiHelper.INFURA_ETH_CALL, engine.getContractAddress(card)) + 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) { @@ -858,10 +875,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific } } - private fun requestElectrum(card: TangemCard, electrumRequest: ElectrumRequest) { + private fun requestElectrum(electrumRequest: ElectrumRequest) { if (UtilHelper.isOnline(activity!!)) { requestCounter++ - serverApiHelperElectrum.electrumRequestData(card, electrumRequest) + serverApiHelperElectrum.electrumRequestData(ctx.card, electrumRequest) } else { Toast.makeText(activity!!, getString(R.string.no_connection), Toast.LENGTH_SHORT).show() srl!!.isRefreshing = false @@ -871,7 +888,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific private fun requestInfura(method: String, contract: String) { if (UtilHelper.isOnline(activity)) { requestCounter++ - serverApiHelper.infura(method, 67, card!!.wallet, contract, "") + serverApiHelper.infura(method, 67, ctx.card!!.wallet, contract, "") } else { Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show() srl!!.isRefreshing = false @@ -880,8 +897,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific private fun requestVerifyAndGetInfo() { if (UtilHelper.isOnline(activity)) { - if ((card!!.isOnlineVerified == null || !card!!.isOnlineVerified)) { - serverApiHelper.cardVerifyAndGetInfo(card) + if ((ctx.card!!.isOnlineVerified == null || !ctx.card!!.isOnlineVerified)) { + serverApiHelper.cardVerifyAndGetInfo(ctx.card) } } else { Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show() @@ -911,7 +928,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific ?: throw CardProtocol.TangemException(getString(R.string.wrong_tag_err)) val uid = tag!!.id val sUID = Util.byteArrayToHexString(uid) - if (card!!.uid != sUID) { + if (ctx.card!!.uid != sUID) { // Log.d(TAG, "Invalid UID: $sUID") nfcManager!!.ignoreTag(isoDep.tag) return @@ -925,7 +942,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific isoDep.timeout = 65000 } - verifyCardTask = VerifyCardTask(activity, card, nfcManager, isoDep, this) + verifyCardTask = VerifyCardTask(activity, ctx.card, nfcManager, isoDep, this) verifyCardTask!!.start() } catch (e: Exception) { @@ -935,7 +952,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific private fun doShareWallet(useURI: Boolean) { if (useURI) { - val txtShare = CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card).toString() + val engine = CoinEngineFactory.create(ctx) + val txtShare = engine!!.shareWalletUri.toString() val intent = Intent(Intent.ACTION_SEND) intent.type = "text/plain" intent.putExtra(Intent.EXTRA_SUBJECT, "Wallet address") @@ -959,7 +977,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific Toast.makeText(activity, R.string.copied_clipboard, Toast.LENGTH_LONG).show() } } else { - val txtShare = card!!.wallet + val txtShare = ctx.card!!.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() @@ -968,8 +986,9 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific private fun startSwapPINActivity() { val intent = Intent(activity, PinSwapActivity::class.java) - intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) - intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) + ctx.saveToBundle(intent.extras) +// intent.putExtra(TangemCard.EXTRA_UID, card!!.uid) +// intent.putExtra(TangemCard.EXTRA_CARD, card!!.asBundle) intent.putExtra("newPIN", newPIN) intent.putExtra("newPIN2", newPIN2) startActivityForResult(intent, REQUEST_CODE_SWAP_PIN) diff --git a/app/src/main/java/com/tangem/presentation/fragment/VerifyCard.kt b/app/src/main/java/com/tangem/presentation/fragment/VerifyCard.kt index cc72c223ec..88bd8efa92 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/VerifyCard.kt +++ b/app/src/main/java/com/tangem/presentation/fragment/VerifyCard.kt @@ -14,10 +14,7 @@ import android.view.ViewGroup import android.widget.PopupMenu import android.widget.Toast import com.tangem.domain.cardReader.NfcManager -import com.tangem.domain.wallet.Blockchain -import com.tangem.domain.wallet.CoinEngineFactory -import com.tangem.domain.wallet.PINStorage -import com.tangem.domain.wallet.TangemCard +import com.tangem.domain.wallet.* import com.tangem.presentation.activity.CreateNewWalletActivity import com.tangem.presentation.activity.PurgeActivity import com.tangem.presentation.activity.PinRequestActivity @@ -45,7 +42,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { } private var nfcManager: NfcManager? = null - private var card: TangemCard? = null + private lateinit var ctx: TangemContext private var requestPIN2Count = 0 private var timerHideErrorAndMessage: Timer? = null @@ -56,8 +53,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { super.onCreate(savedInstanceState) nfcManager = NfcManager(activity, this) - card = TangemCard(activity!!.intent.getStringExtra("UID")) - card!!.loadFromBundle(activity!!.intent.extras!!.getBundle("Card")) + ctx = TangemContext.loadFromBundle(activity, activity!!.intent.extras) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -105,8 +101,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { if (data.extras!!.containsKey("confirmPIN")) { val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) newPIN = data.getStringExtra("newPIN") startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) } else { @@ -122,8 +117,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { if (data.extras!!.containsKey("confirmPIN2")) { val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) newPIN2 = data.getStringExtra("newPIN2") startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) } else { @@ -135,7 +129,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { } } REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) { - if (newPIN == "") newPIN = card!!.pin + if (newPIN == "") newPIN = ctx.card!!.pin if (newPIN2 == "") newPIN2 = PINStorage.getPIN2() @@ -153,8 +147,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { REQUEST_CODE_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) { if (data == null) { data = Intent() - data.putExtra("UID", card!!.uid) - data.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(data.extras) data.putExtra("modification", "delete") } else data.putExtra("modification", "update") @@ -164,34 +157,31 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { if (data != null && data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) { val updatedCard = TangemCard(data.getStringExtra("UID")) updatedCard.loadFromBundle(data.getBundleExtra("Card")) - card = updatedCard + ctx.card = updatedCard } if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { requestPIN2Count++ val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) return } else { if (data != null && data.extras!!.containsKey("message")) { - card!!.error = data.getStringExtra("message") + ctx.error = data.getStringExtra("message") } } } REQUEST_CODE_REQUEST_PIN2_FOR_PURGE -> if (resultCode == Activity.RESULT_OK) { val intent = Intent(context, PurgeActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) startActivityForResult(intent, REQUEST_CODE_PURGE) } REQUEST_CODE_PURGE -> if (resultCode == Activity.RESULT_OK) { if (data == null) { data = Intent() - data.putExtra("UID", card!!.uid) - data.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(data.extras) data.putExtra("modification", "delete") } else { data.putExtra("modification", "update") @@ -202,19 +192,18 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { if (data != null && data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) { val updatedCard = TangemCard(data.getStringExtra("UID")) updatedCard.loadFromBundle(data.getBundleExtra("Card")) - card = updatedCard + ctx.card = updatedCard } if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { requestPIN2Count++ val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_PURGE) return } else { if (data != null && data.extras!!.containsKey("message")) { - card!!.error = data.getStringExtra("message") + ctx.error = data.getStringExtra("message") } } updateViews() @@ -222,7 +211,8 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { REQUEST_CODE_SEND_PAYMENT -> { if (resultCode == Activity.RESULT_OK) { srlVerifyCard.isRefreshing = true - card!!.clearInfo() + ctx.coinData!!.clearInfo() + ctx.card!!.switchToInitialBlockchain() updateViews() } @@ -230,13 +220,13 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { if (data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) { val updatedCard = TangemCard(data.getStringExtra("UID")) updatedCard.loadFromBundle(data.getBundleExtra("Card")) - card = updatedCard + ctx.card = updatedCard } if (data.extras!!.containsKey("message")) { if (resultCode == Activity.RESULT_OK) - card!!.message = data.getStringExtra("message") + ctx.message = data.getStringExtra("message") else - card!!.error = data.getStringExtra("message") + ctx.error = data.getStringExtra("message") } updateViews() } @@ -259,26 +249,26 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { timerHideErrorAndMessage!!.cancel() timerHideErrorAndMessage = null } - tvCardID.text = card!!.cidDescription + tvCardID.text = ctx.card!!.cidDescription - if (card!!.error == null || card!!.error.isEmpty()) { + if (ctx.error == null || ctx.error.isEmpty()) { tvError.visibility = View.GONE tvError.text = "" } else { tvError.visibility = View.VISIBLE - tvError.text = card!!.error + tvError.text = ctx.error } - if (card!!.message == null || card!!.message.isEmpty()) { + if (ctx.message == null || ctx.message.isEmpty()) { tvMessage.visibility = View.GONE tvMessage.text = "" } else { tvMessage.visibility = View.VISIBLE - tvMessage.text = card!!.message + tvMessage.text = ctx.message } - tvManufacturerInfo.text = card!!.manufacturer.officialName + tvManufacturerInfo.text = ctx.card!!.manufacturer.officialName - if (card!!.isManufacturerConfirmed && card!!.isCardPublicKeyValid) { + if (ctx.card!!.isManufacturerConfirmed && ctx.card!!.isCardPublicKeyValid) { tvCardIdentity.setText(R.string.attested) tvCardIdentity.setTextColor(ContextCompat.getColor(context!!, R.color.confirmed)) @@ -287,18 +277,17 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { tvCardIdentity.setTextColor(ContextCompat.getColor(context!!, R.color.not_confirmed)) } - tvIssuer.text = card!!.issuerDescription - tvCardRegistredDate.text = card!!.personalizationDateTimeDescription - //tvBlockchain.text = card!!.blockchainName - if (card!!.tokenSymbol.length > 1) { - val html = Html.fromHtml(card!!.blockchainName) + tvIssuer.text = ctx.card!!.issuerDescription + tvCardRegistredDate.text = ctx.card!!.personalizationDateTimeDescription + val html = Html.fromHtml(ctx.card!!.blockchainName) tvBlockchain.text = html - } else - tvBlockchain.text = card!!.blockchainName - tvValidationNode.text = card!!.validationNodeDescription + tvValidationNode.text = ctx.coinData!!.validationNodeDescription - if (card!!.blockchain == Blockchain.Bitcoin || card!!.blockchain == Blockchain.BitcoinTestNet || card!!.blockchain == Blockchain.BitcoinCash || card!!.blockchain == Blockchain.BitcoinCashTestNet) { + val engine = CoinEngineFactory.create(ctx) + + tvInputs.text = engine.unspentInputsDescription + if (.blockchain == Blockchain.Bitcoin || card!!.blockchain == Blockchain.BitcoinTestNet || card!!.blockchain == Blockchain.BitcoinCash || card!!.blockchain == Blockchain.BitcoinCashTestNet) { var gatheredUnspents = 0 for (i in 0 until card!!.unspentTransactions.size) { if (card!!.unspentTransactions[i].Raw.length > 1) gatheredUnspents++ @@ -308,70 +297,70 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { else tvInputs.text = "" - ivBlockchain.setImageResource(card!!.blockchain.getLogoImageResource(card!!.blockchainID, card!!.tokenSymbol)) + ivBlockchain.setImageResource(Blockchain.getLogoImageResource(ctx.card!!.blockchainID, ctx.card!!.tokenSymbol)) - if (card!!.isReusable!!) + if (ctx.card!!.isReusable!!) tvReusable.setText(R.string.reusable) else tvReusable.setText(R.string.one_off_banknote) - tvSigningMethod.text = card!!.signingMethod.description + tvSigningMethod.text = ctx.card!!.signingMethod.description - if (card!!.status == TangemCard.Status.Loaded || card!!.status == TangemCard.Status.Purged) { + if (ctx.card!!.status == TangemCard.Status.Loaded || ctx.card!!.status == TangemCard.Status.Purged) { when { - card!!.remainingSignatures == 0 -> { + ctx.card!!.remainingSignatures == 0 -> { tvRemainingSignatures.setTextColor(ContextCompat.getColor(context!!, R.color.not_confirmed)) tvRemainingSignatures.setText(R.string.none) } - card!!.remainingSignatures == 1 -> { + ctx.card!!.remainingSignatures == 1 -> { tvRemainingSignatures.setTextColor(ContextCompat.getColor(context!!, R.color.not_confirmed)) tvRemainingSignatures.setText(R.string.last_one) } - card!!.remainingSignatures > 1000 -> { + ctx.card!!.remainingSignatures > 1000 -> { tvRemainingSignatures.setTextColor(ContextCompat.getColor(context!!, R.color.confirmed)) tvRemainingSignatures.setText(R.string.unlimited) } else -> { tvRemainingSignatures.setTextColor(ContextCompat.getColor(context!!, R.color.confirmed)) - tvRemainingSignatures.text = card!!.remainingSignatures.toString() + tvRemainingSignatures.text = ctx.card!!.remainingSignatures.toString() } } - tvSignedTx.text = (card!!.maxSignatures - card!!.remainingSignatures).toString() + tvSignedTx.text = (ctx.card!!.maxSignatures - ctx.card!!.remainingSignatures).toString() } else { tvLastSigned.text = "" tvRemainingSignatures.text = "" tvSignedTx.text = "" } - tvFirmware.text = card!!.firmwareVersion + tvFirmware.text = ctx.card!!.firmwareVersion var features = "" - features += if (card!!.allowSwapPIN()!! && card!!.allowSwapPIN2()!!) { + features += if (ctx.card!!.allowSwapPIN()!! && ctx.card!!.allowSwapPIN2()!!) { "Allows change PIN1 and PIN2\n" - } else if (card!!.allowSwapPIN()!!) { + } else if (ctx.card!!.allowSwapPIN()!!) { "Allows change PIN1\n" - } else if (card!!.allowSwapPIN2()!!) { + } else if (ctx.card!!.allowSwapPIN2()!!) { "Allows change PIN2\n" } else { "Fixed PIN1 and PIN2\n" } - if (card!!.needCVC()!!) + if (ctx.card!!.needCVC()!!) features += "Requires CVC\n" - if (card!!.supportDynamicNDEF()!!) { + if (ctx.card!!.supportDynamicNDEF()!!) { features += "Dynamic NDEF for iOS\n" - } else if (card!!.supportNDEF()!!) + } else if (ctx.card!!.supportNDEF()!!) features += "NDEF\n" - if (card!!.supportBlock()!!) + if (ctx.card!!.supportBlock()!!) features += "Blockable\n" - if (card!!.supportOnlyOneCommandAtTime()!!) + if (ctx.card!!.supportOnlyOneCommandAtTime()!!) features += "Atomic command mode" if (features.endsWith("\n")) @@ -379,7 +368,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { tvFeatures.text = features - if (card!!.useDefaultPIN1()!!) { + if (ctx.card!!.useDefaultPIN1()!!) { imgPIN.setImageResource(R.drawable.unlock_pin1) imgPIN.setOnClickListener { Toast.makeText(context, R.string.this_banknote_protected_default_PIN1_code, Toast.LENGTH_LONG).show() } } else { @@ -387,10 +376,10 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { imgPIN.setOnClickListener { Toast.makeText(context, R.string.this_banknote_protected_user_PIN1_code, Toast.LENGTH_LONG).show() } } - if (card!!.pauseBeforePIN2 > 0 && (card!!.useDefaultPIN2()!! || !card!!.useSmartSecurityDelay())) { + if (ctx.card!!.pauseBeforePIN2 > 0 && (ctx.card!!.useDefaultPIN2()!! || !ctx.card!!.useSmartSecurityDelay())) { imgPIN2orSecurityDelay.setImageResource(R.drawable.timer) - imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(context, String.format(getString(R.string.this_banknote_will_enforce), card!!.pauseBeforePIN2 / 1000.0), Toast.LENGTH_LONG).show() } - } else if (card!!.useDefaultPIN2()!!) { + imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(context, String.format(getString(R.string.this_banknote_will_enforce), ctx.card!!.pauseBeforePIN2 / 1000.0), Toast.LENGTH_LONG).show() } + } else if (ctx.card!!.useDefaultPIN2()!!) { imgPIN2orSecurityDelay.setImageResource(R.drawable.unlock_pin2) imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(context, R.string.this_banknote_protected_default_PIN2_code, Toast.LENGTH_LONG).show() } } else { @@ -398,16 +387,16 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { imgPIN2orSecurityDelay.setOnClickListener { Toast.makeText(context, R.string.this_banknote_protected_user_PIN2_code, Toast.LENGTH_LONG).show() } } - if (card!!.useDevelopersFirmware()!!) { + if (ctx.card!!.useDevelopersFirmware()!!) { imgDeveloperVersion.setImageResource(R.drawable.ic_developer_version) imgDeveloperVersion.visibility = View.VISIBLE imgDeveloperVersion.setOnClickListener { Toast.makeText(context, R.string.unlocked_banknote_only_development_use, Toast.LENGTH_LONG).show() } } else imgDeveloperVersion.visibility = View.INVISIBLE - if (card!!.status == TangemCard.Status.Loaded) { - tvWallet.text = card!!.shortWalletString - if (card!!.isWalletPublicKeyValid) { + if (ctx.card!!.status == TangemCard.Status.Loaded) { + tvWallet.text = ctx.card!!.shortWalletString + if (ctx.card!!.isWalletPublicKeyValid) { tvWalletIdentity.setText(R.string.possession_proved) tvWalletIdentity.setTextColor(ContextCompat.getColor(context!!, R.color.confirmed)) } else { @@ -450,8 +439,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { requestPIN2Count = 0 val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) newPIN = PINStorage.getDefaultPIN() newPIN2 = "" startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) @@ -461,8 +449,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { requestPIN2Count = 0 val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) newPIN = "" newPIN2 = PINStorage.getDefaultPIN2() startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) @@ -472,8 +459,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { requestPIN2Count = 0 val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) newPIN = PINStorage.getDefaultPIN() newPIN2 = PINStorage.getDefaultPIN2() startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN) @@ -490,25 +476,23 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { private fun doPurge() { requestPIN2Count = 0 - val engine = CoinEngineFactory.create(card!!.blockchain) - if (!card!!.hasBalanceInfo()) { + val engine=CoinEngineFactory.create(ctx) + if (!engine.hasBalanceInfo()) { return - } else if (engine != null && engine.isBalanceNotZero(card)) { + } else if (engine.isBalanceNotZero) { Toast.makeText(context, R.string.cannot_erase_wallet_with_non_zero_balance, Toast.LENGTH_LONG).show() return } val intent = Intent(context, PinRequestActivity::class.java) intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString()) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_PURGE) } private fun startSwapPINActivity() { val intent = Intent(context, PinSwapActivity::class.java) - intent.putExtra("UID", card!!.uid) - intent.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(intent.extras) intent.putExtra("newPIN", newPIN) intent.putExtra("newPIN2", newPIN2) startActivityForResult(intent, REQUEST_CODE_SWAP_PIN) @@ -516,8 +500,7 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { fun prepareResultIntent(): Intent { val data = Intent() - data.putExtra("UID", card!!.uid) - data.putExtra("Card", card!!.asBundle) + ctx.saveToBundle(data.extras) return data } @@ -526,12 +509,12 @@ class VerifyCard : Fragment(), NfcAdapter.ReaderCallback { val inflater = popup.menuInflater inflater.inflate(R.menu.menu_loaded_wallet, popup.menu) - popup.menu.findItem(R.id.action_set_PIN1).isVisible = card!!.allowSwapPIN()!! - popup.menu.findItem(R.id.action_reset_PIN1).isVisible = card!!.allowSwapPIN()!! && !card!!.useDefaultPIN1() - popup.menu.findItem(R.id.action_set_PIN2).isVisible = card!!.allowSwapPIN2()!! - popup.menu.findItem(R.id.action_reset_PIN2).isVisible = card!!.allowSwapPIN2()!! && !card!!.useDefaultPIN2() - popup.menu.findItem(R.id.action_reset_PINs).isVisible = card!!.allowSwapPIN()!! && card!!.allowSwapPIN2()!! && !card!!.useDefaultPIN1() && !card!!.useDefaultPIN2() - if (!card!!.isReusable || card!!.status != TangemCard.Status.Loaded) + popup.menu.findItem(R.id.action_set_PIN1).isVisible = ctx.card!!.allowSwapPIN()!! + popup.menu.findItem(R.id.action_reset_PIN1).isVisible = ctx.card!!.allowSwapPIN()!! && !ctx.card!!.useDefaultPIN1() + popup.menu.findItem(R.id.action_set_PIN2).isVisible = ctx.card!!.allowSwapPIN2()!! + popup.menu.findItem(R.id.action_reset_PIN2).isVisible = ctx.card!!.allowSwapPIN2()!! && !ctx.card!!.useDefaultPIN2() + popup.menu.findItem(R.id.action_reset_PINs).isVisible = ctx.card!!.allowSwapPIN()!! && ctx.card!!.allowSwapPIN2()!! && !ctx.card!!.useDefaultPIN1() && !ctx.card!!.useDefaultPIN2() + if (!ctx.card!!.isReusable || ctx.card!!.status != TangemCard.Status.Loaded) popup.menu.findItem(R.id.action_purge).isVisible = false popup.setOnMenuItemClickListener { item -> diff --git a/app/src/main/java/com/tangem/util/BTCUtils.java b/app/src/main/java/com/tangem/util/BTCUtils.java index 2ffecbd159..0adf324f4b 100644 --- a/app/src/main/java/com/tangem/util/BTCUtils.java +++ b/app/src/main/java/com/tangem/util/BTCUtils.java @@ -9,7 +9,7 @@ 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.TangemCard; +import com.tangem.domain.wallet.BtcData; import com.tangem.domain.wallet.Transaction; import com.tangem.domain.wallet.UnspentOutputInfo; @@ -325,10 +325,10 @@ public final class BTCUtils { } return false; } - public static ArrayList getOutputs(List rawTxList, byte[] outputScriptWeAreAbleToSpend) throws BitcoinException { + public static ArrayList getOutputs(List rawTxList, byte[] outputScriptWeAreAbleToSpend) throws BitcoinException { ArrayList unspentOutputs = new ArrayList<>(); - for(TangemCard.UnspentTransaction current: rawTxList) + for(BtcData.UnspentTransaction current: rawTxList) { byte[] rawTxByte = BTCUtils.fromHex(current.Raw); if (rawTxByte == null || current.Raw.isEmpty()) diff --git a/app/src/main/java/com/tangem/util/Util.java b/app/src/main/java/com/tangem/util/Util.java index 08ffe3eced..3ebf4b4bfa 100644 --- a/app/src/main/java/com/tangem/util/Util.java +++ b/app/src/main/java/com/tangem/util/Util.java @@ -406,7 +406,7 @@ public class Util { (byte) value}; } - public static int byteArrayToInt(byte[] byteArray) { + public static int byteArrayToInt(byte[] byteArray) throws IllegalArgumentException { if( byteArray.length==1 ) return byteArray[0]&0xFF; java.nio.ByteBuffer BB=java.nio.ByteBuffer.wrap(byteArray); switch (byteArray.length) @@ -417,7 +417,7 @@ public class Util { } } - public static long byteArrayToLong(byte[] byteArray) { + public static long byteArrayToLong(byte[] byteArray) throws IllegalArgumentException { if( byteArray.length==1 ) return byteArray[0]&0xFF; java.nio.ByteBuffer BB=java.nio.ByteBuffer.wrap(byteArray); switch (byteArray.length) @@ -442,7 +442,7 @@ public class Util { (byte) value}; } - public static int byteArrayToInt(byte[] byteArray, int startPos, int length) { + public static int byteArrayToInt(byte[] byteArray, int startPos, int length) throws IllegalArgumentException { if (byteArray == null) { throw new IllegalArgumentException("Parameter 'byteArray' cannot be null"); } @@ -459,7 +459,7 @@ public class Util { return value; } - public static long byteArrayToLong(byte[] byteArray, int startPos, int length) { + public static long byteArrayToLong(byte[] byteArray, int startPos, int length) throws IllegalArgumentException { if (byteArray == null) { throw new IllegalArgumentException("Parameter 'byteArray' cannot be null"); }