Updated on 2026-08-14
This commit is contained in:
parent
e727b40042
commit
3556c3765e
7 changed files with 331 additions and 86 deletions
|
|
@ -70,4 +70,8 @@ dependencies {
|
|||
implementation(deps.timber)
|
||||
implementation(tangemDeps.card.core)
|
||||
implementation(tangemDeps.blockchain)
|
||||
|
||||
/** Test libraries */
|
||||
implementation(deps.test.junit)
|
||||
implementation(deps.test.truth)
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
package com.tangem.features.walletconnect.transaction.converter
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Parses various transaction parameters from various JSON schemas to UI format for transaction request BS
|
||||
*/
|
||||
internal class TransactionParamsConverter @Inject constructor() : Converter<String, List<WcTransactionRequestBlockUM>> {
|
||||
|
||||
@Suppress("CyclomaticComplexMethod", "NestedBlockDepth")
|
||||
override fun convert(value: String): List<WcTransactionRequestBlockUM> {
|
||||
val result = mutableListOf<WcTransactionRequestBlockUM>()
|
||||
|
||||
fun loop(node: Any?) {
|
||||
when (node) {
|
||||
is JSONObject -> {
|
||||
for (key in node.keys()) {
|
||||
val objectValue = node.get(key)
|
||||
|
||||
when (key) {
|
||||
PRIMARY_TYPE, DATA, FROM, TO, VALUE -> if (objectValue is String) {
|
||||
result.addSingleStringValueBlock(key, objectValue)
|
||||
}
|
||||
|
||||
DOMAIN -> if (objectValue is JSONObject) {
|
||||
result.addMultipleObjectsBlock(key, objectValue)
|
||||
}
|
||||
|
||||
MESSAGE -> if (objectValue is JSONObject) {
|
||||
objectValue.optString(CONTENTS).let { contents ->
|
||||
result.addNestedStringValueBlock(key, nestedKey = CONTENTS, contents)
|
||||
}
|
||||
|
||||
objectValue.optJSONObject(FROM)?.let { from ->
|
||||
result.addMultipleObjectsBlock(FROM, from)
|
||||
}
|
||||
|
||||
objectValue.optJSONObject(TO)?.let { to ->
|
||||
result.addMultipleObjectsBlock(TO, to)
|
||||
}
|
||||
}
|
||||
|
||||
else -> loop(objectValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
is JSONArray -> {
|
||||
for (i in 0 until node.length()) {
|
||||
loop(node.get(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loop(JSONArray(value))
|
||||
return result
|
||||
}
|
||||
|
||||
private fun MutableList<WcTransactionRequestBlockUM>.addSingleStringValueBlock(
|
||||
key: String,
|
||||
stringValue: String,
|
||||
): MutableList<WcTransactionRequestBlockUM> {
|
||||
add(
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str(key.capitalize()),
|
||||
description = stringValue,
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun MutableList<WcTransactionRequestBlockUM>.addNestedStringValueBlock(
|
||||
key: String,
|
||||
nestedKey: String,
|
||||
stringValue: String,
|
||||
): MutableList<WcTransactionRequestBlockUM> {
|
||||
add(
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str(key.capitalize())),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str(nestedKey.capitalize()),
|
||||
description = stringValue,
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun MutableList<WcTransactionRequestBlockUM>.addMultipleObjectsBlock(
|
||||
key: String,
|
||||
objectValue: JSONObject,
|
||||
): MutableList<WcTransactionRequestBlockUM> {
|
||||
add(
|
||||
WcTransactionRequestBlockUM(
|
||||
info = buildList {
|
||||
add(WcTransactionRequestInfoItemUM(TextReference.Str(key.capitalize())))
|
||||
addAll(extractObjects(objectValue))
|
||||
}.toImmutableList(),
|
||||
),
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun String.capitalize(): String = replaceFirstChar { it.uppercaseChar() }
|
||||
|
||||
private fun extractObjects(obj: JSONObject): List<WcTransactionRequestInfoItemUM> {
|
||||
val items = mutableListOf<WcTransactionRequestInfoItemUM>()
|
||||
for (key in obj.keys()) {
|
||||
val objectValue = obj.get(key)
|
||||
if (objectValue is String || objectValue is Number || objectValue is Boolean) {
|
||||
items.add(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str(key),
|
||||
description = objectValue.toString(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val PRIMARY_TYPE = "primaryType"
|
||||
const val DATA = "data"
|
||||
const val FROM = "from"
|
||||
const val TO = "to"
|
||||
const val VALUE = "value"
|
||||
const val DOMAIN = "domain"
|
||||
const val MESSAGE = "message"
|
||||
const val CONTENTS = "contents"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package com.tangem.features.walletconnect.transaction.converter
|
||||
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.*
|
||||
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.*
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionFeeState
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionItemUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
|
@ -45,33 +45,11 @@ internal class WcSendTransactionUMConverter @Inject constructor(
|
|||
feeSelectorUM = value.feeSelectorUM ?: FeeSelectorUM.Loading,
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = buildList {
|
||||
add(
|
||||
addAll(
|
||||
requestBlockUMConverter.convert(
|
||||
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest),
|
||||
),
|
||||
)
|
||||
(value.useCase.method as? WcEthMethod.SendTransaction)?.transaction?.let { transaction ->
|
||||
add(
|
||||
WcTransactionRequestBlockUM(
|
||||
info = buildList {
|
||||
transaction.to?.let {
|
||||
add(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_transaction_info_to_title),
|
||||
description = it,
|
||||
),
|
||||
)
|
||||
}
|
||||
add(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.send_from_wallet_android),
|
||||
description = transaction.from,
|
||||
),
|
||||
)
|
||||
}.toImmutableList(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}.toImmutableList(),
|
||||
onCopy = value.actions.onCopy,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.features.walletconnect.transaction.entity.common.WcTransaction
|
|||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionItemUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class WcSignTransactionUMConverter @Inject constructor(
|
||||
|
|
@ -33,11 +33,9 @@ internal class WcSignTransactionUMConverter @Inject constructor(
|
|||
address = WcAddressConverter.convert(value.useCase.derivationState),
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
persistentListOf(
|
||||
requestBlockUMConverter.convert(
|
||||
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest, value.signModel),
|
||||
),
|
||||
),
|
||||
requestBlockUMConverter.convert(
|
||||
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest, value.signModel),
|
||||
).toImmutableList(),
|
||||
onCopy = value.actions.onCopy,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
package com.tangem.features.walletconnect.transaction.converter
|
||||
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import com.tangem.features.walletconnect.impl.R
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionItemUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -40,30 +34,11 @@ internal class WcSignTypedDataUMConverter @Inject constructor(
|
|||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = buildList {
|
||||
add(
|
||||
addAll(
|
||||
requestBlockUMConverter.convert(
|
||||
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest, value.signModel),
|
||||
),
|
||||
)
|
||||
(value.useCase.method as? WcEthMethod.SignTypedData)?.params?.message?.to?.let { to ->
|
||||
add(
|
||||
WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_transaction_info_to_title),
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.settings_wallet_name_title),
|
||||
description = to.name,
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_common_wallet),
|
||||
description = to.wallet,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}.toImmutableList(),
|
||||
onCopy = value.actions.onCopy,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,40 +7,44 @@ import com.tangem.features.walletconnect.impl.R
|
|||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.json.JSONArray
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val DATA_FIELD = "data"
|
||||
internal class WcTransactionRequestBlockUMConverter @Inject constructor(
|
||||
private val transactionParamsConverter: TransactionParamsConverter,
|
||||
) : Converter<WcTransactionRequestBlockUMConverter.Input, List<WcTransactionRequestBlockUM>> {
|
||||
|
||||
internal class WcTransactionRequestBlockUMConverter @Inject constructor() :
|
||||
Converter<WcTransactionRequestBlockUMConverter.Input, WcTransactionRequestBlockUM> {
|
||||
|
||||
override fun convert(value: Input): WcTransactionRequestBlockUM {
|
||||
override fun convert(value: Input): List<WcTransactionRequestBlockUM> {
|
||||
val params = value.rawSdkRequest.request.params
|
||||
return WcTransactionRequestBlockUM(
|
||||
persistentListOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = value.rawSdkRequest.request.method,
|
||||
val humanMsg = value.signModel?.humanMsg
|
||||
return buildList {
|
||||
add(
|
||||
WcTransactionRequestBlockUM(
|
||||
buildList {
|
||||
add(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_signature_type),
|
||||
description = value.rawSdkRequest.request.method,
|
||||
),
|
||||
)
|
||||
if (!humanMsg.isNullOrEmpty()) {
|
||||
add(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = humanMsg,
|
||||
),
|
||||
)
|
||||
}
|
||||
}.toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = resourceReference(R.string.wc_contents),
|
||||
description = value.signModel?.humanMsg ?: params.tryExtractData() ?: params,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun String.tryExtractData() = try {
|
||||
val array = JSONArray(this)
|
||||
if (array.length() > 0 && array.getJSONObject(0).has(DATA_FIELD)) {
|
||||
array.getJSONObject(0).getString(DATA_FIELD)
|
||||
} else {
|
||||
null
|
||||
)
|
||||
try {
|
||||
addAll(transactionParamsConverter.convert(params))
|
||||
} catch (exception: Exception) {
|
||||
Timber.e(exception, "Error while parsing transaction params - %s", params)
|
||||
}
|
||||
}
|
||||
} catch (ignore: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
data class Input(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
package com.tangem.features.walletconnect.transaction.converter
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestBlockUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionRequestInfoItemUM
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.junit.Test
|
||||
|
||||
class TransactionParamsConverterTest {
|
||||
|
||||
private val converter = TransactionParamsConverter()
|
||||
|
||||
@Test
|
||||
fun `GIVEN sign typed data transaction params WHEN convert THEN return correct data for UI`() {
|
||||
val value = """
|
||||
[
|
||||
"0xcd5F26C95e84279d0ce8E6dd9030d0b2171b6101",
|
||||
{
|
||||
"domain": {
|
||||
"name": "Ether Mail",
|
||||
"version": "1",
|
||||
"chainId": 1,
|
||||
"verifyingContract": "0xcccccccccccccccccccccccccccccccccccccccc"
|
||||
},
|
||||
"message": {
|
||||
"from": {
|
||||
"name": "Cow",
|
||||
"wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
|
||||
},
|
||||
"to": {
|
||||
"name": "Bob",
|
||||
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
|
||||
},
|
||||
"contents": "Hello, Bob!"
|
||||
},
|
||||
"primaryType": "Mail"
|
||||
}
|
||||
]
|
||||
""".trimIndent()
|
||||
val expected = listOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str("PrimaryType"),
|
||||
description = "Mail",
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("Domain")),
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("chainId"), "1"),
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("name"), "Ether Mail"),
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("version"), "1"),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
TextReference.Str("verifyingContract"),
|
||||
"0xcccccccccccccccccccccccccccccccccccccccc",
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("Message")),
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("Contents"), "Hello, Bob!"),
|
||||
).toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("From")),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
TextReference.Str("wallet"),
|
||||
"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("name"), "Cow"),
|
||||
).toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("To")),
|
||||
WcTransactionRequestInfoItemUM(
|
||||
TextReference.Str("wallet"),
|
||||
"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
|
||||
),
|
||||
WcTransactionRequestInfoItemUM(TextReference.Str("name"), "Bob"),
|
||||
).toImmutableList(),
|
||||
),
|
||||
)
|
||||
Truth.assertThat(converter.convert(value)).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN send or approve transaction params WHEN convert THEN return correct data for UI`() {
|
||||
val value = """
|
||||
[
|
||||
{
|
||||
"data": "0x095ea7b3000000000000000000000000f0d4c12a5768d806021f80a262b4d39d26c58b8dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"from": "0xcd5F26C95e84279d0ce8E6dd9030d0b2171b6101",
|
||||
"to": "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0",
|
||||
"value": "0x0"
|
||||
}
|
||||
]
|
||||
""".trimIndent()
|
||||
|
||||
val expected = listOf(
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str("Data"),
|
||||
description = "0x095ea7b3000000000000000000000000f0d4c12a5768d806021f80a262b4d39d26c58b8dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str("From"),
|
||||
description = "0xcd5F26C95e84279d0ce8E6dd9030d0b2171b6101",
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str("To"),
|
||||
description = "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0",
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
WcTransactionRequestBlockUM(
|
||||
info = listOf(
|
||||
WcTransactionRequestInfoItemUM(
|
||||
title = TextReference.Str("Value"),
|
||||
description = "0x0",
|
||||
),
|
||||
).toImmutableList(),
|
||||
),
|
||||
)
|
||||
|
||||
Truth.assertThat(converter.convert(value)).isEqualTo(expected)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue