Updated on 2026-08-14
This commit is contained in:
commit
b690338759
14 changed files with 121 additions and 57 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
16
app/src/main/java/com/tangem/domain/BitcoinNode.kt
Normal file
16
app/src/main/java/com/tangem/domain/BitcoinNode.kt
Normal 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)
|
||||
}
|
||||
|
|
@ -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),
|
||||
|
||||
}
|
||||
|
|
@ -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()));
|
||||
|
|
|
|||
|
|
@ -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()};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue