tangem-app-android-audited/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt
2026-06-05 12:32:13 +04:00

113 lines
No EOL
4.4 KiB
Kotlin

package com.tangem.tap.domain
import com.tangem.Message
import com.tangem.TangemSdk
import com.tangem.blockchain.common.TransactionSigner
import com.tangem.blockchain.common.Wallet
import com.tangem.common.CompletionResult
import com.tangem.domain.card.models.TwinKey
import com.tangem.domain.models.scan.isRing
import com.tangem.operations.sign.SignData
import com.tangem.tap.domain.tasks.MultiSignHashTask
import com.tangem.tap.domain.tasks.SignHashesTask
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
class TangemSigner(
private val cardId: String?,
private val tangemSdk: TangemSdk,
private val initialMessage: Message,
private val twinKey: TwinKey?,
private val signerCallback: (TangemSignerResponse) -> Unit,
) : TransactionSigner {
override suspend fun sign(
hashes: List<ByteArray>,
publicKey: Wallet.PublicKey,
): CompletionResult<List<ByteArray>> {
return suspendCancellableCoroutine { continuation ->
val task = SignHashesTask(hashes, publicKey, twinKey?.getPairKey(publicKey.seedKey))
tangemSdk.startSessionWithRunnable(
runnable = task,
cardId = cardId,
initialMessage = initialMessage,
) { result ->
when (result) {
is CompletionResult.Success -> {
signerCallback(
TangemSignerResponse(
totalSignedHashes = result.data.totalSignedHashes,
remainingSignatures = result.data.remainingSignatures,
isRing = result.data.batchId?.let(::isRing) == true,
signedWalletPublicKey = publicKey.seedKey,
),
)
if (continuation.isActive) {
continuation.resume(CompletionResult.Success(result.data.signatures))
}
}
is CompletionResult.Failure ->
if (continuation.isActive) {
continuation.resume(CompletionResult.Failure(result.error))
}
}
}
}
}
override suspend fun sign(hash: ByteArray, publicKey: Wallet.PublicKey): CompletionResult<ByteArray> {
val result = sign(
hashes = listOf(hash),
publicKey = publicKey,
)
return when (result) {
is CompletionResult.Success -> CompletionResult.Success(result.data.first())
is CompletionResult.Failure -> CompletionResult.Failure(result.error)
}
}
override suspend fun multiSign(
dataToSign: List<SignData>,
publicKey: Wallet.PublicKey,
): CompletionResult<Map<ByteArray, ByteArray>> {
return suspendCancellableCoroutine { continuation ->
val task = MultiSignHashTask(dataToSign, publicKey, twinKey?.getPairKey(publicKey.seedKey))
tangemSdk.startSessionWithRunnable(
runnable = task,
cardId = cardId,
initialMessage = initialMessage,
) { result ->
when (result) {
is CompletionResult.Success -> {
signerCallback(
TangemSignerResponse(
totalSignedHashes = result.data.totalSignedHashes,
remainingSignatures = result.data.remainingSignatures,
isRing = result.data.batchId?.let(::isRing) == true,
signedWalletPublicKey = publicKey.seedKey,
),
)
if (continuation.isActive) {
continuation.resume(CompletionResult.Success(result.data.signatures))
}
}
is CompletionResult.Failure ->
if (continuation.isActive) {
continuation.resume(CompletionResult.Failure(result.error))
}
}
}
}
}
}
@Suppress("ArrayInDataClass")
data class TangemSignerResponse(
val totalSignedHashes: Int?,
val remainingSignatures: Int?,
val isRing: Boolean,
val signedWalletPublicKey: ByteArray,
)