Updated on 2026-08-14
This commit is contained in:
commit
44d76e0580
17 changed files with 166 additions and 37 deletions
7
.idea/dictionaries/.xml
generated
Normal file
7
.idea/dictionaries/.xml
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="Денис">
|
||||
<words>
|
||||
<w>blockchains</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(), "");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
server-android/src/main/res/drawable/card_tg073.png
Normal file
BIN
server-android/src/main/res/drawable/card_tg073.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
Loading…
Add table
Add a link
Reference in a new issue