Updated on 2026-08-14
This commit is contained in:
parent
fe277fc809
commit
7cc9d6abe4
5 changed files with 113 additions and 92 deletions
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.data.network;
|
||||
|
||||
public class ServerURL {
|
||||
public static final String API_TANGEM = "https://tangem-services.appspot.com/"; //TODO: "https://verify.tangem.com/";
|
||||
public static final String API_TANGEM = "https://verify.tangem.com/";
|
||||
public static final String API_COINMARKETCAP = "https://api.coinmarketcap.com/";
|
||||
public static final String API_INFURA = "https://mainnet.infura.io/";
|
||||
public static final String API_ESTIMATEFEE = " https://estimatefee.com/";
|
||||
|
|
|
|||
|
|
@ -468,15 +468,8 @@ public class CardProtocol {
|
|||
|
||||
// Hardcoded smart contracts for the cards manufactured before registration of smart-contract in ETH
|
||||
|
||||
if( mCard.getBatch().equals("0017") )
|
||||
{
|
||||
mCard.setContractAddress("0x9Eef75bA8e81340da9D8d1fd06B2f313DB88839c");
|
||||
}
|
||||
else if( mCard.getBatch().equals("0019") )
|
||||
{
|
||||
mCard.setContractAddress("0x0c056b0cda0763cc14b8b2d6c02465c91e33ec72");
|
||||
}
|
||||
else if (contractAddress != null)
|
||||
|
||||
if (contractAddress != null)
|
||||
{
|
||||
mCard.setContractAddress(contractAddress.getAsString());
|
||||
}
|
||||
|
|
@ -484,9 +477,6 @@ public class CardProtocol {
|
|||
if (tokens_decimal != null)
|
||||
mCard.setTokensDecimal(tokens_decimal.getAsInt());
|
||||
|
||||
// this method has reflection TokenSymbol
|
||||
// you mast call setBlockchainIDFromCard after calling setTokensDecimal
|
||||
mCard.setBlockchainIDFromCard(tlvCardData.getTLV(TLV.Tag.TAG_Blockchain_ID).getAsString());
|
||||
byte[] tlvPersonalizationDT = tlvCardData.getTLV(TLV.Tag.TAG_ManufactureDateTime).Value;
|
||||
int year = (tlvPersonalizationDT[0] & 0xFF) << 8 | (tlvPersonalizationDT[1] & 0xFF);
|
||||
int month = tlvPersonalizationDT[2] - 1;
|
||||
|
|
@ -525,15 +515,28 @@ public class CardProtocol {
|
|||
}
|
||||
|
||||
// substitutions for card, that was produced with wrong blockchain data (for example token contract was unknown)
|
||||
// this method must be called after set issuer because substitution is verified by issuer data key
|
||||
try {
|
||||
LocalStorage localStorage = new LocalStorage(mContext);
|
||||
localStorage.applySubstitution(mCard);
|
||||
// if( mCard.getBatch().equals("0017") )
|
||||
// {
|
||||
// mCard.setContractAddress("0x9Eef75bA8e81340da9D8d1fd06B2f313DB88839c");
|
||||
// }
|
||||
// else if( mCard.getBatch().equals("0019") )
|
||||
// {
|
||||
// mCard.setContractAddress("0x0c056b0cda0763cc14b8b2d6c02465c91e33ec72");
|
||||
// }else {
|
||||
LocalStorage localStorage = new LocalStorage(mContext);
|
||||
localStorage.applySubstitution(mCard);
|
||||
// }
|
||||
}catch(Exception e)
|
||||
{
|
||||
Log.e(logTag, "Can't apply card data substitution");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// this method has reflection TokenSymbol
|
||||
// you mast call setBlockchainIDFromCard after calling setTokensXXX and make substitutions
|
||||
mCard.setBlockchainIDFromCard(tlvCardData.getTLV(TLV.Tag.TAG_Blockchain_ID).getAsString());
|
||||
|
||||
try {
|
||||
mCard.setSettingsMask(readResult.getTagAsInt(TLV.Tag.TAG_SettingsMask));
|
||||
|
|
|
|||
|
|
@ -169,7 +169,8 @@ public class TLV {
|
|||
}
|
||||
|
||||
public String getAsString() {
|
||||
//String s=String.valueOf(Value);
|
||||
if( Value.length==0 ) return "";
|
||||
|
||||
if (Value[Value.length - 1] == 0) {
|
||||
String s1 = new String(Arrays.copyOfRange(Value, 0, Value.length - 1), Charset.forName("utf-8"));
|
||||
return s1.trim();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import java.lang.Exception
|
|||
import java.nio.charset.StandardCharsets
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
data class LocalStorage(
|
||||
val context: Context
|
||||
) {
|
||||
|
|
@ -36,9 +35,17 @@ data class LocalStorage(
|
|||
cacheDir!!.mkdirs()
|
||||
|
||||
if (artworksFile.exists()) {
|
||||
artworksFile.bufferedReader().use { artworks = Gson().fromJson(it, object : TypeToken<HashMap<String, ArtworkInfo>>() {}.type) }
|
||||
try {
|
||||
artworksFile.bufferedReader().use { artworks = Gson().fromJson(it, object : TypeToken<HashMap<String, ArtworkInfo>>() {}.type) }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
artworks = HashMap()
|
||||
}
|
||||
} else {
|
||||
artworks = HashMap()
|
||||
}
|
||||
|
||||
if (artworks.count() == 0) {
|
||||
putResourceArtworkToCatalog(R.drawable.card_default, false)
|
||||
putResourceArtworkToCatalog(R.drawable.card_ru006, false)
|
||||
putResourceArtworkToCatalog(R.drawable.card_ru007, false)
|
||||
|
|
@ -54,30 +61,37 @@ data class LocalStorage(
|
|||
putResourceArtworkToCatalog(R.drawable.card_ru023, true)
|
||||
}
|
||||
if (batchesFile.exists()) {
|
||||
batchesFile.bufferedReader().use { batches = Gson().fromJson(it, object : TypeToken<HashMap<String, BatchInfo>>() {}.type) }
|
||||
try {
|
||||
batchesFile.bufferedReader().use { batches = Gson().fromJson(it, object : TypeToken<HashMap<String, BatchInfo>>() {}.type) }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
batches = HashMap()
|
||||
}
|
||||
} else {
|
||||
batches = HashMap()
|
||||
|
||||
putBatchToCatalog("0004", R.drawable.card_ru006, false)
|
||||
putBatchToCatalog("0006", R.drawable.card_ru006, false)
|
||||
putBatchToCatalog("0010", R.drawable.card_ru006, false)
|
||||
|
||||
putBatchToCatalog("0005", R.drawable.card_ru007, false)
|
||||
putBatchToCatalog("0007", R.drawable.card_ru007, false)
|
||||
putBatchToCatalog("0011", R.drawable.card_ru007, false)
|
||||
|
||||
putBatchToCatalog("0012", R.drawable.card_ru011, false)
|
||||
putBatchToCatalog("0013", R.drawable.card_ru012, false)
|
||||
putBatchToCatalog("0014", R.drawable.card_ru006, false)
|
||||
putBatchToCatalog("0015", R.drawable.card_ru020, false)
|
||||
putBatchToCatalog("0016", R.drawable.card_ru021, false)
|
||||
putBatchToCatalog("0017", R.drawable.card_ru013, false)
|
||||
putBatchToCatalog("0019", R.drawable.card_ru016, false)
|
||||
putBatchToCatalog("001A", R.drawable.card_ru014, false)
|
||||
putBatchToCatalog("001B", R.drawable.card_ru015, false)
|
||||
putBatchToCatalog("001C", R.drawable.card_ru023, false)
|
||||
putBatchToCatalog("001D", R.drawable.card_ru022, true)
|
||||
}
|
||||
|
||||
// if (batches.count() == 0) {
|
||||
// putBatchToCatalog("0004", R.drawable.card_ru006, false)
|
||||
// putBatchToCatalog("0006", R.drawable.card_ru006, false)
|
||||
// putBatchToCatalog("0010", R.drawable.card_ru006, false)
|
||||
//
|
||||
// putBatchToCatalog("0005", R.drawable.card_ru007, false)
|
||||
// putBatchToCatalog("0007", R.drawable.card_ru007, false)
|
||||
// putBatchToCatalog("0011", R.drawable.card_ru007, false)
|
||||
//
|
||||
// putBatchToCatalog("0012", R.drawable.card_ru011, false)
|
||||
// putBatchToCatalog("0013", R.drawable.card_ru012, false)
|
||||
// putBatchToCatalog("0014", R.drawable.card_ru006, false)
|
||||
// putBatchToCatalog("0015", R.drawable.card_ru020, false)
|
||||
// putBatchToCatalog("0016", R.drawable.card_ru021, false)
|
||||
// putBatchToCatalog("0017", R.drawable.card_ru013, false)
|
||||
// putBatchToCatalog("0019", R.drawable.card_ru016, false)
|
||||
// putBatchToCatalog("001A", R.drawable.card_ru014, false)
|
||||
// putBatchToCatalog("001B", R.drawable.card_ru015, false)
|
||||
// putBatchToCatalog("001C", R.drawable.card_ru023, false)
|
||||
// putBatchToCatalog("001D", R.drawable.card_ru022, true)
|
||||
// }
|
||||
}
|
||||
|
||||
private fun getArtworkFile(artworkId: String): File {
|
||||
|
|
@ -111,7 +125,7 @@ data class LocalStorage(
|
|||
fun checkBatchInfoChanged(card: TangemCard, result: CardVerifyAndGetInfo.Response.Item): Boolean {
|
||||
var sData: String? = result.substitution?.data
|
||||
var sSignature: String? = result.substitution?.signature
|
||||
if( card.batch!=result.batch ) {
|
||||
if (card.batch != result.batch) {
|
||||
Log.e("LocalStorage", "Invalid batch received!")
|
||||
return false
|
||||
}
|
||||
|
|
@ -133,9 +147,9 @@ data class LocalStorage(
|
|||
putArtworkToCatalog(artworkId, false, data, updateDate, true)
|
||||
}
|
||||
|
||||
private fun putBatchToCatalog(batch: String, resourceId: Int, forceSave: Boolean = true) {
|
||||
putBatchToCatalog(batch, context.resources.getResourceEntryName(resourceId), null, null, forceSave)
|
||||
}
|
||||
// private fun putBatchToCatalog(batch: String, resourceId: Int, forceSave: Boolean = true) {
|
||||
// putBatchToCatalog(batch, context.resources.getResourceEntryName(resourceId), null, null, forceSave)
|
||||
// }
|
||||
|
||||
private fun putBatchToCatalog(batch: String, artworkId: String?, substitution: String?, substitutionSignature: String?, forceSave: Boolean = true) {
|
||||
batches[batch] = BatchInfo(artworkId, substitution, substitutionSignature)
|
||||
|
|
@ -162,7 +176,7 @@ data class LocalStorage(
|
|||
}
|
||||
|
||||
private fun getArtworkBitmap(artworkId: String): Bitmap? {
|
||||
if( artworkId.isBlank() ) return null
|
||||
if (artworkId.isBlank()) return null
|
||||
val info = artworks[artworkId.toLowerCase()] ?: return null
|
||||
return if (info.isResource) {
|
||||
val resID = context.resources.getIdentifier(artworkId, "drawable", context.packageName)
|
||||
|
|
@ -186,54 +200,52 @@ data class LocalStorage(
|
|||
|
||||
fun getCardArtworkBitmap(card: TangemCard): Bitmap {
|
||||
// special cases (first series of cards, hardcode CID->artwork), on new series batch<->artwork
|
||||
val artworkId =
|
||||
when (card.cidDescription) {
|
||||
in "AA01 0000 0000 0000".."AA01 0000 0000 4999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru006)
|
||||
}
|
||||
in "AA01 0000 0000 5000".."AA01 0000 0000 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru007)
|
||||
}
|
||||
val hexCID = Util.bytesToHex(card.cid)
|
||||
val artworkResourceId: Int? = when {
|
||||
hexCID in "AA01000000000000".."AA0100000000 4999" -> R.drawable.card_ru006
|
||||
hexCID in "AA01000000005000".."AA0100000000 9999" -> R.drawable.card_ru007
|
||||
|
||||
in "AE01 0000 0000 0000".."AE01 0000 0000 4999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru006)
|
||||
}
|
||||
in "AE01 0000 0000 5000".."AE01 0000 0000 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru007)
|
||||
}
|
||||
hexCID in "AE01000000000000".."AE010000 0000 4999" -> R.drawable.card_ru006
|
||||
hexCID in "AE01000000005000".."AE010000 0000 9999" -> R.drawable.card_ru007
|
||||
|
||||
in "CB01 0000 0000 0000".."CB01 0000 0000 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru006)
|
||||
}
|
||||
in "CB01 0000 0001 0000".."CB01 0000 0001 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru007)
|
||||
}
|
||||
hexCID in "CB01000000000000".."CB010000 0000 9999" -> R.drawable.card_ru006
|
||||
hexCID in "CB01000000010000".."CB010000 0001 9999" -> R.drawable.card_ru007
|
||||
|
||||
in "CB01 0000 0002 0000".."CB01 0000 0003 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru006)
|
||||
}
|
||||
in "CB01 0000 0004 0000".."CB01 0000 0005 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru007)
|
||||
}
|
||||
hexCID in "CB01000000020000".."CB010000 0003 9999" -> R.drawable.card_ru006
|
||||
hexCID in "CB01000000040000".."CB010000 0005 9999" -> R.drawable.card_ru007
|
||||
|
||||
in "CB02 0000 0000 0000".."CB02 0000 0002 4999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru006)
|
||||
}
|
||||
in "CB02 0000 0002 5000".."CB02 0000 0004 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru007)
|
||||
}
|
||||
hexCID in "CB02000000000000".."CB020000 0002 4999" -> R.drawable.card_ru006
|
||||
hexCID in "CB02000000025000".."CB020000 0004 9999" -> R.drawable.card_ru007
|
||||
|
||||
in "CB05 0000 1000 0000".."CB05 0000 1000 9999" -> {
|
||||
context.resources.getResourceEntryName(R.drawable.card_ru006)
|
||||
}
|
||||
hexCID in "CB05000010000000".."CB050000 1000 9999" -> R.drawable.card_ru006
|
||||
|
||||
else -> {
|
||||
val batchInfo = batches[card.batch] ?: return getDefaultArtworkBitmap()
|
||||
batchInfo.artworkId
|
||||
}
|
||||
} ?: return getDefaultArtworkBitmap()
|
||||
// if (artworkId.contains('/'))
|
||||
// artworkId = artworkId.split('/').last()
|
||||
card.batch == "0004" -> R.drawable.card_ru006
|
||||
card.batch == "0006" -> R.drawable.card_ru006
|
||||
card.batch == "0010" -> R.drawable.card_ru006
|
||||
card.batch == "0005" -> R.drawable.card_ru007
|
||||
card.batch == "0007" -> R.drawable.card_ru007
|
||||
card.batch == "0011" -> R.drawable.card_ru007
|
||||
card.batch == "0012" -> R.drawable.card_ru011
|
||||
card.batch == "0013" -> R.drawable.card_ru012
|
||||
card.batch == "0014" -> R.drawable.card_ru006
|
||||
card.batch == "0015" -> R.drawable.card_ru020
|
||||
card.batch == "0016" -> R.drawable.card_ru021
|
||||
card.batch == "0017" -> R.drawable.card_ru013
|
||||
card.batch == "0019" -> R.drawable.card_ru016
|
||||
card.batch == "001A" -> R.drawable.card_ru014
|
||||
card.batch == "001B" -> R.drawable.card_ru015
|
||||
card.batch == "001C" -> R.drawable.card_ru023
|
||||
card.batch == "001D" -> R.drawable.card_ru022
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (artworkResourceId != null) {
|
||||
val artworkId = context.resources.getResourceEntryName(artworkResourceId)
|
||||
return getArtworkBitmap(artworkId) ?: return getDefaultArtworkBitmap()
|
||||
}
|
||||
val batchInfo = batches[card.batch] ?: return getDefaultArtworkBitmap()
|
||||
val artworkId = batchInfo.artworkId ?: return getDefaultArtworkBitmap()
|
||||
return getArtworkBitmap(artworkId) ?: return getDefaultArtworkBitmap()
|
||||
}
|
||||
|
||||
|
|
@ -243,13 +255,13 @@ data class LocalStorage(
|
|||
substitution.applyToCard(card)
|
||||
}
|
||||
|
||||
data class ArtworkInfo(
|
||||
private data class ArtworkInfo(
|
||||
val isResource: Boolean,
|
||||
val hash: String,
|
||||
val updateDate: Instant?
|
||||
)
|
||||
|
||||
data class BatchInfo(
|
||||
private data class BatchInfo(
|
||||
val artworkId: String?,
|
||||
val dataSubstitution: String?,
|
||||
val dataSubstitutionSignature: String?
|
||||
|
|
@ -272,9 +284,9 @@ data class LocalStorage(
|
|||
private val contractAddress: String?
|
||||
) {
|
||||
fun applyToCard(card: TangemCard) {
|
||||
if (card.tokenSymbol.isNullOrBlank()) card.tokenSymbol = tokenSymbol
|
||||
if (tokenDecimal != null) card.tokensDecimal = tokenDecimal
|
||||
if (card.contractAddress.isNullOrBlank()) card.contractAddress = contractAddress
|
||||
if (tokenSymbol != null && card.tokenSymbol.isNullOrBlank()) card.tokenSymbol = tokenSymbol
|
||||
if (tokenDecimal != null && card.tokensDecimal == 0) card.tokensDecimal = tokenDecimal
|
||||
if (contractAddress != null && card.contractAddress.isNullOrBlank()) card.contractAddress = contractAddress
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -240,11 +240,16 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
Log.w(TAG, "Batch ${result.batch} info changed to '$result'")
|
||||
ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!))
|
||||
localStorage.applySubstitution(card!!)
|
||||
if (card!!.blockchain == Blockchain.Token || card!!.blockchain == Blockchain.Ethereum) {
|
||||
//TODO: change this very bad code - it need because we have switch to token from ethereum if token symbol specified
|
||||
card!!.setBlockchainIDFromCard(Blockchain.Ethereum.id)
|
||||
}
|
||||
updateViews()
|
||||
}
|
||||
if (result.artwork!=null && localStorage.checkNeedUpdateArtwork(result.artwork)) {
|
||||
if (result.artwork != null && localStorage.checkNeedUpdateArtwork(result.artwork)) {
|
||||
Log.w(TAG, "Artwork '${result.artwork!!.id}' updated, need download")
|
||||
serverApiHelper!!.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), card!!)
|
||||
refresh()
|
||||
}
|
||||
// Log.i(TAG, "setCardVerify " + it.results!![0].passed)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue