From 9652cf62cca885f7fd9a47b41f7bfeb62422ba1d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 1 Mar 2019 18:19:45 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/domain/wallet/btc/BtcEngine.java | 96 ++++++++++++++----- .../tangem/domain/wallet/eth/EthEngine.java | 3 +- .../tangem/domain/wallet/ltc/LitecoinNode.kt | 12 +-- .../tangem/domain/wallet/ltc/LtcEngine.java | 5 - .../tangem/domain/wallet/rsk/RskEngine.java | 2 +- .../domain/wallet/rsk/RskTokenEngine.java | 20 ++-- .../domain/wallet/token/TokenEngine.java | 2 + .../layout/activity_confirm_transaction.xml | 2 +- 8 files changed, 93 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java b/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java index 405b50c8db..2549a0be23 100644 --- a/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java @@ -4,27 +4,28 @@ import android.net.Uri; import android.text.InputFilter; import android.util.Log; -import com.tangem.data.network.ServerApiCommon; +import com.tangem.App; +import com.tangem.card_common.data.TangemCard; import com.tangem.card_common.reader.CardProtocol; +import com.tangem.card_common.tasks.SignTask; +import com.tangem.card_common.util.Util; +import com.tangem.data.Blockchain; +import com.tangem.data.local.PendingTransactionsStorage; +import com.tangem.data.network.ElectrumRequest; +import com.tangem.data.network.ServerApiCommon; +import com.tangem.data.network.ServerApiElectrum; +import com.tangem.domain.wallet.BTCUtils; import com.tangem.domain.wallet.BalanceValidator; import com.tangem.domain.wallet.Base58; -import com.tangem.data.Blockchain; import com.tangem.domain.wallet.CoinData; import com.tangem.domain.wallet.CoinEngine; -import com.tangem.card_common.data.TangemCard; import com.tangem.domain.wallet.TangemContext; import com.tangem.domain.wallet.Transaction; import com.tangem.domain.wallet.UnspentOutputInfo; -import com.tangem.domain.wallet.BTCUtils; -import com.tangem.card_common.tasks.SignTask; import com.tangem.util.CryptoUtil; import com.tangem.util.DecimalDigitsInputFilter; import com.tangem.util.DerEncodingUtil; -import com.tangem.card_common.util.Util; import com.tangem.wallet.R; -import com.tangem.data.network.ElectrumRequest; -import com.tangem.data.network.ServerApiElectrum; - import org.json.JSONArray; import org.json.JSONException; @@ -311,9 +312,7 @@ public class BtcEngine extends CoinEngine { // } return true; - } - catch (Exception e) - { + } catch (Exception e) { e.printStackTrace(); return false; } @@ -477,7 +476,8 @@ public class BtcEngine extends CoinEngine { @Override public byte[][] getHashesToSign() throws Exception { byte[][] dataForSign = new byte[unspentOutputs.size()][]; - if (txForSign.length > 10) throw new Exception("To much hashes in one transaction!"); + if (txForSign.length > 10) + throw new Exception("To much hashes in one transaction!"); for (int i = 0; i < unspentOutputs.size(); ++i) { dataForSign[i] = bodyDoubleHash[i]; } @@ -530,7 +530,7 @@ public class BtcEngine extends CoinEngine { ServerApiElectrum.ResponseListener electrumListener = new ServerApiElectrum.ResponseListener() { @Override public void onSuccess(ElectrumRequest electrumRequest) { - Log.i(TAG, "onSuccess: "+electrumRequest.getMethod()); + Log.i(TAG, "onSuccess: " + electrumRequest.getMethod()); if (electrumRequest.isMethod(ElectrumRequest.METHOD_GetBalance)) { try { String walletAddress = electrumRequest.getParams().getString(0); @@ -544,6 +544,7 @@ public class BtcEngine extends CoinEngine { coinData.setBalanceConfirmed(confBalance); coinData.setBalanceUnconfirmed(unconfirmedBalance); coinData.setValidationNodeDescription(serverApiElectrum.getValidationNodeDescription()); + checkPending(blockchainRequestsCallbacks); } catch (JSONException e) { e.printStackTrace(); Log.e(TAG, "FAIL METHOD_GetBalance JSONException"); @@ -600,19 +601,19 @@ public class BtcEngine extends CoinEngine { if (serverApiElectrum.isRequestsSequenceCompleted()) { blockchainRequestsCallbacks.onComplete(!ctx.hasError()); - }else{ + } else { blockchainRequestsCallbacks.onProgress(); } } @Override public void onFail(ElectrumRequest electrumRequest) { - Log.i(TAG, "onFail: "+electrumRequest.getMethod()+" "+electrumRequest.getError()); + Log.i(TAG, "onFail: " + electrumRequest.getMethod() + " " + electrumRequest.getError()); ctx.setError(electrumRequest.getError()); // ctx.setError(R.string.cannot_obtain_data_from_blockchain); if (serverApiElectrum.isRequestsSequenceCompleted()) { blockchainRequestsCallbacks.onComplete(false);//serverApiElectrum.isErrorOccurred(), serverApiElectrum.getError()); - }else{ + } else { blockchainRequestsCallbacks.onProgress(); } } @@ -624,6 +625,50 @@ public class BtcEngine extends CoinEngine { serverApiElectrum.requestData(ctx, ElectrumRequest.listUnspent(coinData.getWallet())); } + private void checkPending(BlockchainRequestsCallbacks blockchainRequestsCallbacks) { + if (App.pendingTransactionsStorage.hasTransactions(ctx.getCard())) { + ServerApiElectrum serverApiElectrum = new ServerApiElectrum(); + + ServerApiElectrum.ResponseListener electrumListener = new ServerApiElectrum.ResponseListener() { + @Override + public void onSuccess(ElectrumRequest electrumRequest) { + Log.i(TAG, "onSuccess: " + electrumRequest.getMethod()); + try { + if (electrumRequest.getResultString() != null) { + App.pendingTransactionsStorage.removeTransaction(ctx.getCard(), electrumRequest.txHash); + } + + } catch (Exception e) { + Log.e(TAG, "onFail: " + electrumRequest.getMethod() + " " + electrumRequest.getError()); + } + if (serverApiElectrum.isRequestsSequenceCompleted()) { + blockchainRequestsCallbacks.onComplete(!ctx.hasError()); + } else { + blockchainRequestsCallbacks.onProgress(); + } + } + + @Override + public void onFail(ElectrumRequest electrumRequest) { + Log.i(TAG, "onFail: " + electrumRequest.getMethod() + " " + electrumRequest.getError()); +// ctx.setError(R.string.cannot_obtain_data_from_blockchain); + if (serverApiElectrum.isRequestsSequenceCompleted()) { + blockchainRequestsCallbacks.onComplete(false);//serverApiElectrum.isErrorOccurred(), serverApiElectrum.getError()); + } else { + blockchainRequestsCallbacks.onProgress(); + } + } + }; + + serverApiElectrum.setResponseListener(electrumListener); + for (PendingTransactionsStorage.TransactionInfo pendingTx : App.pendingTransactionsStorage.getTransactions(ctx.getCard()).getTransactions()) { + String txHash = BTCUtils.toHex(CryptoUtil.doubleSha256(BTCUtils.fromHex(pendingTx.getTx()))); + serverApiElectrum.requestData(ctx, ElectrumRequest.getTransaction(ctx.getCoinData().getWallet(), txHash)); + } + } + } + + protected Integer calculateEstimatedTransactionSize(String outputAddress, String outAmount) { //todo - правильней было бы использовать constructTransaction try { @@ -686,15 +731,16 @@ public class BtcEngine extends CoinEngine { // // byte[] realTX = BTCUtils.buildTXForSend(outputAddress, myAddress, unspentOutputs, amount, change); - SignTask.TransactionToSign ps= constructTransaction(new Amount(outAmount, getBalanceCurrency()),new Amount("0.00",getFeeCurrency()), true, outputAddress ); + SignTask.TransactionToSign ps = constructTransaction(new Amount(outAmount, getBalanceCurrency()), new Amount("0.00", getFeeCurrency()), true, outputAddress); OnNeedSendTransaction onNeedSendTransactionBackup = onNeedSendTransaction; - onNeedSendTransaction =(tx)->{}; // empty function to bypass exception + onNeedSendTransaction = (tx) -> { + }; // empty function to bypass exception - byte[][] hashesToSign=ps.getHashesToSign(); + byte[][] hashesToSign = ps.getHashesToSign(); byte[] signFromCard = new byte[64 * hashesToSign.length]; - byte[] txForSend=ps.onSignCompleted(signFromCard); + byte[] txForSend = ps.onSignCompleted(signFromCard); onNeedSendTransaction = onNeedSendTransactionBackup; - Log.e(TAG,"txForSend.length="+String.valueOf(txForSend.length)); + Log.e(TAG, "txForSend.length=" + String.valueOf(txForSend.length)); return txForSend.length; // Log.e(TAG,"txForSend.length="+String.valueOf(txForSend.length)+" realTX.length="+String.valueOf(realTX.length)); @@ -753,9 +799,9 @@ public class BtcEngine extends CoinEngine { break; } - if(coinData.minFee!=null && coinData.normalFee!=null && coinData.maxFee!=null ) { + if (coinData.minFee != null && coinData.normalFee != null && coinData.maxFee != null) { blockchainRequestsCallbacks.onComplete(true); - }else{ + } else { blockchainRequestsCallbacks.onProgress(); } } @@ -793,7 +839,7 @@ public class BtcEngine extends CoinEngine { if (resultString == null || resultString.isEmpty()) { ctx.setError("Rejected by node: " + electrumRequest.getError()); blockchainRequestsCallbacks.onComplete(false); - }else { + } else { ctx.setError(null); blockchainRequestsCallbacks.onComplete(true); } diff --git a/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java b/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java index 955785ab68..8a7123527b 100644 --- a/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/eth/EthEngine.java @@ -608,6 +608,7 @@ public class EthEngine extends CoinEngine { serverApiInfura.setResponseListener(responseListener); serverApiInfura.requestData(ServerApiInfura.INFURA_ETH_SEND_RAW_TRANSACTION, 67, coinData.getWallet(), "", txStr); - } + + public int pendingTransactionTimeoutInSeconds() { return 10; } } diff --git a/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt b/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt index de37286389..e80cdc458d 100644 --- a/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt +++ b/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt @@ -3,11 +3,9 @@ package com.tangem.domain.wallet.ltc enum class LitecoinNode(val host: String, val port: Int, val proto: String) { N_001("backup.electrum-ltc.org", 443, "ssl"), N_002("electrum-ltc.petrkr.net", 60002, "ssl"), - N_003("technetium.network", 50003, "ssl"), - N_004("167.99.146.166", 50002, "ssl"), - N_005("electrum-ltc.bysh.me", 50002, "ssl"), - N_006("e-3.claudioboxx.com", 50004, "ssl"), - N_007("e-1.claudioboxx.com", 50004, "ssl"), - N_008("e-2.claudioboxx.com", 50004, "ssl"), - N_009("electrum.ltc.xurious.com", 50002, "ssl"), + N_003("electrum-ltc.bysh.me", 50002, "ssl"), + N_004("e-3.claudioboxx.com", 50004, "ssl"), + N_005("e-1.claudioboxx.com", 50004, "ssl"), + N_006("e-2.claudioboxx.com", 50004, "ssl"), + N_007("electrum.ltc.xurious.com", 50002, "ssl"), } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/ltc/LtcEngine.java b/app/src/main/java/com/tangem/domain/wallet/ltc/LtcEngine.java index bc80eb429a..17db21d852 100644 --- a/app/src/main/java/com/tangem/domain/wallet/ltc/LtcEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/ltc/LtcEngine.java @@ -557,9 +557,4 @@ public class LtcEngine extends BtcEngine { serverApiElectrum.requestData(ctx, ElectrumRequest.getFee()); } - - @Override - public boolean allowSelectFeeLevel() { - return false; - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java b/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java index 633aee5fc2..fd67467442 100644 --- a/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java @@ -201,8 +201,8 @@ public class RskEngine extends EthEngine { serverApiRootstock.setResponseListener(responseListener); serverApiRootstock.requestData(ServerApiRootstock.ROOTSTOCK_ETH_SEND_RAW_TRANSACTION, 67, coinData.getWallet(), "", txStr); - } + public int pendingTransactionTimeoutInSeconds() { return 10; } } diff --git a/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java b/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java index c33b7902ac..e23a529db2 100644 --- a/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java @@ -162,19 +162,19 @@ public class RskTokenEngine extends TokenEngine { gasPrice = gasPrice.substring(2); // rounding gas price to integer gwei - BigInteger l = new BigInteger(gasPrice, 16); + BigInteger gasPriceBI = new BigInteger(gasPrice, 16).divide(BigInteger.valueOf(10000000)).multiply(BigInteger.valueOf(10000000)); - Log.i(TAG, "Rootstock gas price: " + gasPrice + " (" + l.toString() + ")"); - BigInteger m; + Log.i(TAG, "Rootstock gas price: " + gasPrice + " (" + gasPriceBI.toString() + ")"); + BigInteger gasUsed; if (!amount.getCurrency().equals(Blockchain.Rootstock.getCurrency())) - m = BigInteger.valueOf(60000); - else m = BigInteger.valueOf(21000); + gasUsed = BigInteger.valueOf(60000); + else gasUsed = BigInteger.valueOf(21000); - Log.i(TAG, "fee multiplier: " + m.toString()); + Log.i(TAG, "fee multiplier: " + gasUsed.toString()); - CoinEngine.InternalAmount weiMinFee = new CoinEngine.InternalAmount(l.multiply(m), "wei"); - CoinEngine.InternalAmount weiNormalFee = new CoinEngine.InternalAmount(l.multiply(BigInteger.valueOf(12)).divide(BigInteger.valueOf(10)).multiply(m), "wei"); - CoinEngine.InternalAmount weiMaxFee = new CoinEngine.InternalAmount(l.multiply(BigInteger.valueOf(15)).divide(BigInteger.valueOf(10)).multiply(m), "wei"); + CoinEngine.InternalAmount weiMinFee = new CoinEngine.InternalAmount(gasPriceBI.multiply(gasUsed), "wei"); + CoinEngine.InternalAmount weiNormalFee = new CoinEngine.InternalAmount(gasPriceBI.multiply(BigInteger.valueOf(12)).divide(BigInteger.valueOf(10)).multiply(gasUsed), "wei"); + CoinEngine.InternalAmount weiMaxFee = new CoinEngine.InternalAmount(gasPriceBI.multiply(BigInteger.valueOf(15)).divide(BigInteger.valueOf(10)).multiply(gasUsed), "wei"); Log.i(TAG, "min fee : " + weiMinFee.toValueString() + " wei"); Log.i(TAG, "normal fee: " + weiNormalFee.toValueString() + " wei"); Log.i(TAG, "max fee : " + weiMaxFee.toValueString() + " wei"); @@ -251,4 +251,6 @@ public class RskTokenEngine extends TokenEngine { public boolean allowSelectFeeInclusion() { return getBalance().getCurrency().equals(Blockchain.Rootstock.getCurrency()); } + + public int pendingTransactionTimeoutInSeconds() { return 10; } } diff --git a/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java b/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java index 63a93d00dc..ab83e83c5d 100644 --- a/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/token/TokenEngine.java @@ -827,4 +827,6 @@ public class TokenEngine extends CoinEngine { public boolean allowSelectFeeInclusion() { return getBalance().getCurrency().equals(Blockchain.Ethereum.getCurrency()); } + + public int pendingTransactionTimeoutInSeconds() { return 10; } } diff --git a/app/src/main/res/layout/activity_confirm_transaction.xml b/app/src/main/res/layout/activity_confirm_transaction.xml index c0d8ab2048..6e10638831 100644 --- a/app/src/main/res/layout/activity_confirm_transaction.xml +++ b/app/src/main/res/layout/activity_confirm_transaction.xml @@ -278,7 +278,7 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintWidth_min="130dp" /> + app:layout_constraintWidth_min="100dp" />