Updated on 2026-08-14
This commit is contained in:
commit
769944959e
48 changed files with 24963 additions and 587 deletions
|
|
@ -138,7 +138,7 @@ dependencies {
|
|||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
|
||||
|
||||
//dependencies for binance
|
||||
implementation 'com.google.protobuf:protobuf-java:3.6.1'
|
||||
implementation 'com.google.protobuf:protobuf-java:3.11.4'
|
||||
implementation 'io.grpc:grpc-protobuf:1.17.1'
|
||||
implementation 'io.grpc:grpc-stub:1.17.1'
|
||||
implementation 'commons-codec:commons-codec:1.10'
|
||||
|
|
@ -154,4 +154,8 @@ dependencies {
|
|||
|
||||
implementation 'io.fotoapparat:fotoapparat:2.6.1'
|
||||
implementation 'com.otaliastudios:cameraview:2.6.1'
|
||||
|
||||
//dependencies for flow demo
|
||||
implementation 'io.grpc:grpc-okhttp:1.28.0'
|
||||
implementation 'io.grpc:grpc-stub:1.28.0'
|
||||
}
|
||||
|
|
@ -31,7 +31,8 @@ public enum Blockchain {
|
|||
StellarTag("XLM-Tag", "XLM", 1000000.0, R.drawable.ic_logo_stellar, "Stellar"),
|
||||
Eos("EOS", "EOS", 10000.0, R.drawable.tangem2, "EOS"),
|
||||
Ducatus("DUC", "DUC", 100000000.0, R.drawable.tangem2, "Ducatus"),
|
||||
Tezos("TEZOS", "XTZ", 10000000.0, R.drawable.ic_logo_tezos, "Tezos");
|
||||
Tezos("TEZOS", "XTZ", 10000000.0, R.drawable.ic_logo_tezos, "Tezos"),
|
||||
FlowDemo("FLOW/demo", "", 1.0, R.drawable.tangem2, "Flow demo");
|
||||
|
||||
Blockchain(String ID, String currency, double multiplier, int imageResource, String officialName) {
|
||||
mID = ID;
|
||||
|
|
|
|||
|
|
@ -58,11 +58,17 @@ abstract class BaseFragment : Fragment() {
|
|||
Log.d("LIFECYCLE", "onDestroy: ${this::class.java.simpleName}")
|
||||
}
|
||||
|
||||
protected fun navigateUp(@IdRes destination: Int = DESTINATION_NOT_SET): Boolean {
|
||||
return if (destination == DESTINATION_NOT_SET) {
|
||||
findNavController(this).popBackStack()
|
||||
} else {
|
||||
findNavController(this).popBackStack(destination, false)
|
||||
protected fun navigateUp(@IdRes destination: Int = DESTINATION_NOT_SET) {
|
||||
try {
|
||||
if (destination == DESTINATION_NOT_SET) {
|
||||
findNavController(this).popBackStack()
|
||||
} else {
|
||||
findNavController(this).popBackStack(destination, false)
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Log.w(this::class.java.simpleName, e.message)
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.w(this::class.java.simpleName, e.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +90,7 @@ abstract class BaseFragment : Fragment() {
|
|||
}
|
||||
|
||||
protected fun navigateBackWithResult(resultCode: Int, data: Bundle? = null,
|
||||
@IdRes destination: Int = DESTINATION_NOT_SET): Boolean {
|
||||
@IdRes destination: Int = DESTINATION_NOT_SET) {
|
||||
(requireActivity() as MainActivity).viewModel.navigationResult =
|
||||
NavigationResult(requestCode, resultCode, data)
|
||||
return navigateUp(destination)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import android.nfc.Tag
|
|||
import android.nfc.tech.IsoDep
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.App
|
||||
|
|
@ -89,11 +88,6 @@ class ValidateIdFragment : BaseFragment(), NavigationResultListener,
|
|||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
signTransactionTask?.cancel(true)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onNavigationResult(requestCode: String, resultCode: Int, data: Bundle?) {
|
||||
if (requestCode == Constant.REQUEST_CODE_SEND_TRANSACTION_) {
|
||||
navigateBackWithResult(resultCode, data)
|
||||
|
|
@ -262,7 +256,10 @@ class ValidateIdFragment : BaseFragment(), NavigationResultListener,
|
|||
NoExtendedLengthSupportDialog().show(requireFragmentManager(), NoExtendedLengthSupportDialog.TAG)
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(context, R.string.general_notification_scan_again, Toast.LENGTH_LONG).show()
|
||||
(activity as MainActivity).toastHelper.showSingleToast(
|
||||
context,
|
||||
getString(R.string.general_notification_scan_again)
|
||||
)
|
||||
}
|
||||
progressBar?.progress = 100
|
||||
progressBar?.progressTintList = ColorStateList.valueOf(Color.RED)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import android.nfc.Tag
|
|||
import android.nfc.tech.IsoDep
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.App
|
||||
|
|
@ -49,7 +48,6 @@ class WriteIdFragment : BaseFragment(), NavigationResultListener,
|
|||
private lateinit var ctx: TangemContext
|
||||
private lateinit var tx: ByteArray
|
||||
private lateinit var mpFinishSignSound: MediaPlayer
|
||||
private var toast: Toast? = null
|
||||
|
||||
private var idWasWritten = false
|
||||
|
||||
|
|
@ -94,7 +92,6 @@ class WriteIdFragment : BaseFragment(), NavigationResultListener,
|
|||
|
||||
override fun onStop() {
|
||||
writeIDCardTask?.cancel(true)
|
||||
toast?.cancel()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +171,6 @@ class WriteIdFragment : BaseFragment(), NavigationResultListener,
|
|||
if (success) {
|
||||
navigateUp(R.id.main)
|
||||
} else {
|
||||
toast?.cancel()
|
||||
navigateUp(R.id.issueNewIdFragment)
|
||||
}
|
||||
}
|
||||
|
|
@ -231,8 +227,10 @@ class WriteIdFragment : BaseFragment(), NavigationResultListener,
|
|||
}
|
||||
} else {
|
||||
if (!idWasWritten) {
|
||||
toast = Toast.makeText(context, R.string.general_notification_scan_again, Toast.LENGTH_SHORT)
|
||||
toast?.show()
|
||||
(activity as MainActivity).toastHelper.showSingleToast(
|
||||
context,
|
||||
getString(R.string.general_notification_scan_again)
|
||||
)
|
||||
}
|
||||
}
|
||||
progressBar?.progress = 100
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.wallet.ducatus.DucatusEngine
|
|||
import com.tangem.wallet.eos.EosEngine
|
||||
import com.tangem.wallet.eth.EthEngine
|
||||
import com.tangem.wallet.ethID.EthIdEngine
|
||||
import com.tangem.wallet.flowDemo.FlowDemoEngine
|
||||
import com.tangem.wallet.ltc.LtcEngine
|
||||
import com.tangem.wallet.matic.MaticTokenEngine
|
||||
import com.tangem.wallet.nftToken.NftTokenEngine
|
||||
|
|
@ -58,6 +59,7 @@ object CoinEngineFactory {
|
|||
Blockchain.Ducatus -> DucatusEngine()
|
||||
Blockchain.Tezos -> TezosEngine()
|
||||
Blockchain.BitcoinDual -> BtcMultisigEngine()
|
||||
Blockchain.FlowDemo -> FlowDemoEngine()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
@ -105,6 +107,8 @@ object CoinEngineFactory {
|
|||
TezosEngine(context)
|
||||
else if (Blockchain.BitcoinDual == context.blockchain)
|
||||
BtcMultisigEngine(context)
|
||||
else if (Blockchain.FlowDemo == context.blockchain)
|
||||
FlowDemoEngine(context)
|
||||
else
|
||||
return null
|
||||
} catch (e: Exception) {
|
||||
|
|
|
|||
29
app/src/main/java/com/tangem/wallet/flowDemo/FlowDemoData.kt
Normal file
29
app/src/main/java/com/tangem/wallet/flowDemo/FlowDemoData.kt
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.wallet.flowDemo
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import com.tangem.wallet.CoinData
|
||||
import java.lang.Exception
|
||||
|
||||
class FlowDemoData : CoinData() {
|
||||
var description: String? = null
|
||||
|
||||
override fun clearInfo() {
|
||||
super.clearInfo()
|
||||
description = null
|
||||
}
|
||||
|
||||
override fun loadFromBundle(B: Bundle) {
|
||||
super.loadFromBundle(B)
|
||||
if (B.containsKey("Description")) description = B.getString("Description")
|
||||
}
|
||||
|
||||
override fun saveToBundle(B: Bundle) {
|
||||
super.saveToBundle(B)
|
||||
try {
|
||||
if (description != null) B.putString("Description", description!!)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Can't save to bundle ", e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
250
app/src/main/java/com/tangem/wallet/flowDemo/FlowDemoEngine.kt
Normal file
250
app/src/main/java/com/tangem/wallet/flowDemo/FlowDemoEngine.kt
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
package com.tangem.wallet.flowDemo
|
||||
|
||||
import android.net.Uri
|
||||
import android.text.InputFilter
|
||||
import com.google.protobuf.ByteString
|
||||
import com.tangem.tangem_card.reader.CardProtocol.TangemException
|
||||
import com.tangem.tangem_card.tasks.SignTask
|
||||
import com.tangem.tangem_card.util.Util
|
||||
import com.tangem.wallet.*
|
||||
import com.tangem.wallet.binance.client.domain.Account
|
||||
import com.tangem.wallet.flowDemo.proto.Observation
|
||||
import com.tangem.wallet.flowDemo.proto.ObserveServiceGrpc
|
||||
import io.grpc.ManagedChannelBuilder
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.functions.Function
|
||||
import io.reactivex.observers.DisposableSingleObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class FlowDemoEngine : CoinEngine {
|
||||
constructor()
|
||||
|
||||
constructor(context: TangemContext) : super(context) {
|
||||
if (context.coinData == null) {
|
||||
coinData = FlowDemoData()
|
||||
context.coinData = coinData
|
||||
} else if (context.coinData is FlowDemoData) {
|
||||
coinData = context.coinData as FlowDemoData
|
||||
} else {
|
||||
throw Exception("Invalid type of Blockchain data for XlmEngine")
|
||||
}
|
||||
}
|
||||
|
||||
private val TAG = FlowDemoEngine::class.java.simpleName
|
||||
|
||||
var coinData: FlowDemoData? = null
|
||||
|
||||
override fun checkNewTransactionAmount(amount: Amount?): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun requestBalanceAndUnspentTransactions(blockchainRequestsCallbacks: BlockchainRequestsCallbacks?) {
|
||||
val channel = ManagedChannelBuilder.forAddress("ec2-3-134-137-165.us-east-2.compute.amazonaws.com", 3569).usePlaintext().build();
|
||||
val flowApi = ObserveServiceGrpc.newBlockingStub(channel)
|
||||
|
||||
val script = ByteString.copyFrom(
|
||||
"""import TangemTest from 0x02
|
||||
|
||||
pub fun main(): String? {
|
||||
let contract = getAccount(0x02)
|
||||
let collectionRef = contract.published[&TangemTest.TagCollection] ?? panic("missing reference!")
|
||||
let desc = collectionRef.tags["%s"]?.desc
|
||||
return desc
|
||||
}""".format(coinData!!.wallet).toByteArray()
|
||||
)
|
||||
val scriptRequest = Observation.ExecuteScriptRequest.newBuilder().setScript(script).build()
|
||||
|
||||
val scriptResponseObserver = object : DisposableSingleObserver<Observation.ExecuteScriptResponse>() {
|
||||
override fun onSuccess(response: Observation.ExecuteScriptResponse) {
|
||||
coinData!!.isBalanceReceived = true
|
||||
val byteResult = response.value.toByteArray()
|
||||
if (byteResult.size > 8) {
|
||||
coinData!!.description = String(byteResult.copyOfRange(8, byteResult.size)).toUpperCase()
|
||||
}
|
||||
blockchainRequestsCallbacks!!.onComplete(true)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
ctx.error = e.message
|
||||
blockchainRequestsCallbacks!!.onComplete(false)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Single.just(Observation.ExecuteScriptResponse.getDefaultInstance())
|
||||
.map { flowApi.executeScript(scriptRequest) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.timeout(10, TimeUnit.SECONDS)
|
||||
.subscribe(scriptResponseObserver)
|
||||
} catch (e: Exception) {
|
||||
ctx.error = e.message
|
||||
blockchainRequestsCallbacks!!.onComplete(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBalance(): Amount {
|
||||
return Amount()
|
||||
}
|
||||
|
||||
override fun isNeedCheckNode(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getAmountInputFilters(): Array<InputFilter> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getWalletExplorerUri(): Uri {
|
||||
return Uri.parse("https://www.onflow.org/")
|
||||
}
|
||||
|
||||
override fun getBalanceHTML(): String {
|
||||
val balanceString = if(hasBalanceInfo()) {
|
||||
if(coinData!!.description != null) {
|
||||
coinData!!.description!! + " TANGEM CARD"
|
||||
} else {
|
||||
"UNKNOWN CARD"
|
||||
}
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
if (coinData!!.description == "COMMON") {
|
||||
balanceString == "$balanceString<br><small><small>your usual tangem card</small></small>"
|
||||
} else if (coinData!!.description == "RARE") {
|
||||
balanceString == "$balanceString<br><small><small>wow, this one is RARE</small></small>"
|
||||
}
|
||||
|
||||
return balanceString
|
||||
}
|
||||
|
||||
override fun awaitingConfirmation(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getFeeCurrency(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun convertToByteArray(internalAmount: InternalAmount?): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun requestSendTransaction(blockchainRequestsCallbacks: BlockchainRequestsCallbacks?, txForSend: ByteArray?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun hasBalanceInfo(): Boolean {
|
||||
return coinData!!.isBalanceReceived
|
||||
}
|
||||
|
||||
override fun getBalanceEquivalent(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
// public String getOfflineBalanceHTML() {
|
||||
// InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance());
|
||||
// Amount offlineAmount = convertToAmount(offlineInternalAmount);
|
||||
// return offlineAmount.toDescriptionString(getDecimals());
|
||||
// }
|
||||
@Throws(TangemException::class)
|
||||
override fun defineWallet() {
|
||||
try {
|
||||
val wallet = calculateAddress(ctx.card.walletPublicKeyRar)
|
||||
ctx.coinData.wallet = wallet
|
||||
} catch (e: java.lang.Exception) {
|
||||
ctx.coinData.wallet = "ERROR"
|
||||
throw TangemException("Can't define wallet address")
|
||||
}
|
||||
}
|
||||
|
||||
override fun calculateAddress(pkUncompressed: ByteArray?): String {
|
||||
return Util.byteArrayToHexString(pkUncompressed)
|
||||
}
|
||||
|
||||
override fun getShareWalletUri(): Uri {
|
||||
return Uri.parse(ctx.coinData.wallet)
|
||||
}
|
||||
|
||||
override fun getUnspentInputsDescription(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun checkNewTransactionAmountAndFee(amount: Amount?, fee: Amount?, isFeeIncluded: Boolean?): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isBalanceNotZero(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getBalanceCurrency(): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun evaluateFeeEquivalent(fee: String?): String {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun convertToAmount(internalAmount: InternalAmount?): Amount {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun convertToAmount(strAmount: String?, currency: String?): Amount {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isExtractPossible(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun convertToInternalAmount(amount: Amount?): InternalAmount {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun convertToInternalAmount(bytes: ByteArray?): InternalAmount {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun requestFee(blockchainRequestsCallbacks: BlockchainRequestsCallbacks?, targetAddress: String?, amount: Amount?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun validateAddress(address: String?): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun constructTransaction(amountValue: Amount?, feeValue: Amount?, IncFee: Boolean, targetAddress: String?): SignTask.TransactionToSign {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun validateBalance(balanceValidator: BalanceValidator?): Boolean {
|
||||
|
||||
if (hasBalanceInfo()) {
|
||||
if (coinData!!.description != null) {
|
||||
balanceValidator!!.setScore(100)
|
||||
balanceValidator.firstLine = R.string.balance_validator_first_line_verified_in_blockchain
|
||||
balanceValidator.setSecondLine(R.string.empty_string)
|
||||
} else {
|
||||
balanceValidator!!.setScore(0)
|
||||
balanceValidator.firstLine = R.string.balance_validator_first_line_authenticity
|
||||
balanceValidator.setSecondLine(R.string.empty_string)
|
||||
}
|
||||
} else {
|
||||
balanceValidator!!.setScore(0)
|
||||
balanceValidator.firstLine = R.string.balance_validator_first_line_no_connection
|
||||
balanceValidator.setSecondLine(R.string.balance_validator_second_line_authenticity_not_verified)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createCoinData(): CoinData {
|
||||
return FlowDemoData()
|
||||
}
|
||||
}
|
||||
9303
app/src/main/java/com/tangem/wallet/flowDemo/proto/Entities.java
Normal file
9303
app/src/main/java/com/tangem/wallet/flowDemo/proto/Entities.java
Normal file
File diff suppressed because it is too large
Load diff
13161
app/src/main/java/com/tangem/wallet/flowDemo/proto/Observation.java
Normal file
13161
app/src/main/java/com/tangem/wallet/flowDemo/proto/Observation.java
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -228,6 +228,12 @@ class LocalStorage
|
|||
|
||||
fun getCardArtworkBitmap(card: TangemCard): Bitmap {
|
||||
// special cases (first series of cards, hardcode CID->artwork), on new series batch<->artwork
|
||||
|
||||
if (card.isIDIssuer) {
|
||||
val artworkId = context.resources.getResourceEntryName(R.drawable.card_id_issuer)
|
||||
return getArtworkBitmap(artworkId) ?: return getDefaultArtworkBitmap(card)
|
||||
}
|
||||
|
||||
val hexCID = Util.bytesToHex(card.cid)
|
||||
val artworkResourceId: Int? = when {
|
||||
hexCID in "AA01000000000000".."AA01000000004999" -> R.drawable.card_ru006
|
||||
|
|
|
|||
BIN
server-android/src/main/res/drawable/card_id_issuer.png
Normal file
BIN
server-android/src/main/res/drawable/card_id_issuer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
|
|
@ -634,6 +634,15 @@ public class TangemCard {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isIDIssuer() {
|
||||
try {
|
||||
return (productMask & ProductMask.IdIssuer) != 0;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public TLVList tlvIDCardData = null;
|
||||
|
||||
public void setTlvIdCardData(TLVList tlvIDCardData) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ public class ProductMask {
|
|||
public static final int Note = 0x0001;
|
||||
public static final int Tag = 0x0002;
|
||||
public static final int IdCard = 0x0004;
|
||||
public static final int IdIssuer = 0x0008;
|
||||
|
||||
public static String getDescription(int iValue) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
@ -17,6 +18,8 @@ public class ProductMask {
|
|||
sb.append("Tag, ");
|
||||
if ((iValue & ProductMask.IdCard) != 0)
|
||||
sb.append("IdCard, ");
|
||||
if ((iValue & ProductMask.IdIssuer) != 0)
|
||||
sb.append("IdIssuer, ");
|
||||
|
||||
if (sb.length() > 1) sb.delete(sb.length() - 2, sb.length());
|
||||
sb.append("]");
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ data class ProductMask(val rawValue: Int) {
|
|||
const val note = 0x01
|
||||
const val tag = 0x02
|
||||
const val idCard = 0x04
|
||||
const val idIssuer = 0x08
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package com.tangem.tangemtest._arch.structure.abstraction
|
||||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
fun List<Item>.findDataItem(id: Id): BaseItem<Any?>? {
|
||||
var foundItem: BaseItem<Any?>? = null
|
||||
iterate {
|
||||
if (it.id == id) {
|
||||
foundItem = it as? BaseItem<Any?>
|
||||
return@iterate
|
||||
}
|
||||
}
|
||||
return foundItem
|
||||
}
|
||||
|
||||
fun List<Item>.iterate(func: (Item) -> Unit) {
|
||||
forEach {
|
||||
when (it) {
|
||||
is BaseItem<*> -> func(it)
|
||||
is Block -> it.itemList.iterate(func)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.tangemtest._arch.structure.abstraction
|
||||
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface DefaultConverter<A, B> {
|
||||
fun convert(from: A, default: B): B
|
||||
}
|
||||
|
||||
interface ItemsToModel<M> : DefaultConverter<List<Item>, M>
|
||||
interface ModelToItems<M> : Converter<M, List<Item>>
|
||||
|
||||
interface ModelConverter<M> : DefaultConverter<List<Item>, M>, Converter<M, List<Item>>
|
||||
|
|
@ -61,6 +61,8 @@ open class BaseItemViewModel<D> : ItemViewModel<D> {
|
|||
}
|
||||
|
||||
class ViewState {
|
||||
var isHiddenField = false
|
||||
|
||||
var descriptionVisibility: Int = 0x00000008
|
||||
set(value) {
|
||||
field = value
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package com.tangem.tangemtest.ucase.domain.actions
|
|||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,25 +1,65 @@
|
|||
package com.tangem.tangemtest.ucase.domain.actions
|
||||
|
||||
import com.tangem.commands.personalization.entities.CardConfig
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest._arch.structure.impl.EditTextItem
|
||||
import com.tangem.tangemtest._arch.structure.impl.NumberItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.tunnel.ActionView
|
||||
import com.tangem.tangemtest.ucase.tunnel.ItemError
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.CardNumber
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigConverter
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.PersonalizeConfigToCardConfig
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.DefaultPersonalizeParams
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizeAction : BaseAction() {
|
||||
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
|
||||
val cardConfig = attrs.payload.remove(PayloadKey.cardConfig) as? CardConfig
|
||||
?: throw IllegalArgumentException("CardConfig must be in the payloads of the ParamsManager")
|
||||
val itemList = attrs.payload[PayloadKey.itemList] as? List<Item> ?: return
|
||||
val actionView = attrs.payload[PayloadKey.actionView] as? ActionView ?: return
|
||||
|
||||
if (!checkSeries(itemList)) {
|
||||
actionView.showSnackbar(ItemError.BadSeries)
|
||||
return
|
||||
}
|
||||
if (!checkNumber(itemList)) {
|
||||
actionView.showSnackbar(ItemError.BadCardNumber)
|
||||
return
|
||||
}
|
||||
|
||||
val issuer = DefaultPersonalizeParams.issuer()
|
||||
val acquirer = DefaultPersonalizeParams.acquirer()
|
||||
val manufacturer = DefaultPersonalizeParams.manufacturer()
|
||||
|
||||
val personalizeConfig = PersonalizeConfigConverter().convert(itemList, PersonalizeConfig())
|
||||
val cardConfig = PersonalizeConfigToCardConfig().convert(personalizeConfig)
|
||||
|
||||
attrs.cardManager.personalize(cardConfig, issuer, manufacturer, acquirer) {
|
||||
handleResult(payload, it, null, attrs, callback)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSeries(itemList: List<Item>): Boolean {
|
||||
val seriesItem = itemList.findDataItem(CardNumber.Series) as? EditTextItem ?: return false
|
||||
val data = seriesItem.getData() ?: return false
|
||||
|
||||
seriesItem.setData(data.toUpperCase())
|
||||
return data.length == 2 || data.length == 4
|
||||
}
|
||||
|
||||
private fun checkNumber(itemList: List<Item>): Boolean {
|
||||
val seriesItem = itemList.findDataItem(CardNumber.Series) as? EditTextItem ?: return false
|
||||
val numberItem = itemList.findDataItem(CardNumber.Number) as? NumberItem ?: return false
|
||||
val seriesData = seriesItem.getData() ?: return false
|
||||
val numberData = stringOf(numberItem.getData())
|
||||
|
||||
return if (seriesData.length == 2 && numberData.length > 13) false
|
||||
else !(seriesData.length == 4 && numberData.length > 11)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@ package com.tangem.tangemtest.ucase.domain.actions
|
|||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.tangem.CardManager
|
|||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.Payload
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ItemsChangeConsequence
|
||||
import com.tangem.tasks.TaskEvent
|
||||
|
|
@ -34,15 +33,6 @@ interface PayloadKey {
|
|||
val incomingJson: String = "incomingJson"
|
||||
val card = "card"
|
||||
val actionView = "actionView"
|
||||
val itemList = "itemList"
|
||||
}
|
||||
}
|
||||
|
||||
fun List<Item>.findItem(id: Id): Item? {
|
||||
return firstOrNull { it.id == id }
|
||||
}
|
||||
|
||||
fun List<Item>.findDataItem(id: Id): BaseItem<Any?>? {
|
||||
val item = firstOrNull { it.id == id }
|
||||
return if (item is BaseItem<*>) item as BaseItem<Any?>
|
||||
else null
|
||||
}
|
||||
|
|
@ -4,12 +4,12 @@ import com.tangem.CardManager
|
|||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.Payload
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest.ucase.domain.actions.Action
|
||||
import com.tangem.tangemtest.ucase.domain.actions.AttrForAction
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.AffectedItemsCallback
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ItemsChangeConsequence
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,18 +2,14 @@ package com.tangem.tangemtest.ucase.domain.paramsManager.managers
|
|||
|
||||
import com.tangem.CardManager
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.impl.EditTextItem
|
||||
import com.tangem.tangemtest.ucase.domain.actions.PersonalizeAction
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizeItemsManager : BaseItemsManager(PersonalizeAction()) {
|
||||
override fun createItemsList(): List<Item> {
|
||||
return listOf(EditTextItem(TlvId.CardId))
|
||||
}
|
||||
override fun createItemsList(): List<Item> = listOf()
|
||||
|
||||
override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) {
|
||||
action.executeMainAction(this, getAttrsForAction(cardManager), callback)
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import com.tangem.commands.Card
|
|||
import com.tangem.commands.CardStatus
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
|
||||
import com.tangem.tangemtest.ucase.tunnel.ActionView
|
||||
import com.tangem.tangemtest.ucase.tunnel.CardError
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import com.tangem.common.extensions.calculateSha256
|
|||
import com.tangem.common.extensions.calculateSha512
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
|
||||
import com.tangem.tangemtest.ucase.tunnel.ActionView
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
import ru.dev.gbixahue.eu4d.lib.android.global.threading.postUI
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import com.tangem.commands.SettingsMask
|
|||
import com.tangem.commands.SigningMethod
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import java.lang.reflect.Type
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -20,6 +22,7 @@ class GsonInitializer {
|
|||
registerTypeAdapter(SigningMethod::class.java, SigningMethodTypeAdapter())
|
||||
registerTypeAdapter(SettingsMask::class.java, SettingsMaskTypeAdapter())
|
||||
registerTypeAdapter(ProductMask::class.java, ProductMaskTypeAdapter())
|
||||
registerTypeAdapter(Date::class.java, DateTypeAdapter())
|
||||
}
|
||||
builder.setPrettyPrinting()
|
||||
return builder.create()
|
||||
|
|
@ -52,4 +55,11 @@ class SigningMethodTypeAdapter : JsonSerializer<SigningMethod> {
|
|||
override fun serialize(src: SigningMethod, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
||||
return JsonPrimitive(src.rawValue.toString())
|
||||
}
|
||||
}
|
||||
|
||||
class DateTypeAdapter: JsonSerializer<Date> {
|
||||
override fun serialize(src: Date, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
||||
val formatter = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale("en_US"))
|
||||
return JsonPrimitive(formatter.format(src).toString())
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ class PersonalizeResources() {
|
|||
private fun initCardNumber(holder: TypedHolder<Id, Resources>) {
|
||||
holder.register(CardNumber.Series, Resources(R.string.pers_item_series, R.string.info_pers_item_series))
|
||||
holder.register(CardNumber.Number, Resources(R.string.pers_item_number, R.string.info_pers_item_number))
|
||||
holder.register(CardNumber.BatchId, Resources(R.string.pers_item_batch_id, R.string.info_pers_item_batch_id))
|
||||
}
|
||||
|
||||
private fun initCommon(holder: TypedHolder<Id, Resources>) {
|
||||
|
|
@ -86,7 +87,8 @@ class PersonalizeResources() {
|
|||
private fun initProductMask(holder: TypedHolder<Id, Resources>) {
|
||||
holder.register(ProductMask.Note, Resources(R.string.pers_item_note, R.string.info_pers_item_note))
|
||||
holder.register(ProductMask.Tag, Resources(R.string.pers_item_tag, R.string.info_pers_item_tag))
|
||||
holder.register(ProductMask.CardId, Resources(R.string.pers_item_id_card, R.string.info_pers_item_id_card))
|
||||
holder.register(ProductMask.IdCard, Resources(R.string.pers_item_id_card, R.string.info_pers_item_id_card))
|
||||
holder.register(ProductMask.IdIssuerCard, Resources(R.string.pers_item_id_issuer_card, R.string.info_pers_item_id_issuer_card))
|
||||
}
|
||||
|
||||
private fun initSettingsMask(holder: TypedHolder<Id, Resources>) {
|
||||
|
|
@ -110,7 +112,7 @@ class PersonalizeResources() {
|
|||
|
||||
private fun initSettingsMaskProtocolEnc(holder: TypedHolder<Id, Resources>) {
|
||||
holder.register(SettingsMaskProtocolEnc.AllowUnencrypted, Resources(R.string.pers_item_allow_unencrypted, R.string.info_pers_item_allow_unencrypted))
|
||||
holder.register(SettingsMaskProtocolEnc.AlloFastEncryption, Resources(R.string.pers_item_allow_fast_encryption, R.string.info_pers_item_allow_fast_encryption))
|
||||
holder.register(SettingsMaskProtocolEnc.AllowStaticEncryption, Resources(R.string.pers_item_allow_fast_encryption, R.string.info_pers_item_allow_fast_encryption))
|
||||
}
|
||||
|
||||
private fun initSettingsMaskNde(holder: TypedHolder<Id, Resources>) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@ import com.tangem.tangemtest._arch.structure.Id
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
enum class CardError : Id {
|
||||
NotPersonalized
|
||||
interface Errors: Id
|
||||
|
||||
enum class CardError : Errors {
|
||||
NotPersonalized,
|
||||
}
|
||||
|
||||
enum class ItemError: Errors {
|
||||
BadSeries,
|
||||
BadCardNumber,
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ interface ViewScreen
|
|||
|
||||
interface SnackbarHolder {
|
||||
fun showSnackbar(message: String)
|
||||
fun showSnackbar(id: Int)
|
||||
fun showSnackbar(id: Id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,11 +133,15 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder, ActionView {
|
|||
override fun showSnackbar(id: Id) {
|
||||
// MainResourceHolder.safeGet<>()
|
||||
when (id) {
|
||||
CardError.NotPersonalized -> showSnackbar(requireContext().getString(R.string.card_error_not_personalized))
|
||||
CardError.NotPersonalized -> showSnackbar(R.string.card_error_not_personalized)
|
||||
else -> showSnackbar(requireContext().getString(R.string.unknown))
|
||||
}
|
||||
}
|
||||
|
||||
override fun showSnackbar(id: Int) {
|
||||
showSnackbar(requireContext().getString(id))
|
||||
}
|
||||
|
||||
override fun showSnackbar(message: String) {
|
||||
Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ enum class BlockId : PersonalizeId {
|
|||
enum class CardNumber : BlockItem {
|
||||
Series,
|
||||
Number,
|
||||
BatchId,
|
||||
}
|
||||
|
||||
enum class Common : BlockItem {
|
||||
|
|
@ -70,7 +71,8 @@ enum class Token : BlockItem {
|
|||
enum class ProductMask : BlockItem {
|
||||
Note,
|
||||
Tag,
|
||||
CardId
|
||||
IdCard,
|
||||
IdIssuerCard
|
||||
}
|
||||
|
||||
enum class SettingsMask : BlockItem {
|
||||
|
|
@ -94,7 +96,7 @@ enum class SettingsMask : BlockItem {
|
|||
|
||||
enum class SettingsMaskProtocolEnc : BlockItem {
|
||||
AllowUnencrypted,
|
||||
AlloFastEncryption
|
||||
AllowStaticEncryption
|
||||
}
|
||||
|
||||
enum class SettingsMaskNdef : BlockItem {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter
|
||||
|
||||
import com.tangem.commands.EllipticCurve
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.impl.KeyValue
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizeConfigValuesHolder : BaseTypedHolder<Id, Value>() {
|
||||
|
||||
// All registered association values can't be objects
|
||||
fun init(default: PersonalizeConfig) {
|
||||
register(CardNumber.Series, Value(default.series))
|
||||
register(CardNumber.Number, Value(default.startNumber))
|
||||
register(CardNumber.BatchId, Value(default.batchId))
|
||||
register(Common.Curve, Value(default.curveID, Helper.listOfCurves()))
|
||||
register(Common.Blockchain, Value(default.blockchain, Helper.listOfBlockchain()))
|
||||
register(Common.BlockchainCustom, Value(""))
|
||||
register(Common.MaxSignatures, Value(default.MaxSignatures))
|
||||
register(Common.CreateWallet, Value(default.createWallet))
|
||||
register(SigningMethod.SignTx, Value(default.SigningMethod0))
|
||||
register(SigningMethod.SignTxRaw, Value(default.SigningMethod1))
|
||||
register(SigningMethod.SignValidatedTx, Value(default.SigningMethod2))
|
||||
register(SigningMethod.SignValidatedTxRaw, Value(default.SigningMethod3))
|
||||
register(SigningMethod.SignValidatedTxIssuer, Value(default.SigningMethod4))
|
||||
register(SigningMethod.SignValidatedTxRawIssuer, Value(default.SigningMethod5))
|
||||
register(SigningMethod.SignExternal, Value(default.SigningMethod6))
|
||||
register(SignHashExProp.PinLessFloorLimit, Value(default.pinLessFloorLimit))
|
||||
register(SignHashExProp.CryptoExKey, Value(default.hexCrExKey))
|
||||
register(SignHashExProp.RequireTerminalCertSig, Value(default.requireTerminalCertSignature))
|
||||
register(SignHashExProp.RequireTerminalTxSig, Value(default.requireTerminalTxSignature))
|
||||
register(SignHashExProp.CheckPin3, Value(default.checkPIN3onCard))
|
||||
register(Denomination.WriteOnPersonalize, Value(default.writeOnPersonalization))
|
||||
register(Denomination.Denomination, Value(default.denomination))
|
||||
register(Token.ItsToken, Value(default.itsToken))
|
||||
register(Token.Symbol, Value(default.symbol))
|
||||
register(Token.ContractAddress, Value(default.contractAddress))
|
||||
register(Token.Decimal, Value(default.decimal))
|
||||
register(ProductMask.Note, Value(default.cardData.product_note))
|
||||
register(ProductMask.Tag, Value(default.cardData.product_tag))
|
||||
register(ProductMask.IdCard, Value(default.cardData.product_id_card))
|
||||
register(ProductMask.IdIssuerCard, Value(default.cardData.product_id_issuer))
|
||||
register(SettingsMask.IsReusable, Value(default.isReusable))
|
||||
register(SettingsMask.NeedActivation, Value(default.useActivation))
|
||||
register(SettingsMask.ForbidPurge, Value(default.forbidPurgeWallet))
|
||||
register(SettingsMask.AllowSelectBlockchain, Value(default.allowSelectBlockchain))
|
||||
register(SettingsMask.UseBlock, Value(default.useBlock))
|
||||
register(SettingsMask.OneApdu, Value(default.oneApdu))
|
||||
register(SettingsMask.UseCvc, Value(default.useCVC))
|
||||
register(SettingsMask.AllowSwapPin, Value(default.allowSwapPIN))
|
||||
register(SettingsMask.AllowSwapPin2, Value(default.allowSwapPIN2))
|
||||
register(SettingsMask.ForbidDefaultPin, Value(default.forbidDefaultPIN))
|
||||
register(SettingsMask.SmartSecurityDelay, Value(default.smartSecurityDelay))
|
||||
register(SettingsMask.ProtectIssuerDataAgainstReplay, Value(default.protectIssuerDataAgainstReplay))
|
||||
register(SettingsMask.SkipSecurityDelayIfValidated, Value(default.skipSecurityDelayIfValidatedByIssuer))
|
||||
register(SettingsMask.SkipPin2CvcIfValidated, Value(default.skipCheckPIN2andCVCIfValidatedByIssuer))
|
||||
register(SettingsMask.SkipSecurityDelayOnLinkedTerminal, Value(default.skipSecurityDelayIfValidatedByLinkedTerminal))
|
||||
register(SettingsMask.RestrictOverwriteExtraIssuerData, Value(default.restrictOverwriteIssuerDataEx))
|
||||
register(SettingsMaskProtocolEnc.AllowUnencrypted, Value(default.protocolAllowUnencrypted))
|
||||
register(SettingsMaskProtocolEnc.AllowStaticEncryption, Value(default.protocolAllowStaticEncryption))
|
||||
register(SettingsMaskNdef.UseNdef, Value(default.useNDEF))
|
||||
register(SettingsMaskNdef.DynamicNdef, Value(default.useDynamicNDEF))
|
||||
register(SettingsMaskNdef.DisablePrecomputedNdef, Value(default.disablePrecomputedNDEF))
|
||||
register(SettingsMaskNdef.Aar, Value(default.aar, Helper.aarList()))
|
||||
register(SettingsMaskNdef.AarCustom, Value(default.aar))
|
||||
register(Pins.Pin, Value(default.PIN))
|
||||
register(Pins.Pin2, Value(default.PIN2))
|
||||
register(Pins.Pin3, Value(default.PIN3))
|
||||
register(Pins.Cvc, Value(default.CVC))
|
||||
register(Pins.PauseBeforePin2, Value(default.pauseBeforePIN2, Helper.pauseBeforePin()))
|
||||
}
|
||||
}
|
||||
|
||||
class Value(
|
||||
private var value: Any? = null,
|
||||
val list: List<KeyValue>? = mutableListOf()
|
||||
) {
|
||||
fun get(): Any? = value
|
||||
fun set(newValue: Any?) {
|
||||
value = newValue
|
||||
}
|
||||
}
|
||||
|
||||
internal class Helper {
|
||||
companion object {
|
||||
fun listOfCurves(): List<KeyValue> {
|
||||
return EllipticCurve.values().map { KeyValue(it.name, it.curve) }
|
||||
}
|
||||
|
||||
fun listOfBlockchain(): List<KeyValue> {
|
||||
return mutableListOf(
|
||||
KeyValue("--- CUSTOM ---", ""),
|
||||
KeyValue("BTC", "BTC"),
|
||||
KeyValue("BTC/test", "BTC/test"),
|
||||
KeyValue("ETH", "ETH"),
|
||||
KeyValue("ETH/test", "ETH/test"),
|
||||
KeyValue("BCH", "BCH"),
|
||||
KeyValue("BCH/test", "BCH/test"),
|
||||
KeyValue("LTC", "LTC"),
|
||||
KeyValue("XLM", "XLM"),
|
||||
KeyValue("XLM/test", "XLM/test"),
|
||||
KeyValue("RSK", "RSK"),
|
||||
KeyValue("XPR", "XPR"),
|
||||
KeyValue("CARDANO", "CARDANO"),
|
||||
KeyValue("BNB", "BNB"),
|
||||
KeyValue("XTZ", "XTZ"),
|
||||
KeyValue("DUC", "DUC")
|
||||
)
|
||||
}
|
||||
|
||||
fun aarList(): List<KeyValue> {
|
||||
return mutableListOf(
|
||||
KeyValue("--- CUSTOM ---", ""),
|
||||
KeyValue("Release APP", "com.tangem.wallet"),
|
||||
KeyValue("Debug APP", "com.tangem.wallet.debug"),
|
||||
KeyValue("None", "")
|
||||
)
|
||||
}
|
||||
|
||||
fun pauseBeforePin(): List<KeyValue> {
|
||||
return mutableListOf(
|
||||
KeyValue("immediately", 0L),
|
||||
KeyValue("2 seconds", 2000L),
|
||||
KeyValue("5 seconds", 5000L),
|
||||
KeyValue("15 seconds", 15000L),
|
||||
KeyValue("30 seconds", 30000L),
|
||||
KeyValue("1 minute", 60000L),
|
||||
KeyValue("2 minute", 120000L)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter
|
||||
|
||||
import com.tangem.commands.EllipticCurve
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.impl.KeyValue
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class Value(
|
||||
private var value: Any? = null,
|
||||
val list: List<KeyValue>? = mutableListOf()
|
||||
) {
|
||||
fun get(): Any? = value
|
||||
fun set(newValue: Any?) {
|
||||
value = newValue
|
||||
}
|
||||
}
|
||||
|
||||
class IdToValueAssociations : BaseTypedHolder<Id, Value>() {
|
||||
|
||||
// All registered association values can't be objects
|
||||
fun init(from: PersonalizeConfig) {
|
||||
register(CardNumber.Series, Value(from.series))
|
||||
register(CardNumber.Number, Value(from.startNumber))
|
||||
register(Common.Curve, Value(from.curveID, Helper.listOfCurves()))
|
||||
register(Common.Blockchain, Value(from.blockchain, Helper.listOfBlockchain()))
|
||||
register(Common.BlockchainCustom, Value(""))
|
||||
register(Common.MaxSignatures, Value(from.MaxSignatures))
|
||||
register(Common.CreateWallet, Value(from.createWallet))
|
||||
register(SigningMethod.SignTx, Value(from.SigningMethod0))
|
||||
register(SigningMethod.SignTxRaw, Value(from.SigningMethod1))
|
||||
register(SigningMethod.SignValidatedTx, Value(from.SigningMethod2))
|
||||
register(SigningMethod.SignValidatedTxRaw, Value(from.SigningMethod3))
|
||||
register(SigningMethod.SignValidatedTxIssuer, Value(from.SigningMethod4))
|
||||
register(SigningMethod.SignValidatedTxRawIssuer, Value(from.SigningMethod5))
|
||||
register(SigningMethod.SignExternal, Value(from.SigningMethod6))
|
||||
register(SignHashExProp.PinLessFloorLimit, Value(from.pinLessFloorLimit))
|
||||
register(SignHashExProp.CryptoExKey, Value(from.hexCrExKey))
|
||||
register(SignHashExProp.RequireTerminalCertSig, Value(from.requireTerminalCertSignature))
|
||||
register(SignHashExProp.RequireTerminalTxSig, Value(from.requireTerminalTxSignature))
|
||||
register(SignHashExProp.CheckPin3, Value(from.checkPIN3onCard))
|
||||
register(Denomination.WriteOnPersonalize, Value(from.writeOnPersonalization))
|
||||
register(Denomination.Denomination, Value(from.denomination))
|
||||
register(Token.ItsToken, Value(from.itsToken))
|
||||
register(Token.Symbol, Value(from.symbol))
|
||||
register(Token.ContractAddress, Value(from.contractAddress))
|
||||
register(Token.Decimal, Value(from.decimal))
|
||||
register(ProductMask.Note, Value(from.cardData.product_note))
|
||||
register(ProductMask.Tag, Value(from.cardData.product_tag))
|
||||
register(ProductMask.CardId, Value(from.cardData.product_id_card))
|
||||
register(SettingsMask.IsReusable, Value(from.isReusable))
|
||||
register(SettingsMask.NeedActivation, Value(from.useActivation))
|
||||
register(SettingsMask.ForbidPurge, Value(from.forbidPurgeWallet))
|
||||
register(SettingsMask.AllowSelectBlockchain, Value(from.allowSelectBlockchain))
|
||||
register(SettingsMask.UseBlock, Value(from.useBlock))
|
||||
register(SettingsMask.OneApdu, Value(from.oneApdu))
|
||||
register(SettingsMask.UseCvc, Value(from.useCVC))
|
||||
register(SettingsMask.AllowSwapPin, Value(from.allowSwapPIN))
|
||||
register(SettingsMask.AllowSwapPin2, Value(from.allowSwapPIN2))
|
||||
register(SettingsMask.ForbidDefaultPin, Value(from.forbidDefaultPIN))
|
||||
register(SettingsMask.SmartSecurityDelay, Value(from.smartSecurityDelay))
|
||||
register(SettingsMask.ProtectIssuerDataAgainstReplay, Value(from.protectIssuerDataAgainstReplay))
|
||||
register(SettingsMask.SkipSecurityDelayIfValidated, Value(from.skipSecurityDelayIfValidatedByIssuer))
|
||||
register(SettingsMask.SkipPin2CvcIfValidated, Value(from.skipCheckPIN2andCVCIfValidatedByIssuer))
|
||||
register(SettingsMask.SkipSecurityDelayOnLinkedTerminal, Value(from.skipSecurityDelayIfValidatedByLinkedTerminal))
|
||||
register(SettingsMask.RestrictOverwriteExtraIssuerData, Value(from.restrictOverwriteIssuerDataEx))
|
||||
register(SettingsMaskProtocolEnc.AllowUnencrypted, Value(from.protocolAllowUnencrypted))
|
||||
register(SettingsMaskProtocolEnc.AlloFastEncryption, Value(false))
|
||||
register(SettingsMaskNdef.UseNdef, Value(from.useNDEF))
|
||||
register(SettingsMaskNdef.DynamicNdef, Value(from.useDynamicNDEF))
|
||||
register(SettingsMaskNdef.DisablePrecomputedNdef, Value(from.disablePrecomputedNDEF))
|
||||
register(SettingsMaskNdef.Aar, Value(from.aar, Helper.aarList()))
|
||||
register(SettingsMaskNdef.AarCustom, Value(from.aar))
|
||||
register(Pins.Pin, Value(from.PIN))
|
||||
register(Pins.Pin2, Value(from.PIN2))
|
||||
register(Pins.Pin3, Value(from.PIN3))
|
||||
register(Pins.Cvc, Value(from.CVC))
|
||||
register(Pins.PauseBeforePin2, Value(from.pauseBeforePIN2, Helper.pauseBeforePin()))
|
||||
}
|
||||
}
|
||||
|
||||
internal class Helper {
|
||||
companion object {
|
||||
fun listOfCurves(): List<KeyValue> {
|
||||
return EllipticCurve.values().map { KeyValue(it.name, it.curve) }
|
||||
}
|
||||
|
||||
fun listOfBlockchain(): List<KeyValue> {
|
||||
return mutableListOf(
|
||||
KeyValue("--- CUSTOM ---", "BTC/test"),
|
||||
KeyValue("BTC", "BTC"),
|
||||
KeyValue("BTC/test", "BTC/test"),
|
||||
KeyValue("ETH", "ETH"),
|
||||
KeyValue("ETH/test", "ETH/test"),
|
||||
KeyValue("BCH", "BCH"),
|
||||
KeyValue("BCH/test", "BCH/test"),
|
||||
KeyValue("LTC", "LTC"),
|
||||
KeyValue("XLM", "XLM"),
|
||||
KeyValue("XLM/test", "XLM/test"),
|
||||
KeyValue("RSK", "RSK"),
|
||||
KeyValue("XPR", "XPR"),
|
||||
KeyValue("CARDANO", "CARDANO")
|
||||
)
|
||||
}
|
||||
|
||||
fun aarList(): List<KeyValue> {
|
||||
return mutableListOf(
|
||||
KeyValue("--- CUSTOM ---", ""),
|
||||
KeyValue("Release APP", "com.tangem.wallet"),
|
||||
KeyValue("Debug APP", "com.tangem.wallet.debug"),
|
||||
KeyValue("None", "")
|
||||
)
|
||||
}
|
||||
|
||||
fun pauseBeforePin(): List<KeyValue> {
|
||||
return mutableListOf(
|
||||
KeyValue("immediately", 0L),
|
||||
KeyValue("2 seconds", 2000L),
|
||||
KeyValue("5 seconds", 5000L),
|
||||
KeyValue("15 seconds", 15000L),
|
||||
KeyValue("30 seconds", 30000L),
|
||||
KeyValue("1 minute", 60000L),
|
||||
KeyValue("2 minute", 120000L)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,335 +1,26 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter
|
||||
|
||||
import com.tangem.commands.CardData
|
||||
import com.tangem.commands.EllipticCurve
|
||||
import com.tangem.commands.ProductMaskBuilder
|
||||
import com.tangem.commands.personalization.entities.CardConfig
|
||||
import com.tangem.commands.personalization.entities.NdefRecord
|
||||
import com.tangem.tangemtest._arch.structure.Additional
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Block
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ListItemBlock
|
||||
import com.tangem.tangemtest._arch.structure.impl.*
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemsToModel
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ModelConverter
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ModelToItems
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.ItemsToPersonalizeConfig
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.PersonalizeConfigToItem
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizeConfigConverter {
|
||||
class PersonalizeConfigConverter : ModelConverter<PersonalizeConfig> {
|
||||
|
||||
private val associations: IdToValueAssociations = IdToValueAssociations()
|
||||
private val valueMapper = ValueMapper()
|
||||
private val toModel: ItemsToModel<PersonalizeConfig> = ItemsToPersonalizeConfig()
|
||||
private val toItems: ModelToItems<PersonalizeConfig> = PersonalizeConfigToItem()
|
||||
|
||||
fun toBlock(from: PersonalizeConfig): List<Block> {
|
||||
associations.init(from)
|
||||
val blocList = mutableListOf<Block>()
|
||||
blocList.add(cardNumber())
|
||||
blocList.add(common())
|
||||
blocList.add(signingMethod())
|
||||
blocList.add(signHashExProperties())
|
||||
blocList.add(denomination())
|
||||
blocList.add(token())
|
||||
blocList.add(productMask())
|
||||
blocList.add(settingsMask())
|
||||
blocList.add(settingsMaskProtocolEnc())
|
||||
blocList.add(settingsMaskNdef())
|
||||
blocList.add(pins())
|
||||
val payloadBlock = ListItemBlock(Additional.JSON_TAILS)
|
||||
addPayload(payloadBlock, from)
|
||||
blocList.add(payloadBlock)
|
||||
return blocList
|
||||
override fun convert(from: List<Item>, default: PersonalizeConfig): PersonalizeConfig {
|
||||
return toModel.convert(from, default)
|
||||
}
|
||||
|
||||
private fun cardNumber(): Block {
|
||||
val block = createBlock(BlockId.CardNumber)
|
||||
mutableListOf(
|
||||
CardNumber.Series,
|
||||
CardNumber.Number
|
||||
).forEach { createItem(block, it as Id) }
|
||||
return block
|
||||
override fun convert(from: PersonalizeConfig): List<Item> {
|
||||
return toItems.convert(from)
|
||||
}
|
||||
|
||||
private fun common(): Block {
|
||||
val block = createBlock(BlockId.Common)
|
||||
mutableListOf(
|
||||
Common.Curve,
|
||||
Common.Blockchain,
|
||||
Common.BlockchainCustom,
|
||||
Common.MaxSignatures,
|
||||
Common.CreateWallet
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signingMethod(): Block {
|
||||
val block = createBlock(BlockId.SigningMethod)
|
||||
mutableListOf(
|
||||
SigningMethod.SignTx,
|
||||
SigningMethod.SignTxRaw,
|
||||
SigningMethod.SignValidatedTx,
|
||||
SigningMethod.SignValidatedTxRaw,
|
||||
SigningMethod.SignValidatedTxIssuer,
|
||||
SigningMethod.SignValidatedTxRawIssuer,
|
||||
SigningMethod.SignExternal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signHashExProperties(): Block {
|
||||
val block = createBlock(BlockId.SignHashExProp)
|
||||
mutableListOf(
|
||||
SignHashExProp.PinLessFloorLimit,
|
||||
SignHashExProp.CryptoExKey,
|
||||
SignHashExProp.RequireTerminalCertSig,
|
||||
SignHashExProp.RequireTerminalTxSig,
|
||||
SignHashExProp.CheckPin3
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun denomination(): Block {
|
||||
val block = createBlock(BlockId.Denomination)
|
||||
mutableListOf(
|
||||
Denomination.WriteOnPersonalize,
|
||||
Denomination.Denomination
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun token(): Block {
|
||||
val block = createBlock(BlockId.Token)
|
||||
mutableListOf(
|
||||
Token.ItsToken,
|
||||
Token.Symbol,
|
||||
Token.ContractAddress,
|
||||
Token.Decimal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun productMask(): Block {
|
||||
val block = createBlock(BlockId.ProdMask)
|
||||
mutableListOf(
|
||||
ProductMask.Note,
|
||||
ProductMask.Tag,
|
||||
ProductMask.CardId
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMask(): Block {
|
||||
val block = createBlock(BlockId.SettingsMask)
|
||||
mutableListOf(
|
||||
SettingsMask.IsReusable,
|
||||
SettingsMask.NeedActivation,
|
||||
SettingsMask.ForbidPurge,
|
||||
SettingsMask.AllowSelectBlockchain,
|
||||
SettingsMask.UseBlock,
|
||||
SettingsMask.OneApdu,
|
||||
SettingsMask.UseCvc,
|
||||
SettingsMask.AllowSwapPin,
|
||||
SettingsMask.AllowSwapPin2,
|
||||
SettingsMask.ForbidDefaultPin,
|
||||
SettingsMask.SmartSecurityDelay,
|
||||
SettingsMask.ProtectIssuerDataAgainstReplay,
|
||||
SettingsMask.SkipSecurityDelayIfValidated,
|
||||
SettingsMask.SkipPin2CvcIfValidated,
|
||||
SettingsMask.SkipSecurityDelayOnLinkedTerminal,
|
||||
SettingsMask.RestrictOverwriteExtraIssuerData
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskProtocolEnc(): Block {
|
||||
val block = createBlock(BlockId.SettingsMaskProtocolEnc)
|
||||
mutableListOf(
|
||||
SettingsMaskProtocolEnc.AllowUnencrypted,
|
||||
SettingsMaskProtocolEnc.AlloFastEncryption).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskNdef(): Block {
|
||||
val block = createBlock(BlockId.SettingsMaskNdef)
|
||||
mutableListOf(
|
||||
SettingsMaskNdef.UseNdef,
|
||||
SettingsMaskNdef.DynamicNdef,
|
||||
SettingsMaskNdef.DisablePrecomputedNdef,
|
||||
SettingsMaskNdef.Aar,
|
||||
SettingsMaskNdef.AarCustom
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun pins(): Block {
|
||||
val block = createBlock(BlockId.Pins)
|
||||
mutableListOf(Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, Pins.PauseBeforePin2)
|
||||
.forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun createBlock(id: Id): ListItemBlock {
|
||||
return ListItemBlock(id).apply { addItem(TextItem(id)) }
|
||||
}
|
||||
|
||||
private fun addPayload(block: Block, from: PersonalizeConfig) {
|
||||
block.payload[PayloadKey.incomingJson] = from
|
||||
}
|
||||
|
||||
private fun createItem(block: ListItemBlock, id: Id) {
|
||||
val holder = associations.get(id) ?: return
|
||||
val item = when {
|
||||
IdItemHelper.blockIdList.contains(id) -> TextItem(id, holder.get() as? String)
|
||||
IdItemHelper.listItemList.contains(id) -> ListItem(id, holder.list as List<KeyValue>, holder.get())
|
||||
IdItemHelper.boolList.contains(id) -> BoolItem(id, holder.get() as? Boolean)
|
||||
IdItemHelper.editTextList.contains(id) -> EditTextItem(id, holder.get() as? String)
|
||||
IdItemHelper.numberList.contains(id) -> NumberItem(id, holder.get() as? Number)
|
||||
else -> ListItemBlock(Additional.UNDEFINED)
|
||||
}
|
||||
block.addItem(item)
|
||||
}
|
||||
|
||||
fun toConfig(blockList: List<Block>, defaultConfig: PersonalizeConfig): PersonalizeConfig {
|
||||
return valueMapper.mapOnObject(blockList, defaultConfig)
|
||||
}
|
||||
|
||||
fun createCardConfig(applyConfig: PersonalizeConfig): CardConfig {
|
||||
val signingMethod = com.tangem.commands.SigningMethod.build(
|
||||
signHash = applyConfig.SigningMethod0,
|
||||
signRaw = applyConfig.SigningMethod1,
|
||||
signHashValidatedByIssuer = applyConfig.SigningMethod2,
|
||||
signRawValidatedByIssuer = applyConfig.SigningMethod3,
|
||||
signHashValidatedByIssuerAndWriteIssuerData = applyConfig.SigningMethod4,
|
||||
signRawValidatedByIssuerAndWriteIssuerData = applyConfig.SigningMethod5,
|
||||
signPos = applyConfig.SigningMethod6
|
||||
)
|
||||
|
||||
val isNote = applyConfig.cardData.product_note
|
||||
val isTag = applyConfig.cardData.product_tag
|
||||
val isIdCard = applyConfig.cardData.product_id_card
|
||||
|
||||
val productMaskBuilder = ProductMaskBuilder()
|
||||
if (isNote) productMaskBuilder.add(com.tangem.commands.ProductMask.note)
|
||||
if (isTag) productMaskBuilder.add(com.tangem.commands.ProductMask.tag)
|
||||
if (isIdCard) productMaskBuilder.add(com.tangem.commands.ProductMask.idCard)
|
||||
val productMask = productMaskBuilder.build()
|
||||
|
||||
var tokenSymbol: String? = null
|
||||
var tokenContractAddress: String? = null
|
||||
var tokenDecimal: Int? = null
|
||||
if (applyConfig.itsToken) {
|
||||
tokenSymbol = applyConfig.symbol
|
||||
tokenContractAddress = applyConfig.contractAddress
|
||||
tokenDecimal = applyConfig.decimal.toInt()
|
||||
}
|
||||
|
||||
val cardData = CardData(
|
||||
blockchainName = applyConfig.blockchain,
|
||||
batchId = applyConfig.cardData.batch,
|
||||
productMask = productMask,
|
||||
tokenSymbol = tokenSymbol,
|
||||
tokenContractAddress = tokenContractAddress,
|
||||
tokenDecimal = tokenDecimal,
|
||||
issuerName = null,
|
||||
manufactureDateTime = Calendar.getInstance().time,
|
||||
manufacturerSignature = null)
|
||||
|
||||
|
||||
val ndefs = mutableListOf<NdefRecord>()
|
||||
when (applyConfig.aar) {
|
||||
"None" -> null
|
||||
"--- CUSTOM ---" -> NdefRecord(NdefRecord.Type.AAR, applyConfig.aarCustom)
|
||||
else -> NdefRecord(NdefRecord.Type.AAR, applyConfig.aar)
|
||||
}?.let { ndefs.add(it) }
|
||||
|
||||
return CardConfig(
|
||||
"Tangem",
|
||||
"Tangem Test",
|
||||
applyConfig.series,
|
||||
applyConfig.startNumber,
|
||||
1000,
|
||||
applyConfig.PIN,
|
||||
applyConfig.PIN2,
|
||||
applyConfig.PIN3,
|
||||
applyConfig.hexCrExKey,
|
||||
applyConfig.CVC,
|
||||
applyConfig.pauseBeforePIN2.toInt(),
|
||||
applyConfig.smartSecurityDelay,
|
||||
EllipticCurve.byName(applyConfig.curveID) ?: EllipticCurve.Secp256k1,
|
||||
signingMethod,
|
||||
applyConfig.MaxSignatures.toInt(),
|
||||
applyConfig.isReusable,
|
||||
applyConfig.allowSwapPIN,
|
||||
applyConfig.allowSwapPIN2,
|
||||
applyConfig.useActivation,
|
||||
applyConfig.useCVC,
|
||||
applyConfig.useNDEF,
|
||||
applyConfig.useDynamicNDEF,
|
||||
applyConfig.oneApdu,
|
||||
applyConfig.useBlock,
|
||||
applyConfig.allowSelectBlockchain,
|
||||
applyConfig.forbidPurgeWallet,
|
||||
applyConfig.protocolAllowUnencrypted,
|
||||
applyConfig.protocolAllowStaticEncryption,
|
||||
applyConfig.protectIssuerDataAgainstReplay,
|
||||
applyConfig.forbidDefaultPIN,
|
||||
applyConfig.disablePrecomputedNDEF,
|
||||
applyConfig.skipSecurityDelayIfValidatedByIssuer,
|
||||
applyConfig.skipCheckPIN2andCVCIfValidatedByIssuer,
|
||||
applyConfig.skipSecurityDelayIfValidatedByLinkedTerminal,
|
||||
applyConfig.restrictOverwriteIssuerDataEx,
|
||||
applyConfig.requireTerminalTxSignature,
|
||||
applyConfig.requireTerminalCertSignature,
|
||||
applyConfig.checkPIN3onCard,
|
||||
applyConfig.createWallet,
|
||||
cardData,
|
||||
ndefs
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class IdItemHelper {
|
||||
companion object {
|
||||
val blockIdList = mutableListOf<com.tangem.tangemtest.ucase.variants.personalize.BlockId>(
|
||||
BlockId.CardNumber, BlockId.Common, BlockId.SigningMethod, BlockId.SignHashExProp, BlockId.Denomination,
|
||||
BlockId.Token, BlockId.ProdMask, BlockId.SettingsMask, BlockId.SettingsMaskProtocolEnc,
|
||||
BlockId.SettingsMaskNdef, BlockId.Pins
|
||||
)
|
||||
|
||||
val listItemList = mutableListOf(Common.Curve, Common.Blockchain, SettingsMaskNdef.Aar, Pins.PauseBeforePin2)
|
||||
|
||||
val boolList = mutableListOf(
|
||||
Common.CreateWallet, SigningMethod.SignTx, SigningMethod.SignTxRaw, SigningMethod.SignValidatedTx,
|
||||
SigningMethod.SignValidatedTxRaw, SigningMethod.SignValidatedTxIssuer,
|
||||
SigningMethod.SignValidatedTxRawIssuer, SigningMethod.SignExternal, SignHashExProp.RequireTerminalCertSig,
|
||||
SignHashExProp.RequireTerminalTxSig, SignHashExProp.CheckPin3, Denomination.WriteOnPersonalize, Token.ItsToken,
|
||||
ProductMask.Note, ProductMask.Tag, ProductMask.CardId, SettingsMask.IsReusable, SettingsMask.NeedActivation,
|
||||
SettingsMask.ForbidPurge, SettingsMask.AllowSelectBlockchain, SettingsMask.UseBlock, SettingsMask.OneApdu,
|
||||
SettingsMask.UseCvc, SettingsMask.AllowSwapPin, SettingsMask.AllowSwapPin2, SettingsMask.ForbidDefaultPin,
|
||||
SettingsMask.SmartSecurityDelay, SettingsMask.ProtectIssuerDataAgainstReplay,
|
||||
SettingsMask.SkipSecurityDelayIfValidated, SettingsMask.SkipPin2CvcIfValidated,
|
||||
SettingsMask.SkipSecurityDelayOnLinkedTerminal, SettingsMask.RestrictOverwriteExtraIssuerData,
|
||||
SettingsMaskProtocolEnc.AllowUnencrypted, SettingsMaskProtocolEnc.AlloFastEncryption,
|
||||
SettingsMaskNdef.UseNdef, SettingsMaskNdef.DynamicNdef, SettingsMaskNdef.DisablePrecomputedNdef
|
||||
)
|
||||
|
||||
val editTextList = mutableListOf(
|
||||
CardNumber.Series, Common.BlockchainCustom, SignHashExProp.CryptoExKey, Token.Symbol,
|
||||
Token.ContractAddress, Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, SettingsMaskNdef.AarCustom
|
||||
)
|
||||
|
||||
val numberList = mutableListOf(
|
||||
CardNumber.Number, Common.MaxSignatures, SignHashExProp.PinLessFloorLimit, Denomination.Denomination, Token.Decimal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class JsonTails(
|
||||
val count: Int,
|
||||
val numberFormat: String,
|
||||
val issuerData: Any?,
|
||||
val releaseVersion: Boolean,
|
||||
val issuerName: String
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo
|
||||
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
|
||||
class ItemTypes {
|
||||
|
||||
val blockIdList = mutableListOf(
|
||||
BlockId.CardNumber, BlockId.Common, BlockId.SigningMethod, BlockId.SignHashExProp, BlockId.Denomination,
|
||||
BlockId.Token, BlockId.ProdMask, BlockId.SettingsMask, BlockId.SettingsMaskProtocolEnc,
|
||||
BlockId.SettingsMaskNdef, BlockId.Pins
|
||||
)
|
||||
|
||||
val listItemList = mutableListOf(Common.Curve, Common.Blockchain, SettingsMaskNdef.Aar, Pins.PauseBeforePin2)
|
||||
|
||||
val boolList = mutableListOf(
|
||||
Common.CreateWallet, SigningMethod.SignTx, SigningMethod.SignTxRaw, SigningMethod.SignValidatedTx,
|
||||
SigningMethod.SignValidatedTxRaw, SigningMethod.SignValidatedTxIssuer,
|
||||
SigningMethod.SignValidatedTxRawIssuer, SigningMethod.SignExternal, SignHashExProp.RequireTerminalCertSig,
|
||||
SignHashExProp.RequireTerminalTxSig, SignHashExProp.CheckPin3, Denomination.WriteOnPersonalize, Token.ItsToken,
|
||||
ProductMask.Note, ProductMask.Tag, ProductMask.IdCard, ProductMask.IdIssuerCard,SettingsMask.IsReusable, SettingsMask.NeedActivation,
|
||||
SettingsMask.ForbidPurge, SettingsMask.AllowSelectBlockchain, SettingsMask.UseBlock, SettingsMask.OneApdu,
|
||||
SettingsMask.UseCvc, SettingsMask.AllowSwapPin, SettingsMask.AllowSwapPin2, SettingsMask.ForbidDefaultPin,
|
||||
SettingsMask.SmartSecurityDelay, SettingsMask.ProtectIssuerDataAgainstReplay,
|
||||
SettingsMask.SkipSecurityDelayIfValidated, SettingsMask.SkipPin2CvcIfValidated,
|
||||
SettingsMask.SkipSecurityDelayOnLinkedTerminal, SettingsMask.RestrictOverwriteExtraIssuerData,
|
||||
SettingsMaskProtocolEnc.AllowUnencrypted, SettingsMaskProtocolEnc.AllowStaticEncryption,
|
||||
SettingsMaskNdef.UseNdef, SettingsMaskNdef.DynamicNdef, SettingsMaskNdef.DisablePrecomputedNdef
|
||||
)
|
||||
|
||||
val editTextList = mutableListOf(
|
||||
CardNumber.Series, CardNumber.BatchId, Common.BlockchainCustom, SignHashExProp.CryptoExKey, Token.Symbol,
|
||||
Token.ContractAddress, Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, SettingsMaskNdef.AarCustom
|
||||
)
|
||||
|
||||
val numberList = mutableListOf(
|
||||
CardNumber.Number, Common.MaxSignatures, SignHashExProp.PinLessFloorLimit, Denomination.Denomination, Token.Decimal
|
||||
)
|
||||
|
||||
val hiddenList = mutableListOf(
|
||||
CardNumber.Series, CardNumber.BatchId, Pins.Pin3, SigningMethod.SignExternal,
|
||||
SignHashExProp.CryptoExKey, SignHashExProp.CheckPin3, SettingsMask.OneApdu,
|
||||
SettingsMask.UseBlock, SettingsMask.ProtectIssuerDataAgainstReplay,
|
||||
SignHashExProp.RequireTerminalCertSig, SignHashExProp.RequireTerminalTxSig
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -1,45 +1,44 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter
|
||||
package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo
|
||||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Block
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemsToModel
|
||||
import com.tangem.tangemtest._arch.structure.impl.KeyValue
|
||||
import com.tangem.tangemtest._arch.structure.impl.ListValueWrapper
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigValuesHolder
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ValueMapper {
|
||||
private val default: IdToValueAssociations = IdToValueAssociations()
|
||||
private val updatedByItemList: IdToValueAssociations = IdToValueAssociations()
|
||||
class ItemsToPersonalizeConfig : ItemsToModel<PersonalizeConfig> {
|
||||
protected val valuesHolder = PersonalizeConfigValuesHolder()
|
||||
|
||||
|
||||
fun mapOnObject(itemList: List<Item>, defaultConfig: PersonalizeConfig): PersonalizeConfig {
|
||||
default.init(defaultConfig)
|
||||
updatedByItemList.init(defaultConfig)
|
||||
startMapping(itemList)
|
||||
return createConfig()
|
||||
override fun convert(from: List<Item>, default: PersonalizeConfig): PersonalizeConfig {
|
||||
valuesHolder.init(default)
|
||||
mapListItems(from)
|
||||
return createModel()
|
||||
}
|
||||
|
||||
private fun startMapping(itemList: List<Item>) {
|
||||
itemList.forEach { item -> mapItem(item) }
|
||||
private fun mapListItems(itemList: List<Item>) {
|
||||
itemList.forEach { item -> mapItemToHolder(item) }
|
||||
}
|
||||
|
||||
private fun mapItem(item: Item) {
|
||||
private fun mapItemToHolder(item: Item) {
|
||||
when (item) {
|
||||
is Block -> startMapping(item.itemList)
|
||||
is Block -> mapListItems(item.itemList)
|
||||
is BaseItem<*> -> {
|
||||
val value = updatedByItemList.get(item.id) ?: return
|
||||
value.set(item.viewModel.data)
|
||||
val defValue = valuesHolder.get(item.id) ?: return
|
||||
defValue.set(item.viewModel.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConfig(): PersonalizeConfig {
|
||||
private fun createModel(): PersonalizeConfig {
|
||||
val export = PersonalizeConfig()
|
||||
export.series = getTyped(CardNumber.Series)
|
||||
export.startNumber = getTyped(CardNumber.Number)
|
||||
|
|
@ -68,7 +67,8 @@ class ValueMapper {
|
|||
export.decimal = getTyped(Token.Decimal)
|
||||
export.cardData = export.cardData.apply { this.product_note = getTyped(ProductMask.Note) }
|
||||
export.cardData = export.cardData.apply { this.product_tag = getTyped(ProductMask.Tag) }
|
||||
export.cardData = export.cardData.apply { this.product_id_card = getTyped(ProductMask.CardId) }
|
||||
export.cardData = export.cardData.apply { this.product_id_card = getTyped(ProductMask.IdCard) }
|
||||
export.cardData = export.cardData.apply { this.product_id_issuer = getTyped(ProductMask.IdIssuerCard) }
|
||||
export.isReusable = getTyped(SettingsMask.IsReusable)
|
||||
export.useActivation = getTyped(SettingsMask.NeedActivation)
|
||||
export.forbidPurgeWallet = getTyped(SettingsMask.ForbidPurge)
|
||||
|
|
@ -86,7 +86,7 @@ class ValueMapper {
|
|||
export.skipSecurityDelayIfValidatedByLinkedTerminal = getTyped(SettingsMask.SkipSecurityDelayOnLinkedTerminal)
|
||||
export.restrictOverwriteIssuerDataEx = getTyped(SettingsMask.RestrictOverwriteExtraIssuerData)
|
||||
export.protocolAllowUnencrypted = getTyped(SettingsMaskProtocolEnc.AllowUnencrypted)
|
||||
export.allowFastEncryption = getTyped(SettingsMaskProtocolEnc.AlloFastEncryption)
|
||||
export.protocolAllowStaticEncryption = getTyped(SettingsMaskProtocolEnc.AllowStaticEncryption)
|
||||
export.useNDEF = getTyped(SettingsMaskNdef.UseNdef)
|
||||
export.useDynamicNDEF = getTyped(SettingsMaskNdef.DynamicNdef)
|
||||
export.disablePrecomputedNDEF = getTyped(SettingsMaskNdef.DisablePrecomputedNdef)
|
||||
|
|
@ -101,12 +101,12 @@ class ValueMapper {
|
|||
}
|
||||
|
||||
private inline fun <reified Type> getTyped(id: Id): Type {
|
||||
return getTypedBy<Type>(updatedByItemList, id) ?: getTypedBy<Type>(default, id)!!
|
||||
return getTypedBy<Type>(valuesHolder, id)!!
|
||||
}
|
||||
|
||||
private inline fun <reified Type> getTypedBy(associations: IdToValueAssociations, id: Id): Type? {
|
||||
private inline fun <reified Type> getTypedBy(holder: PersonalizeConfigValuesHolder, id: Id): Type? {
|
||||
Log.d(this, "getTyped for id: $id")
|
||||
var typedValue = associations.get(id)?.get()
|
||||
var typedValue = holder.get(id)?.get()
|
||||
|
||||
typedValue = when (typedValue) {
|
||||
is ListValueWrapper -> (typedValue.selectedItem as KeyValue).value as Type
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo
|
||||
|
||||
import com.tangem.commands.CardData
|
||||
import com.tangem.commands.EllipticCurve
|
||||
import com.tangem.commands.ProductMaskBuilder
|
||||
import com.tangem.commands.personalization.entities.CardConfig
|
||||
import com.tangem.commands.personalization.entities.NdefRecord
|
||||
import com.tangem.tangemtest._arch.structure.Additional
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.*
|
||||
import com.tangem.tangemtest._arch.structure.impl.*
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigValuesHolder
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizeConfigToItem : ModelToItems<PersonalizeConfig> {
|
||||
private val valuesHolder = PersonalizeConfigValuesHolder()
|
||||
private val itemTypes = ItemTypes()
|
||||
|
||||
override fun convert(from: PersonalizeConfig): List<Item> {
|
||||
valuesHolder.init(from)
|
||||
val blocList = mutableListOf<Item>()
|
||||
blocList.add(cardNumber())
|
||||
blocList.add(common())
|
||||
blocList.add(signingMethod())
|
||||
blocList.add(signHashExProperties())
|
||||
blocList.add(denomination())
|
||||
blocList.add(token())
|
||||
blocList.add(productMask())
|
||||
blocList.add(settingsMask())
|
||||
blocList.add(settingsMaskProtocolEnc())
|
||||
blocList.add(settingsMaskNdef())
|
||||
blocList.add(pins())
|
||||
val payloadBlock = ListItemBlock(Additional.JSON_TAILS)
|
||||
addPayload(payloadBlock, from)
|
||||
blocList.add(payloadBlock)
|
||||
blocList.iterate {
|
||||
if (itemTypes.hiddenList.contains(it.id)) {
|
||||
(it as BaseItem<*>)?.viewModel.viewState.isHiddenField = true
|
||||
}
|
||||
}
|
||||
return blocList
|
||||
}
|
||||
|
||||
private fun cardNumber(): Block {
|
||||
val block = createBlock(BlockId.CardNumber)
|
||||
mutableListOf(
|
||||
CardNumber.Series,
|
||||
CardNumber.Number,
|
||||
CardNumber.BatchId
|
||||
).forEach { createItem(block, it as Id) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun common(): Block {
|
||||
val block = createBlock(BlockId.Common)
|
||||
mutableListOf(
|
||||
Common.Curve,
|
||||
Common.Blockchain,
|
||||
Common.BlockchainCustom,
|
||||
Common.MaxSignatures,
|
||||
Common.CreateWallet
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signingMethod(): Block {
|
||||
val block = createBlock(BlockId.SigningMethod)
|
||||
mutableListOf(
|
||||
SigningMethod.SignTx,
|
||||
SigningMethod.SignTxRaw,
|
||||
SigningMethod.SignValidatedTx,
|
||||
SigningMethod.SignValidatedTxRaw,
|
||||
SigningMethod.SignValidatedTxIssuer,
|
||||
SigningMethod.SignValidatedTxRawIssuer,
|
||||
SigningMethod.SignExternal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signHashExProperties(): Block {
|
||||
val block = createBlock(BlockId.SignHashExProp)
|
||||
mutableListOf(
|
||||
SignHashExProp.PinLessFloorLimit,
|
||||
SignHashExProp.CryptoExKey,
|
||||
SignHashExProp.RequireTerminalCertSig,
|
||||
SignHashExProp.RequireTerminalTxSig,
|
||||
SignHashExProp.CheckPin3
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun denomination(): Block {
|
||||
val block = createBlock(BlockId.Denomination)
|
||||
mutableListOf(
|
||||
Denomination.WriteOnPersonalize,
|
||||
Denomination.Denomination
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun token(): Block {
|
||||
val block = createBlock(BlockId.Token)
|
||||
mutableListOf(
|
||||
Token.ItsToken,
|
||||
Token.Symbol,
|
||||
Token.ContractAddress,
|
||||
Token.Decimal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun productMask(): Block {
|
||||
val block = createBlock(BlockId.ProdMask)
|
||||
mutableListOf(
|
||||
ProductMask.Note,
|
||||
ProductMask.Tag,
|
||||
ProductMask.IdCard,
|
||||
ProductMask.IdIssuerCard
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMask(): Block {
|
||||
val block = createBlock(BlockId.SettingsMask)
|
||||
mutableListOf(
|
||||
SettingsMask.IsReusable,
|
||||
SettingsMask.NeedActivation,
|
||||
SettingsMask.ForbidPurge,
|
||||
SettingsMask.AllowSelectBlockchain,
|
||||
SettingsMask.UseBlock,
|
||||
SettingsMask.OneApdu,
|
||||
SettingsMask.UseCvc,
|
||||
SettingsMask.AllowSwapPin,
|
||||
SettingsMask.AllowSwapPin2,
|
||||
SettingsMask.ForbidDefaultPin,
|
||||
SettingsMask.SmartSecurityDelay,
|
||||
SettingsMask.ProtectIssuerDataAgainstReplay,
|
||||
SettingsMask.SkipSecurityDelayIfValidated,
|
||||
SettingsMask.SkipPin2CvcIfValidated,
|
||||
SettingsMask.SkipSecurityDelayOnLinkedTerminal,
|
||||
SettingsMask.RestrictOverwriteExtraIssuerData
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskProtocolEnc(): Block {
|
||||
val block = createBlock(BlockId.SettingsMaskProtocolEnc)
|
||||
mutableListOf(
|
||||
SettingsMaskProtocolEnc.AllowUnencrypted,
|
||||
SettingsMaskProtocolEnc.AllowStaticEncryption
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskNdef(): Block {
|
||||
val block = createBlock(BlockId.SettingsMaskNdef)
|
||||
mutableListOf(
|
||||
SettingsMaskNdef.UseNdef,
|
||||
SettingsMaskNdef.DynamicNdef,
|
||||
SettingsMaskNdef.DisablePrecomputedNdef,
|
||||
SettingsMaskNdef.Aar,
|
||||
SettingsMaskNdef.AarCustom
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun pins(): Block {
|
||||
val block = createBlock(BlockId.Pins)
|
||||
mutableListOf(Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, Pins.PauseBeforePin2)
|
||||
.forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun createBlock(id: Id): ListItemBlock {
|
||||
return ListItemBlock(id).apply { addItem(TextItem(id)) }
|
||||
}
|
||||
|
||||
private fun addPayload(block: Block, from: PersonalizeConfig) {
|
||||
block.payload[PayloadKey.incomingJson] = from
|
||||
}
|
||||
|
||||
private fun createItem(block: ListItemBlock, id: Id) {
|
||||
val holder = valuesHolder.get(id) ?: return
|
||||
val item = when {
|
||||
itemTypes.blockIdList.contains(id) -> TextItem(id, holder.get() as? String)
|
||||
itemTypes.listItemList.contains(id) -> ListItem(id, holder.list as List<KeyValue>, holder.get())
|
||||
itemTypes.boolList.contains(id) -> BoolItem(id, holder.get() as? Boolean)
|
||||
itemTypes.editTextList.contains(id) -> EditTextItem(id, holder.get() as? String)
|
||||
itemTypes.numberList.contains(id) -> NumberItem(id, holder.get() as? Number)
|
||||
else -> ListItemBlock(Additional.UNDEFINED)
|
||||
}
|
||||
block.addItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
class PersonalizeConfigToCardConfig : Converter<PersonalizeConfig, CardConfig> {
|
||||
|
||||
override fun convert(from: PersonalizeConfig): CardConfig {
|
||||
val signingMethod = com.tangem.commands.SigningMethod.build(
|
||||
signHash = from.SigningMethod0,
|
||||
signRaw = from.SigningMethod1,
|
||||
signHashValidatedByIssuer = from.SigningMethod2,
|
||||
signRawValidatedByIssuer = from.SigningMethod3,
|
||||
signHashValidatedByIssuerAndWriteIssuerData = from.SigningMethod4,
|
||||
signRawValidatedByIssuerAndWriteIssuerData = from.SigningMethod5,
|
||||
signPos = from.SigningMethod6
|
||||
)
|
||||
|
||||
val isNote = from.cardData.product_note
|
||||
val isTag = from.cardData.product_tag
|
||||
val isIdCard = from.cardData.product_id_card
|
||||
val isIdIssuer = from.cardData.product_id_issuer
|
||||
|
||||
val productMaskBuilder = ProductMaskBuilder()
|
||||
if (isNote) productMaskBuilder.add(com.tangem.commands.ProductMask.note)
|
||||
if (isTag) productMaskBuilder.add(com.tangem.commands.ProductMask.tag)
|
||||
if (isIdCard) productMaskBuilder.add(com.tangem.commands.ProductMask.idCard)
|
||||
if (isIdIssuer) productMaskBuilder.add(com.tangem.commands.ProductMask.idIssuer)
|
||||
val productMask = productMaskBuilder.build()
|
||||
|
||||
var tokenSymbol: String? = null
|
||||
var tokenContractAddress: String? = null
|
||||
var tokenDecimal: Int? = null
|
||||
if (from.itsToken) {
|
||||
tokenSymbol = from.symbol
|
||||
tokenContractAddress = from.contractAddress
|
||||
tokenDecimal = from.decimal.toInt()
|
||||
}
|
||||
|
||||
val blockchain = if (from.blockchain.isNotEmpty()) from.blockchain else from.blockchainCustom
|
||||
val cardData = CardData(
|
||||
blockchainName = blockchain,
|
||||
batchId = from.batchId,
|
||||
productMask = productMask,
|
||||
tokenSymbol = tokenSymbol,
|
||||
tokenContractAddress = tokenContractAddress,
|
||||
tokenDecimal = tokenDecimal,
|
||||
issuerName = null,
|
||||
manufactureDateTime = Calendar.getInstance().time,
|
||||
manufacturerSignature = null)
|
||||
|
||||
|
||||
val ndefs = mutableListOf<NdefRecord>()
|
||||
when (from.aar) {
|
||||
"None" -> null
|
||||
"--- CUSTOM ---" -> NdefRecord(NdefRecord.Type.AAR, from.aarCustom)
|
||||
else -> NdefRecord(NdefRecord.Type.AAR, from.aar)
|
||||
}?.let { ndefs.add(it) }
|
||||
|
||||
return CardConfig(
|
||||
"Tangem",
|
||||
"Tangem Test",
|
||||
from.series,
|
||||
from.startNumber,
|
||||
1000,
|
||||
from.PIN,
|
||||
from.PIN2,
|
||||
from.PIN3,
|
||||
from.hexCrExKey,
|
||||
from.CVC,
|
||||
from.pauseBeforePIN2.toInt(),
|
||||
from.smartSecurityDelay,
|
||||
EllipticCurve.byName(from.curveID) ?: EllipticCurve.Secp256k1,
|
||||
signingMethod,
|
||||
from.MaxSignatures.toInt(),
|
||||
from.isReusable,
|
||||
from.allowSwapPIN,
|
||||
from.allowSwapPIN2,
|
||||
from.useActivation,
|
||||
from.useCVC,
|
||||
from.useNDEF,
|
||||
from.useDynamicNDEF,
|
||||
from.oneApdu,
|
||||
from.useBlock,
|
||||
from.allowSelectBlockchain,
|
||||
from.forbidPurgeWallet,
|
||||
from.protocolAllowUnencrypted,
|
||||
from.protocolAllowStaticEncryption,
|
||||
from.protectIssuerDataAgainstReplay,
|
||||
from.forbidDefaultPIN,
|
||||
from.disablePrecomputedNDEF,
|
||||
from.skipSecurityDelayIfValidatedByIssuer,
|
||||
from.skipCheckPIN2andCVCIfValidatedByIssuer,
|
||||
from.skipSecurityDelayIfValidatedByLinkedTerminal,
|
||||
from.restrictOverwriteIssuerDataEx,
|
||||
from.requireTerminalTxSignature,
|
||||
from.requireTerminalCertSignature,
|
||||
from.checkPIN3onCard,
|
||||
from.createWallet,
|
||||
cardData,
|
||||
ndefs
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,11 +8,12 @@ class PersonalizeConfig {
|
|||
// Card number
|
||||
var series = "BB"
|
||||
var startNumber: Long = 300000000000
|
||||
var batchId = "ffff"
|
||||
|
||||
|
||||
// Common
|
||||
var curveID = "ed25519"
|
||||
var blockchain = "BTC"
|
||||
var blockchain = "BTC/test"
|
||||
var blockchainCustom = ""
|
||||
var MaxSignatures: Long = 100
|
||||
var createWallet = false
|
||||
|
|
@ -71,7 +72,6 @@ class PersonalizeConfig {
|
|||
|
||||
// Settings mask - protocol encryption
|
||||
var protocolAllowUnencrypted = true
|
||||
var allowFastEncryption = false
|
||||
var protocolAllowStaticEncryption = true
|
||||
|
||||
|
||||
|
|
@ -105,4 +105,5 @@ class CardData {
|
|||
var product_note = true
|
||||
var product_tag = false
|
||||
var product_id_card = false
|
||||
var product_id_issuer = false
|
||||
}
|
||||
|
|
@ -9,28 +9,32 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.CardManager
|
||||
import com.tangem.tangem_sdk_new.extensions.init
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Block
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._main.MainViewModel
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManagerFactory
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.resources.ActionType
|
||||
import com.tangem.tangemtest.ucase.tunnel.ActionView
|
||||
import com.tangem.tangemtest.ucase.tunnel.CardError
|
||||
import com.tangem.tangemtest.ucase.tunnel.ItemError
|
||||
import com.tangem.tangemtest.ucase.ui.ActionViewModelFactory
|
||||
import com.tangem.tangemtest.ucase.ui.ParamsViewModel
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.WidgetBuilder
|
||||
import kotlinx.android.synthetic.main.fg_personalize.*
|
||||
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizeFragment : Fragment() {
|
||||
class PersonalizeFragment : Fragment(), ActionView {
|
||||
|
||||
private val mainActivityVM: MainViewModel by activityViewModels()
|
||||
private val personalizeVM: PersonalizeViewModel by viewModels { PersonalizeViewModelFactory(PersonalizeConfig()) }
|
||||
|
|
@ -38,10 +42,9 @@ class PersonalizeFragment : Fragment() {
|
|||
private val itemsManager: ItemsManager by lazy { ParamsManagerFactory.createFactory().get(ActionType.Personalize)!! }
|
||||
private val paramsVM: ParamsViewModel by viewModels() { ActionViewModelFactory(itemsManager) }
|
||||
|
||||
private val blockContainer: ViewGroup by lazy {
|
||||
mainView.findViewById<LinearLayout>(R.id.ll_container)
|
||||
}
|
||||
private lateinit var mainView: View
|
||||
private val blockContainer: ViewGroup by lazy { mainView.findViewById<LinearLayout>(R.id.ll_container) }
|
||||
private val actionFab: FloatingActionButton by lazy { mainView.findViewById<FloatingActionButton>(R.id.fab_action) }
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
Log.d(this, "onCreateView")
|
||||
|
|
@ -52,11 +55,16 @@ class PersonalizeFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val blockList = mutableListOf<Block>()
|
||||
val blockList = mutableListOf<Item>()
|
||||
personalizeVM.ldBlockList.observe(viewLifecycleOwner, Observer { list ->
|
||||
blockList.clear()
|
||||
blockList.addAll(list)
|
||||
blockList.forEach { WidgetBuilder().build(it, blockContainer) }
|
||||
paramsVM.attachToPayload(mutableMapOf(
|
||||
PayloadKey.actionView to this as ActionView,
|
||||
PayloadKey.itemList to blockList
|
||||
))
|
||||
|
||||
})
|
||||
mainActivityVM.ldDescriptionSwitch.observe(viewLifecycleOwner, Observer {
|
||||
personalizeVM.toggleDescriptionVisibility(it)
|
||||
|
|
@ -70,16 +78,34 @@ class PersonalizeFragment : Fragment() {
|
|||
})
|
||||
paramsVM.seError.observe(viewLifecycleOwner, Observer { showSnackbarMessage(it) })
|
||||
|
||||
fab_action?.setOnClickListener {
|
||||
val cardConfig = personalizeVM.createCardConfig(personalizeVM.createConfig(blockList))
|
||||
paramsVM.attachToPayload(mutableMapOf(PayloadKey.cardConfig to cardConfig))
|
||||
paramsVM.invokeMainAction()
|
||||
}
|
||||
actionFab.setOnClickListener { paramsVM.invokeMainAction() }
|
||||
}
|
||||
|
||||
protected fun showSnackbarMessage(message: String) {
|
||||
Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun showActionFab(show: Boolean) {
|
||||
if (show) actionFab.show() else actionFab.hide()
|
||||
}
|
||||
|
||||
override fun showSnackbar(id: Id) {
|
||||
// MainResourceHolder.safeGet<>()
|
||||
when (id) {
|
||||
CardError.NotPersonalized -> showSnackbar(R.string.card_error_not_personalized)
|
||||
ItemError.BadSeries -> showSnackbar(R.string.card_error_bad_series)
|
||||
ItemError.BadCardNumber -> showSnackbar(R.string.card_error_bad_series_number)
|
||||
else -> showSnackbar(requireContext().getString(R.string.unknown))
|
||||
}
|
||||
}
|
||||
|
||||
override fun showSnackbar(id: Int) {
|
||||
showSnackbar(requireContext().getString(id))
|
||||
}
|
||||
|
||||
override fun showSnackbar(message: String) {
|
||||
Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ import android.view.View
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.gson.Gson
|
||||
import com.tangem.commands.personalization.entities.CardConfig
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Block
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.iterate
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigConverter
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig
|
||||
|
||||
|
|
@ -20,32 +19,14 @@ class PersonalizeViewModelFactory(private val config: PersonalizeConfig) : ViewM
|
|||
|
||||
class PersonalizeViewModel(private val config: PersonalizeConfig) : ViewModel() {
|
||||
|
||||
val ldBlockList: MutableLiveData<List<Block>> by lazy { MutableLiveData(initBlockList()) }
|
||||
val ldBlockList: MutableLiveData<List<Item>> by lazy { MutableLiveData(initBlockList()) }
|
||||
|
||||
private fun initBlockList(): List<Block> = createBlocksFromConfig(config)
|
||||
|
||||
fun createBlocksFromConfig(config: PersonalizeConfig): List<Block> {
|
||||
return PersonalizeConfigConverter().toBlock(config)
|
||||
}
|
||||
|
||||
fun createConfig(blocList: List<Block>): PersonalizeConfig {
|
||||
return PersonalizeConfigConverter().toConfig(blocList, PersonalizeConfig())
|
||||
}
|
||||
|
||||
fun createCardConfig(config: PersonalizeConfig): CardConfig {
|
||||
return PersonalizeConfigConverter().createCardConfig(config)
|
||||
}
|
||||
|
||||
fun convertToJson(config: PersonalizeConfig): String {
|
||||
return Gson().toJson(config)
|
||||
}
|
||||
private fun initBlockList(): List<Item> = PersonalizeConfigConverter().convert(config)
|
||||
|
||||
fun toggleDescriptionVisibility(state: Boolean) {
|
||||
ldBlockList.value?.forEach { block ->
|
||||
block.itemList.forEach { item ->
|
||||
val vm = item as? BaseItem<*> ?: return@forEach
|
||||
vm.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE
|
||||
}
|
||||
ldBlockList.value?.iterate {
|
||||
val baseItem = it as? BaseItem<*> ?: return@iterate
|
||||
baseItem.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,12 @@ abstract class BaseWidget<D>(
|
|||
) : ViewWidget, DataWidget<D> {
|
||||
|
||||
override val view: View = inflate(getLayoutId(), parent)
|
||||
|
||||
init {
|
||||
if (dataItem.viewModel.viewState.isHiddenField) {
|
||||
view.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BaseBlockWidget(parent: ViewGroup) : BlockViewWidget {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.google.android.material.textfield.TextInputLayout
|
|||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.impl.EditTextItem
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.abstraction.getResNameId
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.moveCursorToEnd
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
||||
/**
|
||||
|
|
@ -32,10 +33,13 @@ class EditTextWidget(parent: ViewGroup, data: EditTextItem) : DescriptionWidget<
|
|||
tilItem.hint = tilItem.context.getString(getResNameId())
|
||||
etItem.setText(dataItem.viewModel.data)
|
||||
etItem.addTextChangedListener(watcher)
|
||||
dataItem.viewModel.onDataUpdated = {
|
||||
etItem.removeTextChangedListener(watcher)
|
||||
etItem.setText(it)
|
||||
etItem.addTextChangedListener(watcher)
|
||||
}
|
||||
dataItem.viewModel.onDataUpdated = { silentUpdate(it) }
|
||||
}
|
||||
|
||||
private fun silentUpdate(value: String?) {
|
||||
etItem.removeTextChangedListener(watcher)
|
||||
etItem.setText(value)
|
||||
etItem.moveCursorToEnd()
|
||||
etItem.addTextChangedListener(watcher)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,17 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.impl.item
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.InputFilter
|
||||
import android.text.TextWatcher
|
||||
import android.view.ViewGroup
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.impl.NumberItem
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.CardNumber
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.abstraction.getResNameId
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.addInputFilter
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.moveCursorToEnd
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
||||
/**
|
||||
|
|
@ -21,7 +25,7 @@ class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget<Numb
|
|||
|
||||
private val watcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
dataItem.viewModel.updateDataByView(getIntValue(stringOf(s)))
|
||||
dataItem.viewModel.updateDataByView(getValue(stringOf(s)))
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
|
|
@ -30,16 +34,23 @@ class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget<Numb
|
|||
|
||||
init {
|
||||
tilItem.hint = tilItem.context.getString(getResNameId())
|
||||
|
||||
//TODO: remove from Widget
|
||||
if (dataItem.id == CardNumber.Number) etItem.addInputFilter(InputFilter.LengthFilter(13))
|
||||
|
||||
etItem.setText(stringOf(dataItem.viewModel.data))
|
||||
etItem.addTextChangedListener(watcher)
|
||||
dataItem.viewModel.onDataUpdated = {
|
||||
etItem.removeTextChangedListener(watcher)
|
||||
etItem.setText(stringOf(it))
|
||||
etItem.addTextChangedListener(watcher)
|
||||
}
|
||||
dataItem.viewModel.onDataUpdated = { silentUpdate(it) }
|
||||
}
|
||||
|
||||
private fun getIntValue(value: String): Long {
|
||||
private fun silentUpdate(value: Number?) {
|
||||
etItem.removeTextChangedListener(watcher)
|
||||
etItem.setText(stringOf(value))
|
||||
etItem.moveCursorToEnd()
|
||||
etItem.addTextChangedListener(watcher)
|
||||
}
|
||||
|
||||
private fun getValue(value: String): Long {
|
||||
return if (value.isEmpty()) 0L else value.toLong()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,20 +17,20 @@ import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class SpinnerWidget(parent: ViewGroup, data: ListItem) : DescriptionWidget<ListValueWrapper>(parent, data) {
|
||||
class SpinnerWidget(parent: ViewGroup, listItem: ListItem) : DescriptionWidget<ListValueWrapper>(parent, listItem) {
|
||||
override fun getLayoutId(): Int = R.layout.w_personalize_item_spinner
|
||||
|
||||
private val data: ListValueWrapper = listItem.getData()!!
|
||||
|
||||
private val spItem = view.findViewById<Spinner>(R.id.sp_item)
|
||||
private val spAdapter = SpItemAdapter(dataItem.viewModel.data?.itemList)
|
||||
private val spAdapter = SpItemAdapter(data.itemList)
|
||||
|
||||
private val onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
val vmData = dataItem.viewModel.data ?: return
|
||||
|
||||
vmData.selectedItem = vmData.itemList[position]
|
||||
dataItem.viewModel.updateDataByView(vmData)
|
||||
data.selectedItem = data.itemList[position]
|
||||
dataItem.viewModel.updateDataByView(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -38,6 +38,9 @@ class SpinnerWidget(parent: ViewGroup, data: ListItem) : DescriptionWidget<ListV
|
|||
val name = view.findViewById<TextView>(R.id.tv_name)
|
||||
name.setText(getResNameId())
|
||||
spItem.adapter = spAdapter
|
||||
spAdapter.getItemPosition(stringOf(data.selectedItem))?.let {
|
||||
spItem.setSelection(it)
|
||||
}
|
||||
spItem.onItemSelectedListener = onItemSelectedListener
|
||||
dataItem.viewModel.onDataUpdated = {
|
||||
it?.apply {
|
||||
|
|
@ -81,4 +84,9 @@ class SpItemAdapter(list: List<KeyValue>?) : BaseAdapter() {
|
|||
override fun getItemId(position: Int): Long = position.toLong()
|
||||
|
||||
override fun getCount(): Int = itemList.size
|
||||
|
||||
fun getItemPosition(item: String): Int? {
|
||||
val kv = itemList.firstOrNull { it.value == item } ?: return null
|
||||
return itemList.indexOf(kv)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
<string name="switch_description">Docs</string>
|
||||
|
||||
<string name="card_error_not_personalized">Your card hasn\'t been personalized yet. You need to run personalize command first.</string>
|
||||
<string name="card_error_bad_series">Wrong Series</string>
|
||||
<string name="card_error_bad_series_number">Wrong Series and Number</string>
|
||||
|
||||
<string name="stub">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit</string>
|
||||
<!-- <string name="stub">Sed ut perspiciatis unde omnis iste natus</string>-->
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
<string name="pers_item_series">Series</string>
|
||||
<string name="pers_item_number">Number</string>
|
||||
<string name="pers_item_batch_id">Batch ID</string>
|
||||
<string name="pers_item_curve">Curve</string>
|
||||
<string name="pers_item_blockchain">Blockchain</string>
|
||||
<string name="pers_item_custom_blockchain">Custom blockchain</string>
|
||||
|
|
@ -43,6 +44,7 @@
|
|||
<string name="pers_item_note">Note</string>
|
||||
<string name="pers_item_tag">Tag</string>
|
||||
<string name="pers_item_id_card">ID card</string>
|
||||
<string name="pers_item_id_issuer_card">ID Issuer</string>
|
||||
<string name="pers_item_is_reusable">Is reusable</string>
|
||||
<string name="pers_item_need_activation">Need activation</string>
|
||||
<string name="pers_item_forbid_purge">Forbid purge</string>
|
||||
|
|
@ -55,7 +57,7 @@
|
|||
<string name="pers_item_forbid_default_pin">Forbid default PIN</string>
|
||||
<string name="pers_item_smart_security_delay">Smart Security Delay</string>
|
||||
<string name="pers_item_protect_issuer_data_against_replay">Protect issuer data against replay</string>
|
||||
<string name="pers_item_skip_security_delay_if_validated">Security delay if validated</string>
|
||||
<string name="pers_item_skip_security_delay_if_validated">Skip security delay if validated</string>
|
||||
<string name="pers_item_skip_pin2_and_cvc_if_validated">Skip PIN2 and CVC if validated</string>
|
||||
<string name="pers_item_skip_security_delay_on_linked_terminal">Skip security delay on linked terminal</string>
|
||||
<string name="pers_item_restrict_overwrite_ex_issuer_data">Restrict overwrite extra issuer data</string>
|
||||
|
|
@ -86,6 +88,7 @@
|
|||
|
||||
<string name="info_pers_item_series"></string>
|
||||
<string name="info_pers_item_number"></string>
|
||||
<string name="info_pers_item_batch_id"></string>
|
||||
<string name="info_pers_item_curve">Elliptic curve used for all wallet key operations. Supported curves: ‘secp256k1’, ‘ed25519’.</string>
|
||||
<string name="info_pers_item_blockchain">Name of the blockchain. It\'s just a textfield in the card. It\'s needed for host app to tell what blockchain should it use. </string>
|
||||
<string name="info_pers_item_custom_blockchain">You can use this field, to create something special</string>
|
||||
|
|
@ -113,6 +116,7 @@
|
|||
<string name="info_pers_item_note">Self-custodial wallet or note</string>
|
||||
<string name="info_pers_item_tag">Anti-counterfeit tag</string>
|
||||
<string name="info_pers_item_id_card">Personal ID card</string>
|
||||
<string name="info_pers_item_id_issuer_card"></string>
|
||||
<string name="info_pers_item_is_reusable">Defines what happens when user calls PURGE_WALLET command:
|
||||
\nOff - Card will switch to Purged state
|
||||
\nOn - Card will switch to Empty state and let create a new wallet again
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue