Updated on 2026-08-14

This commit is contained in:
Tangem 2019-08-23 13:01:33 +03:00
commit 8610d2f668
34 changed files with 718 additions and 592 deletions

View file

@ -49,8 +49,8 @@ android {
flavorDimensions ""
productFlavors {
tangemAccess {
versionCode 112
versionName "0.907.1." + generateVersionName()
versionCode 114
versionName "0.908.1." + generateVersionName()
applicationId "com.tangem.wallet"
signingConfig signingConfigs.debug
}

View file

@ -8,15 +8,6 @@
"privateKey": "11121314151617184771ED81F2BACF57479E4735EB1405081918171615141312"
}
},
{
"id": "TANGEM SDK OLD",
"dataKey": {
"privateKey": "11121314151617184771ED81F2BACF57479E4735EB1405083927372D40DA9E92"
},
"transactionKey": {
"privateKey": "11121314151617184771ED81F2BACF57479E4735EB1405083927372D40DA9E92"
}
},
{
"id": "TANGEM",
"dataKey": {
@ -35,15 +26,6 @@
"publicKey": "04D292BFC802FFA70ABB1C094A19F6C6766DD353114C25415871BE4586129648CFD77B22FBC1AF3C612497732A04CF845B41D760AFDD820051AB250798503DB340"
}
},
{
"id": "Qlear BAP",
"dataKey": {
"publicKey": "046A9CA7B99B2D8C8CB3ECCC9F1F7667ED4D324F3B3A9A83CBA0FEA8D26038D3385DE95C095EC0A92623D2C123844C8DB0FE03B90A18CC01EB3730DC3C325690A1"
},
"transactionKey": {
"publicKey": "044C8A04CA3E0D0F42799D7E356A8EDB15C97627B3EF0FA5BBDF83B4298E816ACCDED2656347CB5C42CA994DFF8389BE801591C252065E426A369F98D7E96A5AAD"
}
},
{
"id": "Qlear Protocol",
"dataKey": {
@ -63,16 +45,75 @@
}
},
{
"id": "CARDANO",
"id": "Whirl",
"dataKey": {
"publicKey": "0445C312089E57A6952F96D74FF75C962E1E2C2DDA5FB4195661B92E2744791350FE6C60E1A1D145C6A34D8BEAD57506A90FE4A149A9AA43CFF3C6CAE0748B771E",
"privateKeyEncrypted": "2791FA18DFD4D2AD11509266C4721CE9BB4E9C7C8A06BF5071C6294EAB1F47A153CFDEBAF804425E5ED49AFEB70DD741"
"publicKey": "040B3484CB923DAB12915B7B4FC174543C242A4E49AD9046B2816F03DAFC344E7570CBCC245F5D82FAFDB7E413538238EDE2C196EEC2F9F91911AFC9C37F757810"
},
"transactionKey": {
"publicKey": "04969A008E8A61F92EF8D380DB7BB7B8F6F667CA169934371F544F6697D1D2AF97FB87B8D75F550CD782472D46BFCADF354AF17D807C1D2EB82E184C367CACF1FC",
"privateKeyEncrypted": "4707EEB8704D53EB1B6D905604C394D1514C205E3EC16423961BB82A7A47896783F8035BE56D6DAE5DE200E67F2D92E3"
"publicKey": "042EC0898ADF5AF4883D2F077E89CE464766E8E47FA03612F5248494C88A923CA2C444EE71D3A2BE67F13FD65C19E114B577F2B12CE856F1AA80DEBB406F325171"
}
},
{
"id": "D1",
"dataKey": {
"publicKey": "046F1155C3E75C2E0A4B816F53B739BA9DB3FC27C4CDE20E634AF09CA2D88A5199F97AE474B5833E69AD5A43FFB2F62E4E9B7A8BCC271805A5DD19A7AB9C9888D6"
},
"transactionKey": {
"publicKey": "04AE9E9C50073ABCF3219A96806BE8B95DCA97A12A0DE3516C25959266F5DFD032B75E1CC926DAAC274EE0E638A2BDB717C4B9C6F28808D6BEAB2F4CBF91E2DD52"
}
},
{
"id": "Coinstruction",
"dataKey": {
"publicKey": "042D6D305E2927FE18762CF2E74B207B3D7239279248450C31C88C4FEBDBC62D07976D10F7838CA52AF5A7ACB052D09EC8C513E7AC204673D2D3D078DBD859DF49"
},
"transactionKey": {
"publicKey": "045B0561BD9E089E54D730D75F5205A1A3E094A2209D0F11002F2423D63F508BFD161F8BBA8FBAC441AD893287D67141BBEE39E403C43D12A9FE1A25BCF3A144E9"
}
},
{
"id": "EvenToken",
"dataKey": {
"publicKey": "040FB60B37682AED10AB8B9DB324BBB10D7CEDF9D189332212C36A641CF81314E6CC8C219245DF04813DBB26931C547B6A4D55A10B5FFB163F54643A97213276F8"
},
"transactionKey": {
"publicKey": "044CEB1A3C2931F55441B39EB06F938542309DDD436DA486DE605187418163B777684C15D10EE5029CDEFB73DBA2BF90173D27CACEBF4CABFD4553C63021ABBEBB"
}
},
{
"id": "CARDANO",
"dataKey": {
"publicKey": "0445C312089E57A6952F96D74FF75C962E1E2C2DDA5FB4195661B92E2744791350FE6C60E1A1D145C6A34D8BEAD57506A90FE4A149A9AA43CFF3C6CAE0748B771E"
},
"transactionKey": {
"publicKey": "04969A008E8A61F92EF8D380DB7BB7B8F6F667CA169934371F544F6697D1D2AF97FB87B8D75F550CD782472D46BFCADF354AF17D807C1D2EB82E184C367CACF1FC"
}
},
{
"id": "RSK",
"dataKey": {
"publicKey": "04997C29B1158D5A5B7EDCF7A7844EA76C630C80CD326C83F2983C2EF0E632B37282D69CEEDB6445B79B26D73073122E22AB0FE1E9A1CA41D991C45057D9DF0F24"
},
"transactionKey": {
"publicKey": "040E9DDC53387F1006F39451AF11EBD377B98484FC81D24A96A55DEFDDF6F1EE35F07B089EFD05E4E93BDE20372171274ECD8D8805D0CB1FFEF012673F4E330C95"
}
},
{
"id": "DIGIX",
"dataKey": {
"publicKey": "049533C082D074ACC285E9B7E97F50F0883DF0308871232ED2370F19CA8993F01C5D4ABAF848949C7628D48F60F68DA3E5726A53C394619179D42D7F20D347001E"
},
"transactionKey": {
"publicKey": "04346D597CBE34A409C4CC77AED4DB2332D18C181DD6EB0A695FEA8672FF790B1C2518DF3A357484BB1EC89BCB1C3F2A962B2781DF094C8EE0F9C45D98BBA92610"
}
},
{
"id": "Start2Coin",
"dataKey": {
"publicKey": "043D21AFD0E20468F210547079819CB947031F4A31E591A4193E98DEE84AFB5976066CDD43F94820E0B5F82C063603B48C9A84B4C28C3B6DD9E54BB66A1C75036F"
},
"transactionKey": {
"publicKey": "0442C6413C81FCCF6FA18318ECEA270F7B7242E82863A9208253A85BEC394E5F58E6A12F9FE8A708BD05B73862C8833EB0634FF98E527277F625D4AB139B86AEAC"
}
}
]
]

View file

@ -3,6 +3,7 @@ package com.tangem.data.network;
import com.tangem.data.network.model.BlockcypherBody;
import com.tangem.data.network.model.BlockcypherResponse;
import com.tangem.data.network.model.BlockcypherFee;
import com.tangem.data.network.model.BlockcypherTx;
import retrofit2.Call;
import retrofit2.http.Body;
@ -19,6 +20,9 @@ public interface BlockcypherApi {
@GET(Server.ApiBlockcypher.Method.ADDRESS)
Call<BlockcypherResponse> blockcypherAddress(@Path("blockchain") String blockchain, @Path("network") String network, @Path("address") String address);
@GET(Server.ApiBlockcypher.Method.TXS)
Call<BlockcypherTx> blockcypherTxs(@Path("blockchain") String blockchain, @Path("network") String network, @Path("txHash") String txHash);
@Headers("Content-Type: application/json")
@POST(Server.ApiBlockcypher.Method.PUSH)
Call<BlockcypherResponse> blockcypherPush(@Path("blockchain") String blockchain, @Path("network") String network, @Body BlockcypherBody blockcypherBody, @Query("token") String token);

View file

@ -114,6 +114,7 @@ public class Server {
public static class Method {
static final String MAIN = URL_BLOCKCYPHER + V1_MAIN;
static final String ADDRESS = MAIN + "/addrs/{address}?unspentOnly=true&includeScript=true";
static final String TXS = MAIN + "/txs/{txHash}?includeHex=true";
static final String PUSH = MAIN + "/txs/push";
}
}

View file

@ -7,6 +7,7 @@ import com.tangem.data.Blockchain;
import com.tangem.data.network.model.BlockcypherBody;
import com.tangem.data.network.model.BlockcypherFee;
import com.tangem.data.network.model.BlockcypherResponse;
import com.tangem.data.network.model.BlockcypherTx;
import java.util.Random;
@ -20,6 +21,7 @@ public class ServerApiBlockcypher {
public static final String BLOCKCYPHER_ADDRESS = "blockcypher_address";
public static final String BLOCKCYPHER_FEE = "blockcypher_fee";
public static final String BLOCKCYPHER_TXS = "blockcypher_txs";
public static final String BLOCKCYPHER_SEND = "blockcypher_send";
private int requestsCount = 0;
@ -31,6 +33,8 @@ public class ServerApiBlockcypher {
private ResponseListener responseListener;
private TxResponseListener txResponseListener;
public interface ResponseListener {
void onSuccess(String method, BlockcypherResponse blockcypherResponse);
@ -39,10 +43,20 @@ public class ServerApiBlockcypher {
void onFail(String method, String message);
}
public interface TxResponseListener {
void onSuccess(BlockcypherTx blockcypherTx);
void onFail(String message);
}
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void setTxResponseListener(TxResponseListener txListener) {
txResponseListener = txListener;
}
public void requestData(String blockchainID, String method, String wallet, String tx) {
requestsCount++;
String blockchain = blockchainID.toLowerCase();
@ -60,8 +74,8 @@ public class ServerApiBlockcypher {
addressCall.enqueue(new Callback<BlockcypherResponse>() {
@Override
public void onResponse(@NonNull Call<BlockcypherResponse> call, @NonNull Response<BlockcypherResponse> response) {
requestsCount--;
if (response.code() == 200) {
requestsCount--;
responseListener.onSuccess(method, response.body());
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
} else {
@ -72,6 +86,7 @@ public class ServerApiBlockcypher {
@Override
public void onFailure(@NonNull Call<BlockcypherResponse> call, @NonNull Throwable t) {
requestsCount--;
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
@ -83,8 +98,8 @@ public class ServerApiBlockcypher {
feeCall.enqueue(new Callback<BlockcypherFee>() {
@Override
public void onResponse(@NonNull Call<BlockcypherFee> call, @NonNull Response<BlockcypherFee> response) {
requestsCount--;
if (response.code() == 200) {
requestsCount--;
responseListener.onSuccess(method, response.body());
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
} else {
@ -95,12 +110,37 @@ public class ServerApiBlockcypher {
@Override
public void onFailure(@NonNull Call<BlockcypherFee> call, @NonNull Throwable t) {
requestsCount--;
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
break;
case BLOCKCYPHER_TXS:
Call<BlockcypherTx> txsCall = blockcypherApi.blockcypherTxs(blockchain, network, tx);
txsCall.enqueue(new Callback<BlockcypherTx>() {
@Override
public void onResponse(@NonNull Call<BlockcypherTx> call,@NonNull Response<BlockcypherTx> response) {
requestsCount--;
if (response.code() == 200) {
txResponseListener.onSuccess(response.body());
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
} else {
txResponseListener.onFail(String.valueOf(response.code()));
Log.e(TAG, "requestData " + method + " onResponse " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<BlockcypherTx> call, @NonNull Throwable t) {
requestsCount--;
txResponseListener.onFail(String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
break;
case BLOCKCYPHER_SEND:
BlockcypherToken blockcypherToken = BlockcypherToken.values()[new Random().nextInt(BlockcypherToken.values().length)];
@ -108,8 +148,8 @@ public class ServerApiBlockcypher {
sendCall.enqueue(new Callback<BlockcypherResponse>() {
@Override
public void onResponse(@NonNull Call<BlockcypherResponse> call, @NonNull Response<BlockcypherResponse> response) {
requestsCount--;
if (response.code() == 201) {
requestsCount--;
responseListener.onSuccess(method, response.body());
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
} else {
@ -120,6 +160,7 @@ public class ServerApiBlockcypher {
@Override
public void onFailure(@NonNull Call<BlockcypherResponse> call, @NonNull Throwable t) {
requestsCount--;
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
@ -127,6 +168,7 @@ public class ServerApiBlockcypher {
break;
default:
requestsCount--;
responseListener.onFail(method, "undeclared method");
Log.e(TAG, "requestData " + method + " onFailure - undeclared method");
break;

View file

@ -13,8 +13,6 @@ import retrofit2.Response;
public class ServerApiSoChain {
public static String NETWORK_BTC = "BTC";
private static String TAG = ServerApiSoChain.class.getSimpleName();
private int requestsCount = 0;
@ -86,9 +84,9 @@ public class ServerApiSoChain {
call.enqueue(new Callback<SoChain.Response.AddressBalance>() {
@Override
public void onResponse(@NonNull Call<SoChain.Response.AddressBalance> call, @NonNull Response<SoChain.Response.AddressBalance> response) {
requestsCount--;
Log.i(TAG, "requestAddressBalance onResponse " + response.code());
if (response.code() == 200) {
requestsCount--;
addressInfoListener.onSuccess(response.body());
} else {
addressInfoListener.onFail(String.valueOf(response.code()));
@ -97,6 +95,7 @@ public class ServerApiSoChain {
@Override
public void onFailure(@NonNull Call<SoChain.Response.AddressBalance> call, @NonNull Throwable t) {
requestsCount--;
Log.e(TAG, "requestAddressBalance onFailure " + t.getMessage());
addressInfoListener.onFail(String.valueOf(t.getMessage()));
}
@ -111,9 +110,9 @@ public class ServerApiSoChain {
call.enqueue(new Callback<SoChain.Response.TxUnspent>() {
@Override
public void onResponse(@NonNull Call<SoChain.Response.TxUnspent> call, @NonNull Response<SoChain.Response.TxUnspent> response) {
requestsCount--;
Log.i(TAG, "requestAddressBalance onResponse " + response.code());
if (response.code() == 200) {
requestsCount--;
addressInfoListener.onSuccess(response.body());
} else {
addressInfoListener.onFail(String.valueOf(response.code()));
@ -122,6 +121,7 @@ public class ServerApiSoChain {
@Override
public void onFailure(@NonNull Call<SoChain.Response.TxUnspent> call, @NonNull Throwable t) {
requestsCount--;
Log.e(TAG, "requestAddressBalance onFailure " + t.getMessage());
addressInfoListener.onFail(String.valueOf(t.getMessage()));
}
@ -138,9 +138,9 @@ public class ServerApiSoChain {
call.enqueue(new Callback<SoChain.Response.SendTx>() {
@Override
public void onResponse(@NonNull Call<SoChain.Response.SendTx> call, @NonNull Response<SoChain.Response.SendTx> response) {
requestsCount--;
Log.i(TAG, "requestAddressBalance onResponse " + response.code());
if (response.code() == 200) {
requestsCount--;
sendTxListener.onSuccess(response.body());
} else {
sendTxListener.onFail(String.valueOf(response.code()));
@ -149,6 +149,7 @@ public class ServerApiSoChain {
@Override
public void onFailure(@NonNull Call<SoChain.Response.SendTx> call, @NonNull Throwable t) {
requestsCount--;
Log.e(TAG, "requestAddressBalance onFailure " + t.getMessage());
sendTxListener.onFail(String.valueOf(t.getMessage()));
}

View file

@ -138,7 +138,7 @@ public class ServerApiStellar {
});
}
private void doStellarRequest(TangemContext ctx, StellarRequest.Base stellarRequest) throws IOException {
public void doStellarRequest(TangemContext ctx, StellarRequest.Base stellarRequest) throws IOException {
stellarRequest.setError(null);
try {
Server server;

View file

@ -33,6 +33,11 @@ data class BlockcypherTxref(
var script: String? = null
)
data class BlockcypherTx(
@SerializedName("hex")
var hex: String? = null
)
data class BlockcypherFee(
@SerializedName("low_fee_per_kb")
var low_fee_per_kb: Long? = null,

View file

@ -267,8 +267,8 @@ public final class BCHUtils {
ArrayList<UnspentOutputInfo> unspentOutputs = new ArrayList<>();
for (BtcData.UnspentTransaction current : rawTxList) {
byte[] rawTxByte = BCHUtils.fromHex(current.Raw);
if (rawTxByte == null || current.Raw.isEmpty()) {
byte[] rawTxByte = BCHUtils.fromHex(current.script);
if (rawTxByte == null || current.script.isEmpty()) {
continue;
}

View file

@ -190,8 +190,8 @@ public final class BTCUtils {
ArrayList<UnspentOutputInfo> unspentOutputs = new ArrayList<>();
for (BtcData.UnspentTransaction current : rawTxList) {
byte[] rawTxByte = BTCUtils.fromHex(current.Raw);
if (rawTxByte == null || current.Raw.isEmpty()) {
byte[] rawTxByte = BTCUtils.fromHex(current.script);
if (rawTxByte == null || current.script.isEmpty()) {
continue;
}

View file

@ -209,8 +209,6 @@ public abstract class CoinEngine {
public abstract InputFilter[] getAmountInputFilters();
public abstract String getOfflineBalanceHTML();
public abstract String evaluateFeeEquivalent(String fee);
public abstract String getFeeCurrency();
@ -237,6 +235,16 @@ public abstract class CoinEngine {
public abstract String getUnspentInputsDescription();
public String getOfflineBalanceHTML() {
return "";
}
// public String getOfflineBalanceHTML() {
// InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
// Amount offlineAmount = convertToAmount(offlineInternalAmount);
// return offlineAmount.toDescriptionString(getDecimals());
// }
public void defineWallet() throws CardProtocol.TangemException {
try {
String wallet = calculateAddress(ctx.getCard().getWalletPublicKey());

View file

@ -89,13 +89,6 @@ public class BtcCashEngine extends CoinEngine {
return "BCH";
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;
@ -591,8 +584,8 @@ public class BtcCashEngine extends CoinEngine {
JSONObject jsUnspent = jsUnspentArray.getJSONObject(i);
BtcData.UnspentTransaction trUnspent = new BtcData.UnspentTransaction();
trUnspent.txID = jsUnspent.getString("tx_hash");
trUnspent.Amount = jsUnspent.getLong("value");
trUnspent.Height = jsUnspent.getInt("height");
trUnspent.amount = jsUnspent.getLong("value");
trUnspent.outputN = jsUnspent.getInt("height");
coinData.getUnspentTransactions().add(trUnspent);
}
} catch (JSONException e) {
@ -623,7 +616,7 @@ public class BtcCashEngine extends CoinEngine {
String raw = electrumRequest.getResultString();
for (BtcData.UnspentTransaction tx : coinData.getUnspentTransactions()) {
if (tx.txID.equals(txHash))
tx.Raw = raw;
tx.script = raw;
}
} catch (JSONException e) {
e.printStackTrace();

View file

@ -109,13 +109,6 @@ public class BinanceEngine extends CoinEngine {
return "BNB";
}
@Override
public String getOfflineBalanceHTML() { //TODO:check
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;

View file

@ -17,14 +17,16 @@ public class BtcData extends CoinData {
private Long balanceConfirmed, balanceUnconfirmed;
private boolean useBlockcypher = false;
public String getUnspentInputsDescription() {
try {
int gatheredUnspents = 0;
if( unspentTransactions==null ) return "";
for (int i = 0; i < unspentTransactions.size(); i++) {
if (unspentTransactions.get(i).Raw != null && unspentTransactions.get(i).Raw.length() > 1) gatheredUnspents++;
if (unspentTransactions.get(i).script != null && unspentTransactions.get(i).script.length() > 1) gatheredUnspents++;
}
return String.valueOf(unspentTransactions.size()) + " unspents (" + String.valueOf(gatheredUnspents) + " received)";
return unspentTransactions.size() + " unspents (" + gatheredUnspents + " received)";
}
catch (Exception e)
{
@ -35,24 +37,24 @@ public class BtcData extends CoinData {
public static class UnspentTransaction {
public String txID;
public Long Amount;
public Integer Height;
public String Raw = "";
public Long amount;
public Integer outputN;
public String script = "";
public Bundle getAsBundle() {
Bundle B = new Bundle();
B.putString("txID", txID);
B.putLong("Amount", Amount);
B.putInt("Height", Height);
B.putString("Raw", Raw);
B.putLong("Amount", amount);
B.putInt("OutputN", outputN);
B.putString("Script", script);
return B;
}
public void loadFromBundle(Bundle B) {
txID = B.getString("txID");
Amount = B.getLong("Amount");
Height = B.getInt("Height");
Raw = B.getString("Raw");
amount = B.getLong("Amount");
outputN = B.getInt("OutputN");
script = B.getString("Script");
}
}
@ -83,6 +85,7 @@ public class BtcData extends CoinData {
i++;
}
}
if (B.containsKey("UseBlockcypher")) useBlockcypher = B.getBoolean("UseBlockcypher");
}
@Override
@ -98,6 +101,7 @@ public class BtcData extends CoinData {
}
if (balanceConfirmed != null) B.putLong("BalanceConfirmed", balanceConfirmed);
if (balanceUnconfirmed != null) B.putLong("BalanceUnconfirmed", balanceUnconfirmed);
if (useBlockcypher) B.putBoolean("UseBlockcypher", true);
} catch (Exception e) {
Log.e("Can't save to bundle ", e.getMessage());
}
@ -131,4 +135,11 @@ public class BtcData extends CoinData {
return balanceConfirmed != null || balanceUnconfirmed != null;
}
public boolean isUseBlockcypher() {
return useBlockcypher;
}
public void setUseBlockcypher(boolean useBlockcypher) {
this.useBlockcypher = useBlockcypher;
}
}

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,7 @@ public class CardanoData extends CoinData {
// int gatheredUnspents = 0;
if( unspentOutputs ==null ) return "";
// for (int i = 0; i < unspentOutputs.size(); i++) {
// if (unspentOutputs.get(i).Raw != null && unspentOutputs.get(i).Raw.length() > 1) gatheredUnspents++;
// if (unspentOutputs.get(i).script != null && unspentOutputs.get(i).script.length() > 1) gatheredUnspents++;
// }
return String.valueOf(unspentOutputs.size()) + " unspents";// (" + String.valueOf(gatheredUnspents) + " received)";
}

View file

@ -103,13 +103,6 @@ public class CardanoEngine extends CoinEngine {
return "ADA";
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;

View file

@ -85,13 +85,6 @@ public class DucatusEngine extends BtcEngine {
return "LTC";
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;
@ -525,7 +518,7 @@ public class DucatusEngine extends BtcEngine {
String txHash = new String(BTCUtils.reverse(CryptoUtil.doubleSha256(BTCUtils.fromHex(raw)))); //TODO: check
for (BtcData.UnspentTransaction tx : coinData.getUnspentTransactions()) {
if (tx.txID.equals(txHash))
tx.Raw = raw;
tx.script = raw;
}
} catch (Exception e) {
e.printStackTrace();
@ -548,8 +541,8 @@ public class DucatusEngine extends BtcEngine {
for (InsightResponse utxo : utxoList) {
BtcData.UnspentTransaction trUnspent = new BtcData.UnspentTransaction();
trUnspent.txID = utxo.getTxid();
trUnspent.Amount = utxo.getSatoshis();
trUnspent.Height = utxo.getHeight();
trUnspent.amount = utxo.getSatoshis();
trUnspent.outputN = utxo.getHeight();
coinData.getUnspentTransactions().add(trUnspent);
}

View file

@ -115,13 +115,6 @@ public class EosEngine extends CoinEngine {
return Blockchain.Eos.getCurrency();
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;
@ -336,8 +329,8 @@ public class EosEngine extends CoinEngine {
// return address;
// byte[] csum = Ripemd160.from(pkCompressed).bytes();
// csum = Raw.copy(csum, 0, 4);
// byte[] addy = Raw.concat(pkCompressed, csum);
// csum = script.copy(csum, 0, 4);
// byte[] addy = script.concat(pkCompressed, csum);
// StringBuffer bf = new StringBuffer("EOS");
// bf.append(Base58.encode(addy));
// return bf.toString() + " " + address;

View file

@ -91,13 +91,6 @@ public class EthEngine extends CoinEngine {
return Blockchain.Ethereum.getCurrency();
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;

View file

@ -2,15 +2,11 @@ package com.tangem.wallet.ltc;
import android.net.Uri;
import android.text.InputFilter;
import android.util.Log;
import com.tangem.data.network.ElectrumRequest;
import com.tangem.data.network.ServerApiElectrum;
import com.tangem.wallet.BTCUtils;
import com.tangem.wallet.BalanceValidator;
import com.tangem.wallet.Base58;
import com.tangem.wallet.CoinData;
import com.tangem.wallet.CoinEngine;
import com.tangem.wallet.TangemContext;
import com.tangem.wallet.Transaction;
import com.tangem.wallet.UnspentOutputInfo;
@ -25,8 +21,6 @@ import com.tangem.util.DecimalDigitsInputFilter;
import com.tangem.util.DerEncodingUtil;
import com.tangem.wallet.R;
import org.json.JSONException;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -36,7 +30,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LtcEngine extends BtcEngine {
private static final String TAG = LtcEngine.class.getSimpleName();
@ -88,13 +81,6 @@ public class LtcEngine extends BtcEngine {
return "LTC";
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;
@ -402,7 +388,7 @@ public class LtcEngine extends BtcEngine {
byte[] pbKey = ctx.getCard().getWalletPublicKey();
for (BtcData.UnspentTransaction utxo : coinData.getUnspentTransactions()) {
unspentOutputs.add(new UnspentOutputInfo(BTCUtils.fromHex(utxo.txID), new Transaction.Script(BTCUtils.fromHex(utxo.Raw)), utxo.Amount, utxo.Height, -1, utxo.txID, null));
unspentOutputs.add(new UnspentOutputInfo(BTCUtils.fromHex(utxo.txID), new Transaction.Script(BTCUtils.fromHex(utxo.script)), utxo.amount, utxo.outputN, -1, utxo.txID, null));
}
long fullAmount = 0;

View file

@ -83,11 +83,6 @@ public class NftTokenEngine extends CoinEngine {
return new InputFilter[0];
}
@Override
public String getOfflineBalanceHTML() {
return ctx.getString(R.string.not_implemented);
}
protected String getContractAddress(TangemCard card) {
return card.getContractAddress();
}

View file

@ -138,11 +138,6 @@ public class TokenEngine extends CoinEngine {
return this.getBlockchain().getCurrency();
}
@Override
public String getOfflineBalanceHTML() {
return ctx.getString(R.string.not_implemented);
}
protected static int getChainDecimals() {
return 18;
}

View file

@ -1,6 +1,7 @@
package com.tangem.wallet.xlm;
import android.net.Uri;
import android.os.StrictMode;
import android.text.InputFilter;
import android.util.Log;
@ -18,7 +19,9 @@ import com.tangem.wallet.R;
import com.tangem.wallet.TangemContext;
import org.stellar.sdk.AssetTypeNative;
import org.stellar.sdk.CreateAccountOperation;
import org.stellar.sdk.KeyPair;
import org.stellar.sdk.Operation;
import org.stellar.sdk.PaymentOperation;
import org.stellar.sdk.Transaction;
import org.stellar.sdk.TransactionEx;
@ -85,13 +88,6 @@ public class XlmEngine extends CoinEngine {
return "XLM";
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;
@ -356,12 +352,22 @@ public class XlmEngine extends CoinEngine {
@Override
public SignTask.TransactionToSign constructTransaction(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) throws Exception {
checkBlockchainDataExists();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
if (IncFee) {
amountValue = new Amount(amountValue.subtract(feeValue), amountValue.getCurrency());
}
TransactionEx transaction = TransactionEx.buildEx(60, coinData.getAccountResponse(), new PaymentOperation.Builder(KeyPair.fromAccountId(targetAddress), new AssetTypeNative(), amountValue.toValueString()).build());
Operation operation;
if (isAccountCreated(targetAddress))
operation = new PaymentOperation.Builder(KeyPair.fromAccountId(targetAddress), new AssetTypeNative(), amountValue.toValueString()).build();
else
operation = new CreateAccountOperation.Builder(KeyPair.fromAccountId(targetAddress), amountValue.toValueString()).build();
TransactionEx transaction = TransactionEx.buildEx(60, coinData.getAccountResponse(), operation);
if (transaction.getFee() != convertToInternalAmount(feeValue).intValueExact()) {
throw new Exception("Invalid fee!");
@ -408,6 +414,26 @@ public class XlmEngine extends CoinEngine {
};
}
// network call inside, don't use on main thread
private boolean isAccountCreated(String address) {
final ServerApiStellar serverApi = new ServerApiStellar();
StellarRequest.Balance request = new StellarRequest.Balance(address);
try {
serverApi.doStellarRequest(ctx, request);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
return true; // suppose account is created if anything goes wrong TODO:check
}
if (request.errorResponse != null && request.errorResponse.getCode() == 404)
return false;
else
return true;
}
@Override
public void requestBalanceAndUnspentTransactions(BlockchainRequestsCallbacks blockchainRequestsCallbacks) {
final ServerApiStellar serverApi = new ServerApiStellar();
@ -539,6 +565,8 @@ public class XlmEngine extends CoinEngine {
return false;
}
public int pendingTransactionTimeoutInSeconds() { return 10; }
public int pendingTransactionTimeoutInSeconds() {
return 10;
}
}

View file

@ -63,8 +63,10 @@ public class XrpData extends CoinData {
public CoinEngine.InternalAmount getBalanceInInternalUnits() {
if (balanceUnconfirmed != null)
return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceUnconfirmed).subtract(BigDecimal.valueOf(reserve)), "Drops");
else
else if (balanceConfirmed != null)
return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceConfirmed).subtract(BigDecimal.valueOf(reserve)), "Drops");
else
return null;
}
// public Long getBalanceUnconfirmed() {

View file

@ -79,13 +79,6 @@ public class XrpEngine extends CoinEngine {
return "XRP";
}
@Override
public String getOfflineBalanceHTML() {
InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
Amount offlineAmount = convertToAmount(offlineInternalAmount);
return offlineAmount.toDescriptionString(getDecimals());
}
@Override
public boolean isBalanceNotZero() {
if (coinData == null) return false;

View file

@ -9,7 +9,8 @@ public enum Manufacturer {
Unknown("", "Unknown"),
SMARTCASH_AG("SMART CASH AG", "TANGEM AG"),
DEVELOPERS_SMARTCASH_AG("DEVELOP CASH AG", "TANGEM AG (DEVELOPERS)"),
SMARTCASH("SMART CASH", "TANGEM");
SMARTCASH("SMART CASH", "TANGEM"),
TANGEM("TANGEM", "TANGEM");
private String ID;
private String officialName;

View file

@ -49,7 +49,7 @@ class LocalStorage
artworks = HashMap()
}
if (artworks.count() < 23) {
if (artworks.count() < 28) {
// forceSave=true only on the last one
putResourceArtworkToCatalog(R.drawable.card_default, false)
putResourceArtworkToCatalog(R.drawable.card_default_nft, false)
@ -73,6 +73,11 @@ class LocalStorage
putResourceArtworkToCatalog(R.drawable.card_ru032, false)
putResourceArtworkToCatalog(R.drawable.card_ru037, false)
putResourceArtworkToCatalog(R.drawable.card_ru039, false)
putResourceArtworkToCatalog(R.drawable.card_ru040, false)
putResourceArtworkToCatalog(R.drawable.card_ru041, false)
putResourceArtworkToCatalog(R.drawable.card_ru042, false)
putResourceArtworkToCatalog(R.drawable.card_ru043, false)
putResourceArtworkToCatalog(R.drawable.card_tg044, false)
putResourceArtworkToCatalog(R.drawable.card_ff32, true)
}
if (batchesFile.exists()) {
@ -223,6 +228,10 @@ class LocalStorage
hexCID in "CB05000010000000".."CB05000010009999" -> R.drawable.card_ru006
//LTC and DGX
hexCID in "CB25000000000000".."CB25000000099999" -> R.drawable.card_ru043
hexCID in "CB26000000000000".."CB26000000099999" -> R.drawable.card_tg044
card.batch == "0004" -> R.drawable.card_ru006
card.batch == "0006" -> R.drawable.card_ru006
card.batch == "0010" -> R.drawable.card_ru006
@ -247,7 +256,12 @@ class LocalStorage
card.batch == "0021" -> R.drawable.card_ru031
card.batch == "0022" -> R.drawable.card_ru032
card.batch == "0025" -> R.drawable.card_ru037
card.batch == "0027" -> R.drawable.card_ru038
card.batch == "0030" -> R.drawable.card_ru038
card.batch == "0026" -> R.drawable.card_ru039
card.batch == "0028" -> R.drawable.card_ru040
card.batch == "0029" -> R.drawable.card_ru041
card.batch == "0031" -> R.drawable.card_ru042
card.batch == "FF32" -> R.drawable.card_ff32
else -> null

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB