Updated on 2026-08-14

This commit is contained in:
Tangem 2020-07-30 17:42:41 +03:00
commit 44d76e0580
17 changed files with 166 additions and 37 deletions

7
.idea/dictionaries/.xml generated Normal file
View file

@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="Денис">
<words>
<w>blockchains</w>
</words>
</dictionary>
</component>

View file

@ -679,8 +679,12 @@ public class BtcCashEngine extends CoinEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}

View file

@ -11,7 +11,10 @@ import com.tangem.data.Blockchain;
import com.tangem.data.network.BinanceApi;
import com.tangem.data.network.Server;
import com.tangem.data.network.ServerApiBinance;
import com.tangem.data.network.ServerApiPayId;
import com.tangem.data.network.model.BinanceFees;
import com.tangem.data.network.model.PayIdAddress;
import com.tangem.data.network.model.PayIdResponse;
import com.tangem.tangem_card.data.TangemCard;
import com.tangem.tangem_card.reader.CardProtocol;
import com.tangem.tangem_card.tasks.SignTask;
@ -44,6 +47,10 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import io.reactivex.CompletableObserver;
import io.reactivex.SingleObserver;
import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.observers.DisposableSingleObserver;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@ -154,6 +161,10 @@ public class BinanceAssetEngine extends CoinEngine {
return false;
}
if (address.contains("$")) { // PayID
return validatePayId(address);
}
try {
Crypto.decodeAddress(address);
} catch (Exception e) {
@ -380,6 +391,14 @@ public class BinanceAssetEngine extends CoinEngine {
public SignTask.TransactionToSign constructTransaction(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) throws Exception {
checkBlockchainDataExists();
String destination;
//PayID
if (coinData.getResolvedPayIdAddress() != null) {
destination = coinData.getResolvedPayIdAddress();
} else {
destination = targetAddress;
}
String amount;
if (IncFee && amountValue.getCurrency().equals(getFeeCurrency())) { //Coin transfer only
@ -398,7 +417,7 @@ public class BinanceAssetEngine extends CoinEngine {
Transfer transfer = new Transfer();
transfer.setCoin(amountValue.getCurrency().equals(getFeeCurrency()) ? getFeeCurrency() : ctx.getCard().getContractAddress());
transfer.setFromAddress(ctx.getCoinData().getWallet());
transfer.setToAddress(targetAddress);
transfer.setToAddress(destination);
transfer.setAmount(amount);
TransactionOption options = TransactionOption.DEFAULT_INSTANCE;
@ -490,6 +509,27 @@ public class BinanceAssetEngine extends CoinEngine {
}
public void requestFee(BlockchainRequestsCallbacks blockchainRequestsCallbacks, String targetAddress, Amount amount) {
CompletableObserver payIdObserver = new DisposableCompletableObserver() {
@Override
public void onComplete() {
checkFee(blockchainRequestsCallbacks);
}
@Override
public void onError(Throwable e) {
ctx.setError(e.getMessage());
blockchainRequestsCallbacks.onComplete(false);
}
};
if (targetAddress.contains("$")) { // PayID
resolvePayID(targetAddress, payIdObserver);
} else {
checkFee(blockchainRequestsCallbacks);
}
}
private void checkFee(BlockchainRequestsCallbacks blockchainRequestsCallbacks) {
try {
String baseUrl = Server.ApiBinance.Method.API_V1;
@ -535,6 +575,46 @@ public class BinanceAssetEngine extends CoinEngine {
}
}
private void resolvePayID(String targetAddress, CompletableObserver observer) {
final ServerApiPayId serverApiPayId = new ServerApiPayId();
SingleObserver<PayIdResponse> payIdObserver = new DisposableSingleObserver<PayIdResponse>() {
@Override
public void onSuccess(PayIdResponse payIdResponse) {
try {
String resolvedAddress = null;
for (PayIdAddress address : payIdResponse.getAddresses()) {
if (address.getPaymentNetwork().equals(ctx.getBlockchain().getCurrency()) &&
address.getEnvironment().equals("MAINNET")) {
resolvedAddress = address.getAddressDetails().getAddress();
break;
}
}
if (validateAddress(resolvedAddress)) {
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}
} catch (Exception e) {
observer.onError(new Exception("Unknown response format on PayID request"));
}
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onFail: " + "payID" + " " + e.getMessage());
observer.onError(new Exception("PayID error:" + e.getMessage()));
}
};
serverApiPayId.getAddress(targetAddress, ctx.getBlockchain(), payIdObserver);
}
public void requestSendTransaction(BlockchainRequestsCallbacks blockchainRequestsCallbacks, byte[] txForSend) {
// RequestBody requestBody = TransactionRequestAssemblerExtSign.createRequestBody(txForSend);
try {

View file

@ -575,8 +575,12 @@ public class BinanceEngine extends CoinEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}

View file

@ -1087,11 +1087,11 @@ public class BtcEngine extends CoinEngine {
}
}
if (validateAddress(resolvedAddress)) {
if (resolvedAddress.equals(coinData.getWallet())) {
observer.onError(new Exception(ctx.getString(R.string.prepare_transaction_error_same_address)));
} else {
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));

View file

@ -9,7 +9,6 @@ import com.tangem.App;
import com.tangem.Constant;
import com.tangem.data.local.PendingTransactionsStorage;
import com.tangem.data.network.ServerApiAdalite;
import com.tangem.data.network.ServerApiBlockcypher;
import com.tangem.data.network.ServerApiPayId;
import com.tangem.data.network.model.AdaliteResponse;
import com.tangem.data.network.model.AdaliteResponseUtxo;
@ -776,8 +775,12 @@ public class CardanoEngine extends CoinEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}
@ -817,15 +820,8 @@ public class CardanoEngine extends CoinEngine {
@Override
public void onSuccess(String method, String stringResponse) {
if (method.equals(ServerApiAdalite.ADALITE_SEND)) {
if (stringResponse.equals("\"Transaction sent successfully!\"")) {
ctx.setError(null);
blockchainRequestsCallbacks.onComplete(true);
} else { // TODO: Make check for a valid send response
ctx.setError(stringResponse);
blockchainRequestsCallbacks.onComplete(false);
}
}
ctx.setError(null);
blockchainRequestsCallbacks.onComplete(true);
}

View file

@ -604,8 +604,12 @@ public class DucatusEngine extends BtcEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}

View file

@ -674,7 +674,7 @@ public class EthEngine extends CoinEngine {
}
if (validateAddress(resolvedAddress)) {
if (resolvedAddress.equals(coinData.getWallet())) {
ctx.setError(R.string.prepare_transaction_error_same_address);
ctx.setError("Resolved PayID address equals source address");
blockchainRequestsCallbacks.onComplete(false);
} else {
coinData.setResolvedPayIdAddress(resolvedAddress);

View file

@ -758,8 +758,12 @@ public class LtcEngine extends BtcEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}

View file

@ -200,7 +200,17 @@ public class RskEngine extends EthEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
if (resolvedAddress.equals(coinData.getWallet())) {
ctx.setError("Resolved PayID address equals source address");
blockchainRequestsCallbacks.onComplete(false);
} else {
coinData.setResolvedPayIdAddress(resolvedAddress);
if (serverApiRootstock.isRequestsSequenceCompleted() && serverApiPayId.isRequestsSequenceCompleted()) {
blockchainRequestsCallbacks.onComplete(!ctx.hasError());
} else {
blockchainRequestsCallbacks.onProgress();
}
}
} else {
ctx.setError("Unknown address format in PayID response");
blockchainRequestsCallbacks.onComplete(false);

View file

@ -231,7 +231,17 @@ public class RskTokenEngine extends TokenEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
if (resolvedAddress.equals(coinData.getWallet())) {
ctx.setError("Resolved PayID address equals source address");
blockchainRequestsCallbacks.onComplete(false);
} else {
coinData.setResolvedPayIdAddress(resolvedAddress);
if (serverApiRootstock.isRequestsSequenceCompleted() && serverApiPayId.isRequestsSequenceCompleted()) {
blockchainRequestsCallbacks.onComplete(!ctx.hasError());
} else {
blockchainRequestsCallbacks.onProgress();
}
}
} else {
ctx.setError("Unknown address format in PayID response");
blockchainRequestsCallbacks.onComplete(false);

View file

@ -877,7 +877,7 @@ public class TokenEngine extends CoinEngine {
}
if (validateAddress(resolvedAddress)) {
if (resolvedAddress.equals(coinData.getWallet())) {
ctx.setError(R.string.prepare_transaction_error_same_address);
ctx.setError("Resolved PayID address equals source address");
blockchainRequestsCallbacks.onComplete(false);
} else {
coinData.setResolvedPayIdAddress(resolvedAddress);

View file

@ -589,7 +589,7 @@ public class XlmAssetEngine extends CoinEngine {
CompletableObserver payIdObserver = new DisposableCompletableObserver() {
@Override
public void onComplete() {
checkTargetAccountCreated(blockchainRequestsCallbacks, targetAddress, amount);
checkTargetAccountCreated(blockchainRequestsCallbacks, coinData.getResolvedPayIdAddress(), amount);
}
@Override
@ -622,8 +622,12 @@ public class XlmAssetEngine extends CoinEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}

View file

@ -565,7 +565,7 @@ public class XlmEngine extends CoinEngine {
CompletableObserver payIdObserver = new DisposableCompletableObserver() {
@Override
public void onComplete() {
checkTargetAccountCreated(blockchainRequestsCallbacks, targetAddress, amount);
checkTargetAccountCreated(blockchainRequestsCallbacks, coinData.getResolvedPayIdAddress(), amount);
}
@Override
@ -598,8 +598,12 @@ public class XlmEngine extends CoinEngine {
}
}
if (validateAddress(resolvedAddress)) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
if (!resolvedAddress.equals(coinData.getWallet())) {
coinData.setResolvedPayIdAddress(resolvedAddress);
observer.onComplete();
} else {
observer.onError(new Exception("Resolved PayID address equals source address"));
}
} else {
observer.onError(new Exception("Unknown address format in PayID response"));
}

View file

@ -635,14 +635,14 @@ public class XrpEngine extends CoinEngine {
XrpXAddressDecoded xAddressDecoded = XrpXAddressService.Companion.decode(resolvedAddress);
if (xAddressDecoded == null) { // classic address
if (resolvedAddress.equals(coinData.getWallet())) {
ctx.setError(R.string.prepare_transaction_error_same_address);
ctx.setError("Resolved PayID address equals source address");
blockchainRequestsCallbacks.onComplete(false);
} else {
serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, resolvedAddress, "");
}
} else { // X-address
if (xAddressDecoded.getAddress().equals(coinData.getWallet())) {
ctx.setError(R.string.prepare_transaction_error_same_address);
ctx.setError("Resolved PayID address equals source address");
blockchainRequestsCallbacks.onComplete(false);
} else {
serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, xAddressDecoded.getAddress(), "");

View file

@ -47,7 +47,7 @@ class LocalStorage
artworks = HashMap()
}
if (artworks.count() < 44) {
if (artworks.count() < 45) {
// forceSave=true only on the last one
putResourceArtworkToCatalog(R.drawable.card_default, false)
putResourceArtworkToCatalog(R.drawable.card_default_nft, false)
@ -90,6 +90,7 @@ class LocalStorage
putResourceArtworkToCatalog(R.drawable.card_tg061, false)
putResourceArtworkToCatalog(R.drawable.card_tg062, false)
putResourceArtworkToCatalog(R.drawable.card_tg063, false)
putResourceArtworkToCatalog(R.drawable.card_tg073, false)
putResourceArtworkToCatalog(R.drawable.card_tgslix, false)
putResourceArtworkToCatalog(R.drawable.card_bc00, false)
putResourceArtworkToCatalog(R.drawable.card_ff32, true)
@ -305,6 +306,7 @@ class LocalStorage
card.batch == "0050" -> R.drawable.card_tg061
card.batch == "0051" -> R.drawable.card_tg062
card.batch == "0052" -> R.drawable.card_tg063
card.batch == "0060" -> R.drawable.card_tg073
card.batch == "FF32" -> R.drawable.card_ff32
else -> null

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB