Updated on 2026-08-14

This commit is contained in:
Tangem 2018-07-12 19:48:16 +03:00
commit b690338759
14 changed files with 121 additions and 57 deletions

View file

@ -22,6 +22,7 @@ public class ElectrumRequest {
public String error;
public String WalletAddress;
public String TxHash;
public String TX;
public String Host;
public int Port;
@ -125,6 +126,7 @@ public class ElectrumRequest {
ElectrumRequest request = new ElectrumRequest();
try {
request.WalletAddress=wallet;
request.TX=tx;
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_SendTransaction + "\", \"params\":[\"" + tx + "\"] }");
} catch (JSONException e) {
e.printStackTrace();

View file

@ -9,6 +9,7 @@ import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.CoinEngineFactory;
import com.tangem.domain.wallet.LastSignStorage;
import com.tangem.domain.wallet.SharedData;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.presentation.activity.SendTransactionActivity;
import org.json.JSONException;
@ -19,15 +20,46 @@ import java.util.List;
public class ConnectTask extends ElectrumTask {
private WeakReference<SendTransactionActivity> reference;
private int remaining_attempts;
public ConnectTask(SendTransactionActivity context, String host, int port) {
super(host, port);
reference = new WeakReference<>(context);
private void CreateChildTask (TangemCard mCard, String tx, String error_message) {
if (remaining_attempts > 0) {
remaining_attempts--;
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
if (mCard.getBlockchain() == Blockchain.Bitcoin || mCard.getBlockchain() == Blockchain.BitcoinTestNet) {
String nodeAddress = engine.GetNode(mCard);
int nodePort = engine.GetNodePort(mCard);
ConnectTask connectTask = new ConnectTask(reference.get(), nodeAddress, nodePort, remaining_attempts);
connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx));
} else if (mCard.getBlockchain() == Blockchain.BitcoinCash || mCard.getBlockchain() == Blockchain.BitcoinCashTestNet) {
String nodeAddress = engine.GetNode(mCard);
int nodePort = engine.GetNodePort(mCard);
ConnectTask connectTask = new ConnectTask(reference.get(), nodeAddress, nodePort,remaining_attempts);
connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx));
}
} else {
reference.get().finishWithError(error_message);
}
}
public ConnectTask(SendTransactionActivity context, String host, int port, SharedData sharedData) {
public ConnectTask(SendTransactionActivity context, String host, int port, int attempts) {
super(host, port);
reference = new WeakReference<>(context);
remaining_attempts = attempts;
}
public ConnectTask(SendTransactionActivity context, String host, int port, int attempts, SharedData sharedData) {
super(host, port, sharedData);
reference = new WeakReference<>(context);
remaining_attempts = attempts;
}
@Override
@ -61,24 +93,27 @@ public class ConnectTask extends ElectrumTask {
sendTransactionActivity.finishWithSuccess();
} catch (Exception e) {
engine.SwitchNode(null);
sendTransactionActivity.finishWithError(hashTX);
return;
// sendTransactionActivity.finishWithError(hashTX);
CreateChildTask(sendTransactionActivity.mCard, request.TX, hashTX);
}
} catch (JSONException e) {
e.printStackTrace();
engine.SwitchNode(null);
sendTransactionActivity.finishWithError(e.toString());
// sendTransactionActivity.finishWithError(e.toString());
CreateChildTask(sendTransactionActivity.mCard, request.TX, e.toString());
}
}
} else if (request.error != null) {
} else {
engine.SwitchNode(null);
sendTransactionActivity.finishWithError(request.error);
// sendTransactionActivity.finishWithError(request.error);
CreateChildTask(sendTransactionActivity.mCard, request.TX, request.error);
}
} catch (JSONException e) {
e.printStackTrace();
engine.SwitchNode(null);
sendTransactionActivity.finishWithError(e.toString());
// sendTransactionActivity.finishWithError(e.toString());
CreateChildTask(sendTransactionActivity.mCard, request.TX, e.toString());
}
}
}

View file

@ -42,6 +42,7 @@ public class ETHRequestTask extends InfuraTask {
JSONObject err = msg.getJSONObject("error");
hashTX = err.getString("message");
LastSignStorage.setLastMessage(sendTransactionActivity.mCard.getWallet(), hashTX);
Log.e("Send_TX_Error:", hashTX);
sendTransactionActivity.finishWithError(hashTX);
return;
}

View file

@ -69,6 +69,7 @@ public class SignPaymentTask extends Thread {
Log.i(TAG, "[-- Start sign payment --]");
if (isCancelled) return;
protocol.run_Read(false);
protocol.run_VerifyCard();
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
@ -102,7 +103,7 @@ public class SignPaymentTask extends Thread {
txStr = String.format("0x%s", txStr);
}
LastSignStorage.setLastTX(mCard.getWallet(), txStr);
//LastSignStorage.setLastTX(mCard.getWallet(), txStr);
Intent intent = new Intent(mContext, SendTransactionActivity.class);
intent.putExtra("UID", mCard.getUID());

View file

@ -57,7 +57,7 @@ public class VerifyCardTask extends Thread {
String PIN = mCard.getPIN();
protocol.setPIN(PIN);
protocol.run_Read();
protocol.run_Read(false);
PINStorage.setLastUsedPIN(PIN);
mNotifications.OnReadProgress(protocol, 30);
if (isCancelled) return;

View file

@ -0,0 +1,16 @@
package com.tangem.domain
enum class BitcoinNode(val host: String, val port: Int) {
n1("174.138.11.174", 50001),
n2("btc.cihar.com", 50001),
n3("electrum.leblancnet.us", 50001),
n4("electrum.qtornado.com", 50001),
n5("electrum.vom-stausee.de", 50001),
n6("helicarrier.bauerj.eu", 50001),
n7("kirsche.emzy.de", 50001),
n8("ndnd.selfhost.eu", 50001),
n9("spv.48.org", 50003),
n10("such.ninja", 50001),
n11("tardis.bauerj.eu", 50001),
n12("vps.hsmiths.com", 50001)
}

View file

@ -1,9 +1,9 @@
package com.tangem.domain
enum class BitcoinNodeTestNet(val host: String, val port: Int) {
arihanc_com("testnetnode.arihanc.com", 51001),
hsmiths_com("testnet.hsmiths.com", 53011),
qtornado_com("testnet.qtornado.com", 51001),
bauerj_eu("testnet1.bauerj.eu", 50001),
n1("testnetnode.arihanc.com", 51001),
n2("testnet.hsmiths.com", 53011),
n3("testnet.qtornado.com", 51001),
n4("testnet1.bauerj.eu", 50001),
}

View file

@ -408,6 +408,9 @@ public class CardProtocol {
}
public void run_Read() throws Exception {
run_Read(true);
}
public void run_Read(boolean parseResult) throws Exception {
CommandApdu rqApdu = StartPrepareCommand(INS.Read);
Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" ")));
@ -421,9 +424,12 @@ public class CardProtocol {
readResult = rspApdu.getTLVs();
parseReadResult();
run_ReadWriteIssuerData();
if( parseResult ){
parseReadResult();
run_ReadWriteIssuerData();
}else{
//TODO: проверить что карта та же
}
} else if (rspApdu.isStatus(SW_PIN_ERROR)) {
throw new TangemException_InvalidPIN(String.format("FAILED: [%04X] - Possible PIN is invalid!\n", rspApdu.getSW1SW2()));

View file

@ -2,6 +2,7 @@ package com.tangem.domain.wallet;
import android.net.Uri;
import com.tangem.domain.BitcoinNode;
import com.tangem.domain.BitcoinNodeTestNet;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.TLV;
@ -55,20 +56,22 @@ public class BtcEngine extends CoinEngine {
}
public static String[] GetBitcoinServiceHosts() {
return new String[]{"vps.hsmiths.com", "tardis.bauerj.eu" /*"arihancckjge66iv.onion"*/, "electrumx.bot.nu", "electrumx.hopto.org"/* "btc.asis.io"*/, "e-x.not.fyi", "electrum.backplanedns.org", "helicarrier.bauerj.eu", "electrum.vom-stausee.de", "electrum0.snel.it", "kirsche.emzy.de"};
// return new String[]{"vps.hsmiths.com", "tardis.bauerj.eu" /*"arihancckjge66iv.onion"*/, "electrumx.bot.nu", "electrumx.hopto.org"/* "btc.asis.io"*/, "e-x.not.fyi", "electrum.backplanedns.org", "helicarrier.bauerj.eu", "electrum.vom-stausee.de", "electrum0.snel.it", "kirsche.emzy.de"};
return new String[]{BitcoinNode.n1.getHost(), BitcoinNode.n2.getHost(),BitcoinNode.n3.getHost(),BitcoinNode.n4.getHost(),BitcoinNode.n5.getHost(),BitcoinNode.n6.getHost(),BitcoinNode.n7.getHost(),BitcoinNode.n8.getHost(),BitcoinNode.n9.getHost(),BitcoinNode.n10.getHost(),BitcoinNode.n11.getHost(),BitcoinNode.n12.getHost(),};
}
public static Integer[] GetBitcoinServicePorts() {
return new Integer[]{8080, 50001/* 8080*/, 50001, 50001, 50001, 50001, 50001, 50001, 50001, 50001};
// return new Integer[]{8080, 50001/* 8080*/, 50001, 50001, 50001, 50001, 50001, 50001, 50001, 50001};
return new Integer[]{BitcoinNode.n1.getPort(), BitcoinNode.n2.getPort(),BitcoinNode.n3.getPort(),BitcoinNode.n4.getPort(),BitcoinNode.n5.getPort(),BitcoinNode.n6.getPort(),BitcoinNode.n7.getPort(),BitcoinNode.n8.getPort(),BitcoinNode.n9.getPort(),BitcoinNode.n10.getPort(),BitcoinNode.n11.getPort(),BitcoinNode.n12.getPort(),};
}
public static String[] GetBitcoinTestNetServiceHosts() {
return new String[]{/*"testnetnode.arihanc.com"*/BitcoinNodeTestNet.hsmiths_com.getHost(), BitcoinNodeTestNet.qtornado_com.getHost(), BitcoinNodeTestNet.bauerj_eu.getHost()};
return new String[]{BitcoinNodeTestNet.n1.getHost(), BitcoinNodeTestNet.n2.getHost(), BitcoinNodeTestNet.n3.getHost(), BitcoinNodeTestNet.n4.getHost()};
}
public static Integer[] GetBitcoinTestNetServicePorts() {
return new Integer[]{/*51001*/BitcoinNodeTestNet.hsmiths_com.getPort(), BitcoinNodeTestNet.qtornado_com.getPort(), BitcoinNodeTestNet.bauerj_eu.getPort()};
return new Integer[]{BitcoinNodeTestNet.n1.getPort(), BitcoinNodeTestNet.n2.getPort(), BitcoinNodeTestNet.n3.getPort(), BitcoinNodeTestNet.n4.getPort()};
}

View file

@ -59,7 +59,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
public boolean balanceRequestSuccess = false;
private EditText etWallet;
// private TextView tvAmountEquivalent;
// private TextView tvFeeEquivalent;
private TextView tvFeeEquivalent;
public EditText etAmount;
public EditText etFee;
private ImageView ivCamera;
@ -95,7 +95,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
etFee = findViewById(R.id.etFee);
// TextView tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent);
// tvAmountEquivalent = findViewById(R.id.tvAmountEquivalent);
// tvFeeEquivalent = findViewById(R.id.tvFeeEquivalent);
tvFeeEquivalent = findViewById(R.id.tvFeeEquivalent);
ivCamera = findViewById(R.id.ivCamera);
rgFee = findViewById(R.id.rgFee);
@ -138,21 +138,21 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// try {
//
// CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
// String eqFee = engine.EvaluteFeeEquivalent(mCard, etFee.getText().toString());
// tvFeeEquivalent.setText(eqFee);
//
// if (!mCard.getAmountEquivalentDescriptionAvailable()) {
// tvFeeEquivalent.setError("Service unavailable");
// } else {
// tvFeeEquivalent.setError(null);
// }
// } catch (Exception e) {
// e.printStackTrace();
// tvFeeEquivalent.setText("");
// }
try {
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
String eqFee = engine.EvaluteFeeEquivalent(mCard, etFee.getText().toString());
tvFeeEquivalent.setText(eqFee);
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
tvFeeEquivalent.setError("Service unavailable");
} else {
tvFeeEquivalent.setError(null);
}
} catch (Exception e) {
e.printStackTrace();
tvFeeEquivalent.setText("");
}
}
@Override

View file

@ -47,12 +47,12 @@ public class SendTransactionActivity extends AppCompatActivity {
} else if (mCard.getBlockchain() == Blockchain.Bitcoin || mCard.getBlockchain() == Blockchain.BitcoinTestNet) {
String nodeAddress = engine.GetNode(mCard);
int nodePort = engine.GetNodePort(mCard);
ConnectTask connectTask = new ConnectTask(SendTransactionActivity.this, nodeAddress, nodePort);
ConnectTask connectTask = new ConnectTask(SendTransactionActivity.this, nodeAddress, nodePort,3);
connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx));
} else if (mCard.getBlockchain() == Blockchain.BitcoinCash || mCard.getBlockchain() == Blockchain.BitcoinCashTestNet) {
String nodeAddress = engine.GetNode(mCard);
int nodePort = engine.GetNodePort(mCard);
ConnectTask connectTask = new ConnectTask(SendTransactionActivity.this, nodeAddress, nodePort);
ConnectTask connectTask = new ConnectTask(SendTransactionActivity.this, nodeAddress, nodePort,3);
connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx));
}
@ -70,7 +70,7 @@ public class SendTransactionActivity extends AppCompatActivity {
public void finishWithError(String Message) {
Intent intent = new Intent();
intent.putExtra("message", "Failed to send transaction. Try again.");
intent.putExtra("message", "Try again. Failed to send transaction (" + Message + ")");
setResult(MainActivity.RESULT_CANCELED, intent);
finish();
}

View file

@ -680,7 +680,7 @@ public class LoadedWallet extends Fragment implements SwipeRefreshLayout.OnRefre
tvMessage.setVisibility(View.GONE);
} else {
if (needResendTX) {
tvMessage.setText(R.string.sending_cached_transaction);
//tvMessage.setText(R.string.sending_cached_transaction);
} else {
tvMessage.setText(mCard.getMessage());
}

View file

@ -330,18 +330,18 @@
app:layout_constraintLeft_toRightOf="@+id/etFee"
app:layout_constraintTop_toTopOf="parent"/>
<!--<TextView-->
<!--android:id="@+id/tvFeeEquivalent"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_marginStart="8dp"-->
<!--android:fontFamily="@font/montserrat_light"-->
<!--android:textColor="@android:color/darker_gray"-->
<!--android:textSize="@dimen/text_size_1_small"-->
<!--app:layout_constraintBottom_toBottomOf="parent"-->
<!--app:layout_constraintLeft_toRightOf="@+id/tvCurrency2"-->
<!--app:layout_constraintTop_toTopOf="parent"-->
<!--tools:text="000"/>-->
<TextView
android:id="@+id/tvFeeEquivalent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:fontFamily="@font/montserrat_light"
android:paddingLeft="10dp"
android:textColor="@android:color/darker_gray"
android:textSize="@dimen/text_size_1_small"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/tvCurrency2"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

View file

@ -91,7 +91,7 @@
<string name="wallet_empty">The wallet is empty</string>
<string name="not_enough_funds">Not enough funds for transaction fee (gas)!</string>
<string name="please_wait_while_previous">Please wait while previous transaction is confirmed in blockchain</string>
<string name="please_wait_for_confirmation">Please wait for confirmation of incoming transaction!</string>
<string name="please_wait_for_confirmation">Could not obtain all inputs. Swipe down to refresh.</string>
<string name="card_hasn_t_remaining_signature">Card hasn\'t remaining signature!</string>
<string name="reusable_wallet">REUSABLE WALLET</string>
<string name="banknote">BANKNOTE</string>