Updated on 2026-08-14
This commit is contained in:
commit
e26bd42888
11 changed files with 100 additions and 21 deletions
|
|
@ -183,29 +183,51 @@ class TangemSdk(
|
|||
}
|
||||
|
||||
/**
|
||||
* This method launches a [WriteUserDataCommand] on a new thread.
|
||||
* This method launches a [WriteUserDataCommand] on a new thread, writing UserData and UserCounter fields.
|
||||
*
|
||||
* This command writes some of UserData, UserProtectedData, UserCounter and UserProtectedCounter fields.
|
||||
* User_Data and User_ProtectedData are never changed or parsed by the executable code the Tangem COS.
|
||||
* The App defines purpose of use, format and it's payload. For example, this field may contain cashed information
|
||||
* User_Data is never changed or parsed by the executable code the Tangem COS.
|
||||
* The App defines purpose of use, format and its payload. For example, this field may contain cashed information
|
||||
* from blockchain to accelerate preparing new transaction.
|
||||
* User_Counter and User_ProtectedCounter are counters, that initial values can be set by App and increased on every signing
|
||||
* The initial value of User_Counter can be set by an App and increased on every signing
|
||||
* of new transaction (on SIGN command that calculate new signatures). The App defines purpose of use.
|
||||
* For example, this fields may contain blockchain nonce value.
|
||||
*
|
||||
* Writing of UserCounter and UserData is protected only by PIN1.
|
||||
* UserProtectedCounter and UserProtectedData need additionally PIN2 to confirmation.
|
||||
*/
|
||||
fun writeUserData(
|
||||
cardId: String,
|
||||
userData: ByteArray? = null,
|
||||
userProtectedData: ByteArray? = null,
|
||||
userCounter: Int? = null,
|
||||
initialMessage: Message? = null,
|
||||
callback: (result: CompletionResult<WriteUserDataResponse>) -> Unit
|
||||
) {
|
||||
val command = WriteUserDataCommand(userData = userData,userCounter = userCounter)
|
||||
startSessionWithRunnable(command, cardId, initialMessage, callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method launches a [WriteUserDataCommand] on a new thread,
|
||||
* writing UserProtectedData and UserProtectedCounter fields.
|
||||
*
|
||||
* User_ProtectedData is never changed or parsed by the executable code the Tangem COS.
|
||||
* The App defines purpose of use, format and its payload. For example, this field may contain cashed information
|
||||
* from blockchain to accelerate preparing new transaction.
|
||||
* The initial value of User_ProtectedCounter can be set by an App and increased on every signing
|
||||
* of a new transaction (on SIGN command that calculate new signatures). The App defines the purpose of use.
|
||||
* For example, this fields may contain blockchain nonce value.
|
||||
*
|
||||
* UserProtectedCounter and UserProtectedData require PIN2 for confirmation.
|
||||
*/
|
||||
fun writeProtectedUserData(
|
||||
cardId: String,
|
||||
userProtectedData: ByteArray? = null,
|
||||
userProtectedCounter: Int? = null,
|
||||
initialMessage: Message? = null,
|
||||
callback: (result: CompletionResult<WriteUserDataResponse>) -> Unit
|
||||
) {
|
||||
val command = WriteUserDataCommand(userData, userProtectedData, userCounter, userProtectedCounter)
|
||||
val command = WriteUserDataCommand(
|
||||
userProtectedData = userProtectedData, userProtectedCounter = userProtectedCounter
|
||||
)
|
||||
startSessionWithRunnable(command, cardId, initialMessage, callback)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,9 +50,7 @@ class TestUserDataActivity : AppCompatActivity() {
|
|||
tangemSdk.writeUserData(
|
||||
writeOptions.cardId!!,
|
||||
writeOptions.userData,
|
||||
writeOptions.userProtectedData,
|
||||
writeOptions.userCounter,
|
||||
writeOptions.userProtectedCounter
|
||||
writeOptions.userCounter
|
||||
) {
|
||||
when (it) {
|
||||
is CompletionResult.Failure -> handleError(tv_write_result, it.error)
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ class ActionListFragment : BaseFragment() {
|
|||
ActionType.ReadIssuerExData,
|
||||
ActionType.WriteIssuerExData,
|
||||
ActionType.ReadUserData,
|
||||
ActionType.WriteUserData
|
||||
ActionType.WriteUserData,
|
||||
ActionType.WriteProtectedUserData
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -11,12 +11,10 @@ class WriteUserDataAction : BaseAction() {
|
|||
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
|
||||
val userData = (attrs.itemList.findItem(TlvId.UserData)?.getData() as? String)?.toByteArray()
|
||||
?: return
|
||||
val protectedUserData = (attrs.itemList.findItem(TlvId.ProtectedUserData)?.getData() as? String)?.toByteArray()
|
||||
?: return
|
||||
val cardId = attrs.itemList.findItem(TlvId.CardId)?.viewModel?.data ?: return
|
||||
val counter = (attrs.itemList.findItem(TlvId.Counter)?.viewModel?.data as? Int) ?: 1
|
||||
|
||||
attrs.tangemSdk.writeUserData(stringOf(cardId), userData, protectedUserData, counter, counter) {
|
||||
attrs.tangemSdk.writeUserData(stringOf(cardId), userData, counter) {
|
||||
handleResult(payload, it, null, attrs, callback)
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +22,6 @@ class WriteUserDataAction : BaseAction() {
|
|||
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
|
||||
return when (id) {
|
||||
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
|
||||
TlvId.Counter -> { callback -> ReadUserDataAction().executeMainAction(payload, attrs, callback) }
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.devkit.ucase.domain.actions
|
||||
|
||||
import com.tangem.devkit._arch.structure.Id
|
||||
import com.tangem.devkit._arch.structure.PayloadHolder
|
||||
import com.tangem.devkit._arch.structure.abstraction.findItem
|
||||
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.devkit.ucase.variants.TlvId
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
||||
|
||||
class WriteUserProtectedDataAction : BaseAction() {
|
||||
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
|
||||
val protectedUserData = (attrs.itemList.findItem(TlvId.ProtectedUserData)?.getData() as? String)?.toByteArray()
|
||||
?: return
|
||||
val cardId = attrs.itemList.findItem(TlvId.CardId)?.viewModel?.data ?: return
|
||||
val counter = (attrs.itemList.findItem(TlvId.Counter)?.viewModel?.data as? Int) ?: 1
|
||||
|
||||
attrs.tangemSdk.writeProtectedUserData(stringOf(cardId), protectedUserData, counter) {
|
||||
handleResult(payload, it, null, attrs, callback)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
|
||||
return when (id) {
|
||||
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,9 +96,18 @@ class WriteUserDataItemsManager : BaseItemsManager(WriteUserDataAction()) {
|
|||
setItems(listOf(
|
||||
EditTextItem(TlvId.CardId, null),
|
||||
EditTextItem(TlvId.Counter, "1"),
|
||||
EditTextItem(TlvId.UserData, "User data to be written on a card"),
|
||||
EditTextItem(TlvId.ProtectedUserData, "Protected user data to be written on a card")
|
||||
|
||||
EditTextItem(TlvId.UserData, "User data to be written on a card")
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
class WriteProtectedUserDataItemsManager : BaseItemsManager(WriteUserProtectedDataAction()) {
|
||||
init {
|
||||
setItemChangeConsequences(CardIdConsequence())
|
||||
setItems(listOf(
|
||||
EditTextItem(TlvId.CardId, null),
|
||||
EditTextItem(TlvId.Counter, "1"),
|
||||
EditTextItem(TlvId.ProtectedUserData, "Protected user data to be written on a card")
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ enum class ActionType : Id {
|
|||
WriteIssuerExData,
|
||||
ReadUserData,
|
||||
WriteUserData,
|
||||
WriteProtectedUserData,
|
||||
Personalize,
|
||||
Depersonalize,
|
||||
Unknown,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class ActionResources {
|
|||
holder.register(ActionType.WriteIssuerExData, ActionRes(R.string.action_issuer_write_ex_data, R.string.info_action_issuer_write_ex_data, R.id.action_nav_entry_point_to_nav_issuer_write_ex_data))
|
||||
holder.register(ActionType.ReadUserData, ActionRes(R.string.action_user_read_data, R.string.info_action_user_read_data, R.id.action_nav_entry_point_to_nav_user_read_data))
|
||||
holder.register(ActionType.WriteUserData, ActionRes(R.string.action_user_write_data, R.string.info_action_user_write_data, R.id.action_nav_entry_point_to_nav_user_write_data))
|
||||
holder.register(ActionType.WriteProtectedUserData, ActionRes(R.string.action_user_write_protected_data, R.string.info_action_user_write_protected_data, R.id.action_nav_entry_point_to_nav_user_write_protected_data))
|
||||
// holder.register(ActionType.Unknown, getIfNotContains())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.devkit.ucase.variants.userdata.ui
|
||||
|
||||
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
|
||||
import com.tangem.devkit.ucase.domain.paramsManager.managers.WriteProtectedUserDataItemsManager
|
||||
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
|
||||
|
||||
class WriteProtectedUserDataFragment : BaseCardActionFragment() {
|
||||
|
||||
override val itemsManager: ItemsManager by lazy { WriteProtectedUserDataItemsManager() }
|
||||
}
|
||||
|
|
@ -44,6 +44,9 @@
|
|||
<action
|
||||
android:id="@+id/action_nav_entry_point_to_nav_user_write_data"
|
||||
app:destination="@id/nav_user_write_data" />
|
||||
<action
|
||||
android:id="@+id/action_nav_entry_point_to_nav_user_write_protected_data"
|
||||
app:destination="@id/nav_user_write_protected_data" />
|
||||
<action
|
||||
android:id="@+id/action_nav_entry_point_to_nav_wallet_create"
|
||||
app:destination="@id/nav_wallet_create" />
|
||||
|
|
@ -119,6 +122,12 @@
|
|||
android:label="@string/action_user_write_data"
|
||||
tools:layout="@layout/fg_base_action_layout" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_user_write_protected_data"
|
||||
android:name="com.tangem.devkit.ucase.variants.userdata.ui.WriteProtectedUserDataFragment"
|
||||
android:label="@string/action_user_write_protected_data"
|
||||
tools:layout="@layout/fg_base_action_layout" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_wallet_create"
|
||||
android:name="com.tangem.devkit.ucase.variants.createwallet.ui.CreateWalletActionFragment"
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
<string name="action_issuer_write_ex_data">Write Issuer Extra Data</string>
|
||||
<string name="action_user_read_data">Read User Data</string>
|
||||
<string name="action_user_write_data">Write User Data</string>
|
||||
<string name="action_user_write_protected_data">Write Protected User Data</string>
|
||||
|
||||
<string name="info_action_card_scan">This command returns all data about the card and the wallet, including unique card number (CID) that has to be submitted while calling all other commands</string>
|
||||
<string name="info_action_card_sign">Depending on Signing_Method parameter defined during personalization, this command signs data using Wallet_PrivateKey</string>
|
||||
|
|
@ -26,7 +27,8 @@
|
|||
<string name="info_action_issuer_read_ex_data">This command retrieves Issuer Extra Data field and its issuer’s signature.</string>
|
||||
<string name="info_action_issuer_write_ex_data">This command writes Issuer Extra Data field and its issuer’s signature to the card.</string>
|
||||
<string name="info_action_user_read_data">This command returns User Data and User Protected Data (up to 512-byte each) and two counters: User Counter and User Protected Counter.</string>
|
||||
<string name="info_action_user_write_data"> This command writes to the card any of User Data, User Protected Data, User Counter and User Protected Counter fields.
|
||||
</string>
|
||||
<string name="info_action_user_write_data"> This command writes to the card User Data and User Counter fields.</string>
|
||||
<string name="info_action_user_write_protected_data"> This command writes to the card User Protected Data and User Protected Counter fields.</string>
|
||||
|
||||
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue