From 94da507ef7945657b4dce784ff11ba19df3d83a3 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Wed, 16 Oct 2024 12:37:30 +0500 Subject: [PATCH 1/9] AND-8611 Add Casper API --- .../casper/models/CasperBalance.kt | 7 +++ .../blockchains/casper/network/CasperApi.kt | 27 ++++++++++ .../converters/CasperBalanceBodyConverter.kt | 18 +++++++ .../network/request/CasperQueryBalanceBody.kt | 14 +++++ .../network/request/CasperRpcBodyFactory.kt | 31 +++++++++++ .../casper/network/request/CasperRpcMethod.kt | 11 ++++ .../network/response/CasperRpcResponse.kt | 18 +++++++ .../response/CasperRpcResponseAdapter.kt | 53 +++++++++++++++++++ .../response/CasperRpcResponseResult.kt | 13 +++++ .../blockchain/network/RetrofitBuilder.kt | 3 ++ 10 files changed, 195 insertions(+) create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperApi.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperQueryBalanceBody.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcBodyFactory.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcMethod.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponse.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseResult.kt diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt new file mode 100644 index 000000000..2f87f94a1 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt @@ -0,0 +1,7 @@ +package com.tangem.blockchain.blockchains.casper.models + +import java.math.BigDecimal + +data class CasperBalance( + val balance: BigDecimal, +) \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperApi.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperApi.kt new file mode 100644 index 000000000..16ae7c102 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperApi.kt @@ -0,0 +1,27 @@ +package com.tangem.blockchain.blockchains.casper.network + +import com.tangem.blockchain.blockchains.casper.network.response.CasperRpcResponse +import com.tangem.blockchain.common.JsonRPCRequest +import retrofit2.http.Body +import retrofit2.http.Headers +import retrofit2.http.POST +import retrofit2.http.Url + +/** + * Casper RPC API + * + * @see Casper JSON RPC + * + */ +internal interface CasperApi { + + /** + * Get data by body [JsonRPCRequest] + * + * @param postfixUrl postfix url for supports base url without '/' + * @param body rpc body + */ + @Headers("Content-Type: application/json") + @POST + suspend fun post(@Url postfixUrl: String, @Body body: JsonRPCRequest): CasperRpcResponse +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt new file mode 100644 index 000000000..75ca8c9a4 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt @@ -0,0 +1,18 @@ +package com.tangem.blockchain.blockchains.casper.network.converters + +import com.tangem.blockchain.blockchains.casper.network.request.CasperQueryBalanceBody + +/** + * Converter from address to [CasperQueryBalanceBody] + * + */ +internal object CasperBalanceBodyConverter { + + fun convert(address: String): CasperQueryBalanceBody { + return CasperQueryBalanceBody( + purseIdentifier = CasperQueryBalanceBody.PurseIdentifier( + mainPurseUnderPublicKey = address + ) + ) + } +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperQueryBalanceBody.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperQueryBalanceBody.kt new file mode 100644 index 000000000..629816165 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperQueryBalanceBody.kt @@ -0,0 +1,14 @@ +package com.tangem.blockchain.blockchains.casper.network.request + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +internal data class CasperQueryBalanceBody( + @Json(name = "purse_identifier") val purseIdentifier: PurseIdentifier, +) { + @JsonClass(generateAdapter = true) + data class PurseIdentifier( + @Json(name = "main_purse_under_public_key") val mainPurseUnderPublicKey: String, + ) +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcBodyFactory.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcBodyFactory.kt new file mode 100644 index 000000000..487bab5bb --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcBodyFactory.kt @@ -0,0 +1,31 @@ +package com.tangem.blockchain.blockchains.casper.network.request + +import com.tangem.blockchain.blockchains.casper.network.converters.CasperBalanceBodyConverter +import com.tangem.blockchain.common.JsonRPCRequest + +/** + * Factory for creating [JsonRPCRequest] + * + * @see Casper JSON-RPC schema + * + */ +internal object CasperRpcBodyFactory { + + /** + * Create query balance body + * + * @param address address + */ + fun createQueryBalanceBody(address: String) = create( + method = CasperRpcMethod.QueryBalance, + params = CasperBalanceBodyConverter.convert(address), + ) + + private fun create(method: CasperRpcMethod, params: Any?): JsonRPCRequest { + return JsonRPCRequest( + id = "1", + method = method.name, + params = params, + ) + } +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcMethod.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcMethod.kt new file mode 100644 index 000000000..46237a1db --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/request/CasperRpcMethod.kt @@ -0,0 +1,11 @@ +package com.tangem.blockchain.blockchains.casper.network.request + +/** + * Casper rpc method + * + * @property name method name + */ +internal sealed class CasperRpcMethod(val name: String) { + + data object QueryBalance : CasperRpcMethod(name = "query_balance") +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponse.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponse.kt new file mode 100644 index 000000000..94b246359 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponse.kt @@ -0,0 +1,18 @@ +package com.tangem.blockchain.blockchains.casper.network.response + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** Casper RPC response */ +internal sealed interface CasperRpcResponse { + + /** Success response with [result] */ + data class Success(val result: Any) : CasperRpcResponse + + /** Failure response with error [message] */ + @JsonClass(generateAdapter = true) + data class Failure( + @Json(name = "message") val message: String, + @Json(name = "code") val code: Int = 0, + ) : CasperRpcResponse +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt new file mode 100644 index 000000000..8cf35db59 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt @@ -0,0 +1,53 @@ +package com.tangem.blockchain.blockchains.casper.network.response + +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import com.squareup.moshi.adapter +import com.tangem.blockchain.network.moshi + +/** Casper rpc response adapter [JsonAdapter] */ +@OptIn(ExperimentalStdlibApi::class) +internal object CasperRpcResponseAdapter : JsonAdapter() { + + private val options = JsonReader.Options.of("result", "error") + + private val failureAdapter by lazy { moshi.adapter() } + + private val parsingResponseFailure = CasperRpcResponse.Failure("Parsing response failure") + + override fun fromJson(reader: JsonReader): CasperRpcResponse { + var casperRpcResponse: CasperRpcResponse? = null + + reader.beginObject() + + while (reader.hasNext()) { + when (reader.selectName(options)) { + 0 -> { + casperRpcResponse = runCatching { reader.readJsonValue() } + .mapCatching { CasperRpcResponse.Success(result = requireNotNull(it)) } + .getOrElse { parsingResponseFailure } + } + 1 -> { + casperRpcResponse = runCatching { failureAdapter.fromJson(reader) } + .mapCatching { CasperRpcResponse.Failure(message = requireNotNull(it).message) } + .getOrElse { parsingResponseFailure } + } + -1 -> reader.skipNameAndValue() + } + } + + reader.endObject() + + return casperRpcResponse ?: CasperRpcResponse.Failure(message = "Unknown error") + } + + override fun toJson(writer: JsonWriter, value: CasperRpcResponse?) { + error("Not used") + } + + private fun JsonReader.skipNameAndValue() { + skipName() + skipValue() + } +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseResult.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseResult.kt new file mode 100644 index 000000000..9c1406352 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseResult.kt @@ -0,0 +1,13 @@ +package com.tangem.blockchain.blockchains.casper.network.response + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** Type of success response result */ +internal sealed interface CasperRpcResponseResult { + + @JsonClass(generateAdapter = true) + data class Balance( + @Json(name = "balance") val balance: String, + ) : CasperRpcResponseResult +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt index 932e0946e..6d8d6c8c8 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt @@ -4,6 +4,8 @@ import com.squareup.moshi.* import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.tangem.blockchain.blockchains.aptos.network.response.AptosResource import com.tangem.blockchain.blockchains.aptos.network.response.AptosResourceBodyAdapter +import com.tangem.blockchain.blockchains.casper.network.response.CasperRpcResponse +import com.tangem.blockchain.blockchains.casper.network.response.CasperRpcResponseAdapter import com.tangem.blockchain.blockchains.filecoin.network.response.FilecoinRpcResponse import com.tangem.blockchain.blockchains.filecoin.network.response.FilecoinRpcResponseAdapter import com.tangem.blockchain.common.EnumeratedEnum @@ -75,6 +77,7 @@ internal val moshi: Moshi by lazy { .add(BigDecimal::class.java, BigDecimalAdapter) .add(AptosResource::class.java, AptosResourceBodyAdapter) .add(FilecoinRpcResponse::class.java, FilecoinRpcResponseAdapter) + .add(CasperRpcResponse::class.java, CasperRpcResponseAdapter) .add(createEnumJsonAdapter()) .add(PolygonScanResultAdapter()) .add(KotlinJsonAdapterFactory()) From 17a5a0fe3bdcb8fa65e0a4332c10f6f0240f16d3 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Wed, 16 Oct 2024 12:40:37 +0500 Subject: [PATCH 2/9] AND-8612 Add CasperNetworkProvider --- .../casper/network/CasperNetworkProvider.kt | 9 +++ .../casper/network/CasperNetworkService.kt | 20 ++++++ .../provider/CasperRpcNetworkProvider.kt | 69 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt new file mode 100644 index 000000000..4d41d5824 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt @@ -0,0 +1,9 @@ +package com.tangem.blockchain.blockchains.casper.network + +import com.tangem.blockchain.blockchains.casper.models.CasperBalance +import com.tangem.blockchain.common.NetworkProvider +import com.tangem.blockchain.extensions.Result + +interface CasperNetworkProvider : NetworkProvider { + suspend fun getBalance(address: String): Result +} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt new file mode 100644 index 000000000..2cbcff0c5 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt @@ -0,0 +1,20 @@ +package com.tangem.blockchain.blockchains.casper.network + +import com.tangem.blockchain.blockchains.casper.models.CasperBalance +import com.tangem.blockchain.extensions.Result +import com.tangem.blockchain.network.MultiNetworkProvider +import java.math.BigDecimal + +internal class CasperNetworkService( + providers: List +): CasperNetworkProvider { + + override val baseUrl: String + get() = multiJsonRpcProvider.currentProvider.baseUrl + + private val multiJsonRpcProvider = MultiNetworkProvider(providers) + + override suspend fun getBalance(address: String): Result { + return multiJsonRpcProvider.performRequest(CasperNetworkProvider::getBalance, address) + } +} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt new file mode 100644 index 000000000..d03840e24 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt @@ -0,0 +1,69 @@ +package com.tangem.blockchain.blockchains.casper.network.provider + +import com.squareup.moshi.adapter +import com.tangem.blockchain.blockchains.casper.models.CasperBalance +import com.tangem.blockchain.blockchains.casper.network.CasperApi +import com.tangem.blockchain.blockchains.casper.network.CasperNetworkProvider +import com.tangem.blockchain.blockchains.casper.network.request.CasperRpcBodyFactory +import com.tangem.blockchain.blockchains.casper.network.response.CasperRpcResponse +import com.tangem.blockchain.blockchains.casper.network.response.CasperRpcResponseResult +import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.JsonRPCRequest +import com.tangem.blockchain.extensions.Result +import com.tangem.blockchain.network.createRetrofitInstance +import com.tangem.blockchain.network.moshi +import kotlinx.io.IOException +import okhttp3.Interceptor +import java.math.BigDecimal + +@OptIn(ExperimentalStdlibApi::class) +internal class CasperRpcNetworkProvider( + override val baseUrl: String, + private val postfixUrl: String, + headerInterceptors: List = emptyList(), +) : CasperNetworkProvider { + + private val api = createRetrofitInstance(baseUrl, headerInterceptors).create(CasperApi::class.java) + + override suspend fun getBalance(address: String): Result = post( + body = CasperRpcBodyFactory.createQueryBalanceBody(address), + onSuccess = { response: CasperRpcResponseResult.Balance -> + CasperBalance(balance = BigDecimal(response.balance)) + }, + onFailure = { response -> + if (response.isNoActorError()) BlockchainSdkError.AccountNotFound() else toDefaultError(response) + }, + ) + + private fun CasperRpcResponse.Failure.isNoActorError() = code == ERROR_CODE_QUERY_FAILED + + private suspend inline fun post( + body: JsonRPCRequest, + onSuccess: (Data) -> Domain, + onFailure: (CasperRpcResponse.Failure) -> BlockchainSdkError = ::toDefaultError, + ): Result { + return try { + when (val response = api.post(body = body, postfixUrl = postfixUrl)) { + is CasperRpcResponse.Success -> { + Result.Success( + data = onSuccess( + moshi.adapter().fromJsonValue(response.result)!!, + ), + ) + } + is CasperRpcResponse.Failure -> Result.Failure(error = onFailure(response)) + } + } catch (e: Exception) { + Result.Failure(e.toBlockchainSdkError()) + } + } + + private fun toDefaultError(response: CasperRpcResponse.Failure): BlockchainSdkError { + return IOException(response.message).toBlockchainSdkError() + } + + companion object { + // https://github.com/casper-network/casper-node/blob/dev/node/src/components/rpc_server/rpcs/error_code.rs + private const val ERROR_CODE_QUERY_FAILED = -32003 + } +} From aee091076a3e14eebbb8f57b2f95b75feb968886 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Wed, 16 Oct 2024 12:41:57 +0500 Subject: [PATCH 3/9] AND-8613: Add CasperProvidersBuilder --- .../casper/CasperProvidersBuilder.kt | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt new file mode 100644 index 000000000..1e4d11775 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt @@ -0,0 +1,52 @@ +package com.tangem.blockchain.blockchains.casper + +import com.tangem.blockchain.blockchains.casper.network.CasperNetworkProvider +import com.tangem.blockchain.blockchains.casper.network.provider.CasperRpcNetworkProvider +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.BlockchainSdkConfig +import com.tangem.blockchain.common.NowNodeCredentials +import com.tangem.blockchain.common.createWithPostfixIfContained +import com.tangem.blockchain.common.logging.AddHeaderInterceptor +import com.tangem.blockchain.common.network.providers.NetworkProvidersBuilder +import com.tangem.blockchain.common.network.providers.ProviderType +import com.tangem.blockchain.extensions.letNotBlank + +internal class CasperProvidersBuilder( + override val providerTypes: List, + private val config: BlockchainSdkConfig, +) : NetworkProvidersBuilder() { + + override fun createProviders(blockchain: Blockchain): List { + return providerTypes.mapNotNull { + when (it) { + is ProviderType.Public -> createPublicNetworkProvider(baseUrl = it.url) + ProviderType.NowNodes -> createNowNodesNetworkProvider() + else -> null + } + } + } + + private fun createPublicNetworkProvider(baseUrl: String): CasperNetworkProvider { + return createWithPostfixIfContained( + baseUrl = baseUrl, + postfixUrl = POSTFIX_URL, + create = ::CasperRpcNetworkProvider, + ) + } + + private fun createNowNodesNetworkProvider(): CasperNetworkProvider? { + return config.nowNodeCredentials?.apiKey?.letNotBlank { + CasperRpcNetworkProvider( + baseUrl = "https://casper.nownodes.io/", + postfixUrl = POSTFIX_URL, + headerInterceptors = listOf( + AddHeaderInterceptor(mapOf(NowNodeCredentials.headerApiKey to it)), + ), + ) + } + } + + private companion object { + const val POSTFIX_URL = "rpc" + } +} From 46bc0ea51c17111e794f8af0aca3d2a0042b5ed7 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Wed, 16 Oct 2024 12:43:17 +0500 Subject: [PATCH 4/9] AND-8610: Add CasperWalletManager --- .../casper/CasperTransactionBuilder.kt | 15 +++++ .../blockchains/casper/CasperWalletManager.kt | 61 +++++++++++++++++++ .../blockchain/common/WalletManagerFactory.kt | 2 +- .../impl/CasperWalletManagerAssembly.kt | 29 +++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt new file mode 100644 index 000000000..280d91248 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt @@ -0,0 +1,15 @@ +package com.tangem.blockchain.blockchains.casper + +import com.tangem.blockchain.common.Wallet + +/** + * Casper transaction builder + * + * @property wallet wallet + * + */ +internal class CasperTransactionBuilder(private val wallet: Wallet) { + + var minReserve = 2.5.toBigDecimal() + +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt new file mode 100644 index 000000000..86a8cd7f7 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt @@ -0,0 +1,61 @@ +package com.tangem.blockchain.blockchains.casper + +import android.util.Log +import com.tangem.blockchain.blockchains.casper.models.CasperBalance +import com.tangem.blockchain.blockchains.casper.network.CasperNetworkProvider +import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.transaction.Fee +import com.tangem.blockchain.common.transaction.TransactionFee +import com.tangem.blockchain.common.transaction.TransactionSendResult +import com.tangem.blockchain.extensions.Result +import java.math.BigDecimal + +internal class CasperWalletManager( + wallet: Wallet, + private val networkProvider: CasperNetworkProvider, + private val transactionBuilder: CasperTransactionBuilder, +) : WalletManager(wallet), ReserveAmountProvider { + + override val currentHost: String get() = networkProvider.baseUrl + val blockchain = wallet.blockchain + + override suspend fun updateInternal() { + when (val result = networkProvider.getBalance(wallet.address)) { + is Result.Success -> updateWallet(result.data) + is Result.Failure -> updateError(result.error) + } + } + + private fun updateWallet(balance: CasperBalance) { + if (balance.balance != wallet.amounts[AmountType.Coin]?.value) { + wallet.recentTransactions.clear() + } + wallet.setCoinValue(balance.balance.movePointLeft(wallet.blockchain.decimals())) + } + + private fun updateError(error: BlockchainError) { + Log.e(this::class.java.simpleName, error.customMessage, error) + if (error is BlockchainSdkError) throw error + } + + override suspend fun send( + transactionData: TransactionData, + signer: TransactionSigner, + ): Result { + TODO("Not yet implemented") + } + + override suspend fun getFee(amount: Amount, destination: String): Result { + return Result.Success(TransactionFee.Single(Fee.Common(Amount(FEE, blockchain)))) + } + + override fun getReserveAmount(): BigDecimal = transactionBuilder.minReserve + + override suspend fun isAccountFunded(destinationAddress: String): Boolean = + networkProvider.getBalance(destinationAddress) is Result.Success + + companion object { + // according to Casper wallet for nowx + private val FEE = 0.1.toBigDecimal() + } +} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt index 00f3df009..825f5fade 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt @@ -199,7 +199,7 @@ class WalletManagerFactory( Blockchain.Sei, Blockchain.SeiTestnet -> SeiWalletManagerAssembly Blockchain.InternetComputer -> ICPWalletManagerAssembly Blockchain.Sui, Blockchain.SuiTestnet -> SuiteWalletManagerAssembly - Blockchain.Casper, Blockchain.CasperTestnet -> TODO() // AND-8610 + Blockchain.Casper, Blockchain.CasperTestnet -> CasperWalletManagerAssembly Blockchain.Unknown, -> error("Unsupported blockchain") } diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt b/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt new file mode 100644 index 000000000..c179e0571 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt @@ -0,0 +1,29 @@ +package com.tangem.blockchain.common.assembly.impl + +import com.tangem.blockchain.blockchains.casper.CasperProvidersBuilder +import com.tangem.blockchain.blockchains.casper.CasperTransactionBuilder +import com.tangem.blockchain.blockchains.casper.CasperWalletManager +import com.tangem.blockchain.blockchains.casper.network.CasperNetworkService +import com.tangem.blockchain.common.assembly.WalletManagerAssembly +import com.tangem.blockchain.common.assembly.WalletManagerAssemblyInput + +/** + * Casper [WalletManagerAssembly] + * + */ +internal object CasperWalletManagerAssembly : WalletManagerAssembly() { + override fun make(input: WalletManagerAssemblyInput): CasperWalletManager { + return with(input.wallet) { + CasperWalletManager( + wallet = this, + networkProvider = CasperNetworkService( + providers = CasperProvidersBuilder( + providerTypes = input.providerTypes, + config = input.config, + ).build(blockchain), + ), + transactionBuilder = CasperTransactionBuilder(this), + ) + } + } +} From 6c4332c412f8b534fd335ced5fb343481767028f Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Wed, 16 Oct 2024 12:43:30 +0500 Subject: [PATCH 5/9] Fix some Casper issues --- .../blockchain/blockchains/casper/CasperAddressService.kt | 2 +- .../casper/{cashaddr => utils}/CasperAddressUtils.kt | 2 +- .../tangem/blockchain/common/derivation/DerivationConfigV1.kt | 2 +- .../tangem/blockchain/common/derivation/DerivationConfigV2.kt | 2 +- .../tangem/blockchain/common/derivation/DerivationConfigV3.kt | 2 +- .../providers/CasperExternalLinkProvider.kt | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) rename blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/{cashaddr => utils}/CasperAddressUtils.kt (97%) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperAddressService.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperAddressService.kt index 94ad5aa71..ff1742cb8 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperAddressService.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperAddressService.kt @@ -1,6 +1,6 @@ package com.tangem.blockchain.blockchains.casper -import com.tangem.blockchain.blockchains.casper.cashaddr.CasperAddressUtils.checksum +import com.tangem.blockchain.blockchains.casper.utils.CasperAddressUtils.checksum import com.tangem.blockchain.common.address.AddressService import com.tangem.blockchain.extensions.isSameCase import com.tangem.common.card.EllipticCurve diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/cashaddr/CasperAddressUtils.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/utils/CasperAddressUtils.kt similarity index 97% rename from blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/cashaddr/CasperAddressUtils.kt rename to blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/utils/CasperAddressUtils.kt index f6a7d23fb..5a95b0602 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/cashaddr/CasperAddressUtils.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/utils/CasperAddressUtils.kt @@ -1,4 +1,4 @@ -package com.tangem.blockchain.blockchains.casper.cashaddr +package com.tangem.blockchain.blockchains.casper.utils import org.bouncycastle.jcajce.provider.digest.Blake2b diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt index 8feb73f3a..6838f6c3c 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt @@ -171,7 +171,7 @@ object DerivationConfigV1 : DerivationConfig() { -> mapOf(AddressType.Default to DerivationPath("m/44'/246'/0'/0'/0'")) Blockchain.Casper, Blockchain.CasperTestnet, - -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0/0")) + -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0'/0'")) } } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt index b4cacf4cc..b9eed32f7 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt @@ -171,7 +171,7 @@ object DerivationConfigV2 : DerivationConfig() { -> mapOf(AddressType.Default to DerivationPath("m/44'/246'/0'/0'/0'")) Blockchain.Casper, Blockchain.CasperTestnet, - -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0/0")) + -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0'/0'")) } } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt index 1359647d5..5edac97b3 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt @@ -167,7 +167,7 @@ object DerivationConfigV3 : DerivationConfig() { -> mapOf(AddressType.Default to DerivationPath("m/44'/246'/0'/0'/0'")) Blockchain.Casper, Blockchain.CasperTestnet, - -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0/0")) + -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0'/0'")) } } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/externallinkprovider/providers/CasperExternalLinkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/externallinkprovider/providers/CasperExternalLinkProvider.kt index c4953b25f..aa363b31d 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/externallinkprovider/providers/CasperExternalLinkProvider.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/externallinkprovider/providers/CasperExternalLinkProvider.kt @@ -10,10 +10,10 @@ internal class CasperExternalLinkProvider(isTestnet: Boolean) : ExternalLinkProv override val testNetTopUpUrl = "https://testnet.cspr.live/tools/faucet/" override fun explorerUrl(walletAddress: String, contractAddress: String?): String { - return explorerBaseUrl + "deploy/$walletAddress" + return explorerBaseUrl + "account/$walletAddress" } override fun getExplorerTxUrl(transactionHash: String): TxExploreState { - return TxExploreState.Url(url = "${explorerBaseUrl}transactions/$transactionHash") + return TxExploreState.Url(url = "${explorerBaseUrl}deploy/$transactionHash") } } From f47aba9dbece2b235204e73d325b3cd961e65cb9 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Wed, 16 Oct 2024 13:01:48 +0500 Subject: [PATCH 6/9] Fix code style issues --- .../blockchains/casper/CasperTransactionBuilder.kt | 2 +- .../blockchain/blockchains/casper/CasperWalletManager.kt | 2 +- .../blockchain/blockchains/casper/models/CasperBalance.kt | 2 +- .../blockchains/casper/network/CasperNetworkProvider.kt | 2 +- .../blockchains/casper/network/CasperNetworkService.kt | 7 +++---- .../network/converters/CasperBalanceBodyConverter.kt | 4 ++-- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt index 280d91248..988a858ca 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperTransactionBuilder.kt @@ -8,8 +8,8 @@ import com.tangem.blockchain.common.Wallet * @property wallet wallet * */ +@Suppress("UnusedPrivateMember") internal class CasperTransactionBuilder(private val wallet: Wallet) { var minReserve = 2.5.toBigDecimal() - } diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt index 86a8cd7f7..fac03289a 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt @@ -58,4 +58,4 @@ internal class CasperWalletManager( // according to Casper wallet for nowx private val FEE = 0.1.toBigDecimal() } -} \ No newline at end of file +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt index 2f87f94a1..41f24cb58 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt @@ -4,4 +4,4 @@ import java.math.BigDecimal data class CasperBalance( val balance: BigDecimal, -) \ No newline at end of file +) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt index 4d41d5824..33a566c97 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt @@ -6,4 +6,4 @@ import com.tangem.blockchain.extensions.Result interface CasperNetworkProvider : NetworkProvider { suspend fun getBalance(address: String): Result -} \ No newline at end of file +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt index 2cbcff0c5..ca4dbdc3a 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt @@ -3,11 +3,10 @@ package com.tangem.blockchain.blockchains.casper.network import com.tangem.blockchain.blockchains.casper.models.CasperBalance import com.tangem.blockchain.extensions.Result import com.tangem.blockchain.network.MultiNetworkProvider -import java.math.BigDecimal internal class CasperNetworkService( - providers: List -): CasperNetworkProvider { + providers: List, +) : CasperNetworkProvider { override val baseUrl: String get() = multiJsonRpcProvider.currentProvider.baseUrl @@ -17,4 +16,4 @@ internal class CasperNetworkService( override suspend fun getBalance(address: String): Result { return multiJsonRpcProvider.performRequest(CasperNetworkProvider::getBalance, address) } -} \ No newline at end of file +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt index 75ca8c9a4..6880c396e 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt @@ -11,8 +11,8 @@ internal object CasperBalanceBodyConverter { fun convert(address: String): CasperQueryBalanceBody { return CasperQueryBalanceBody( purseIdentifier = CasperQueryBalanceBody.PurseIdentifier( - mainPurseUnderPublicKey = address - ) + mainPurseUnderPublicKey = address, + ), ) } } From 7cbe40970ba0e0002c7d83f8e1002ea69485db69 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Fri, 18 Oct 2024 01:43:44 +0500 Subject: [PATCH 7/9] Use only Secp256k1 and right derivation for it --- .../src/main/java/com/tangem/blockchain/common/Blockchain.kt | 2 +- .../tangem/blockchain/common/derivation/DerivationConfigV1.kt | 2 +- .../tangem/blockchain/common/derivation/DerivationConfigV2.kt | 2 +- .../tangem/blockchain/common/derivation/DerivationConfigV3.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt index 8f5496558..09c253c0c 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt @@ -474,7 +474,6 @@ enum class Blockchain( return when (this) { Unknown -> emptyList() Tezos, - Casper, CasperTestnet, -> listOf( EllipticCurve.Secp256k1, EllipticCurve.Ed25519, @@ -538,6 +537,7 @@ enum class Blockchain( InternetComputer, EnergyWebChain, EnergyWebChainTestnet, Core, CoreTestnet, + Casper, CasperTestnet, -> listOf(EllipticCurve.Secp256k1) Stellar, StellarTestnet, diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt index 6838f6c3c..8feb73f3a 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV1.kt @@ -171,7 +171,7 @@ object DerivationConfigV1 : DerivationConfig() { -> mapOf(AddressType.Default to DerivationPath("m/44'/246'/0'/0'/0'")) Blockchain.Casper, Blockchain.CasperTestnet, - -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0'/0'")) + -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0/0")) } } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt index b9eed32f7..b4cacf4cc 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV2.kt @@ -171,7 +171,7 @@ object DerivationConfigV2 : DerivationConfig() { -> mapOf(AddressType.Default to DerivationPath("m/44'/246'/0'/0'/0'")) Blockchain.Casper, Blockchain.CasperTestnet, - -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0'/0'")) + -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0/0")) } } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt index 5edac97b3..1359647d5 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/derivation/DerivationConfigV3.kt @@ -167,7 +167,7 @@ object DerivationConfigV3 : DerivationConfig() { -> mapOf(AddressType.Default to DerivationPath("m/44'/246'/0'/0'/0'")) Blockchain.Casper, Blockchain.CasperTestnet, - -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0'/0'")) + -> mapOf(AddressType.Default to DerivationPath("m/44'/506'/0'/0/0")) } } } From e4b1d56f5d124679c73ba79ad23c946ca2361866 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Fri, 18 Oct 2024 01:45:07 +0500 Subject: [PATCH 8/9] Fix fetching balance for not activated account --- .../network/provider/CasperRpcNetworkProvider.kt | 15 +++++++++------ .../network/response/CasperRpcResponseAdapter.kt | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt index d03840e24..eae7b0b93 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt @@ -30,17 +30,20 @@ internal class CasperRpcNetworkProvider( onSuccess = { response: CasperRpcResponseResult.Balance -> CasperBalance(balance = BigDecimal(response.balance)) }, - onFailure = { response -> - if (response.isNoActorError()) BlockchainSdkError.AccountNotFound() else toDefaultError(response) + onFailure = { + // Account is not funded yet + if (it.code == ERROR_CODE_QUERY_FAILED) { + Result.Success(CasperBalance(balance = BigDecimal.ZERO)) + } else { + Result.Failure(toDefaultError(it)) + } }, ) - private fun CasperRpcResponse.Failure.isNoActorError() = code == ERROR_CODE_QUERY_FAILED - private suspend inline fun post( body: JsonRPCRequest, onSuccess: (Data) -> Domain, - onFailure: (CasperRpcResponse.Failure) -> BlockchainSdkError = ::toDefaultError, + onFailure: (CasperRpcResponse.Failure) -> Result, ): Result { return try { when (val response = api.post(body = body, postfixUrl = postfixUrl)) { @@ -51,7 +54,7 @@ internal class CasperRpcNetworkProvider( ), ) } - is CasperRpcResponse.Failure -> Result.Failure(error = onFailure(response)) + is CasperRpcResponse.Failure -> onFailure(response) } } catch (e: Exception) { Result.Failure(e.toBlockchainSdkError()) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt index 8cf35db59..5ede588d3 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/response/CasperRpcResponseAdapter.kt @@ -30,7 +30,7 @@ internal object CasperRpcResponseAdapter : JsonAdapter() { } 1 -> { casperRpcResponse = runCatching { failureAdapter.fromJson(reader) } - .mapCatching { CasperRpcResponse.Failure(message = requireNotNull(it).message) } + .mapCatching { requireNotNull(it) } .getOrElse { parsingResponseFailure } } -1 -> reader.skipNameAndValue() From 49692085707edbca8172631d2fbf9cc05ce64702 Mon Sep 17 00:00:00 2001 From: Evgenii Kuzovkin Date: Mon, 21 Oct 2024 12:06:22 +0500 Subject: [PATCH 9/9] AND-8491 Fix review issues --- .../blockchains/casper/CasperProvidersBuilder.kt | 10 +++++++++- .../blockchains/casper/CasperWalletManager.kt | 8 ++++---- .../blockchains/casper/models/CasperBalance.kt | 4 ++-- .../casper/network/CasperNetworkProvider.kt | 2 +- .../converters/CasperBalanceBodyConverter.kt | 4 ---- .../network/provider/CasperRpcNetworkProvider.kt | 13 ++++++++----- .../assembly/impl/CasperWalletManagerAssembly.kt | 1 + 7 files changed, 25 insertions(+), 17 deletions(-) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt index 1e4d11775..e88c35930 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt @@ -14,6 +14,7 @@ import com.tangem.blockchain.extensions.letNotBlank internal class CasperProvidersBuilder( override val providerTypes: List, private val config: BlockchainSdkConfig, + private val blockchain: Blockchain, ) : NetworkProvidersBuilder() { override fun createProviders(blockchain: Blockchain): List { @@ -30,7 +31,13 @@ internal class CasperProvidersBuilder( return createWithPostfixIfContained( baseUrl = baseUrl, postfixUrl = POSTFIX_URL, - create = ::CasperRpcNetworkProvider, + create = { baseUrl, postfixUrl -> + CasperRpcNetworkProvider( + baseUrl = baseUrl, + postfixUrl = postfixUrl, + blockchain = blockchain, + ) + }, ) } @@ -42,6 +49,7 @@ internal class CasperProvidersBuilder( headerInterceptors = listOf( AddHeaderInterceptor(mapOf(NowNodeCredentials.headerApiKey to it)), ), + blockchain = blockchain, ) } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt index fac03289a..72b758912 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperWalletManager.kt @@ -17,7 +17,7 @@ internal class CasperWalletManager( ) : WalletManager(wallet), ReserveAmountProvider { override val currentHost: String get() = networkProvider.baseUrl - val blockchain = wallet.blockchain + private val blockchain = wallet.blockchain override suspend fun updateInternal() { when (val result = networkProvider.getBalance(wallet.address)) { @@ -27,10 +27,10 @@ internal class CasperWalletManager( } private fun updateWallet(balance: CasperBalance) { - if (balance.balance != wallet.amounts[AmountType.Coin]?.value) { + if (balance.value != wallet.amounts[AmountType.Coin]?.value) { wallet.recentTransactions.clear() } - wallet.setCoinValue(balance.balance.movePointLeft(wallet.blockchain.decimals())) + wallet.setCoinValue(balance.value) } private fun updateError(error: BlockchainError) { @@ -55,7 +55,7 @@ internal class CasperWalletManager( networkProvider.getBalance(destinationAddress) is Result.Success companion object { - // according to Casper wallet for nowx + // according to Casper Wallet private val FEE = 0.1.toBigDecimal() } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt index 41f24cb58..459dad51a 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/models/CasperBalance.kt @@ -2,6 +2,6 @@ package com.tangem.blockchain.blockchains.casper.models import java.math.BigDecimal -data class CasperBalance( - val balance: BigDecimal, +internal data class CasperBalance( + val value: BigDecimal, ) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt index 33a566c97..5ae2e04ab 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt @@ -4,6 +4,6 @@ import com.tangem.blockchain.blockchains.casper.models.CasperBalance import com.tangem.blockchain.common.NetworkProvider import com.tangem.blockchain.extensions.Result -interface CasperNetworkProvider : NetworkProvider { +internal interface CasperNetworkProvider : NetworkProvider { suspend fun getBalance(address: String): Result } diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt index 6880c396e..b0b75e2d3 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt @@ -2,10 +2,6 @@ package com.tangem.blockchain.blockchains.casper.network.converters import com.tangem.blockchain.blockchains.casper.network.request.CasperQueryBalanceBody -/** - * Converter from address to [CasperQueryBalanceBody] - * - */ internal object CasperBalanceBodyConverter { fun convert(address: String): CasperQueryBalanceBody { diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt index eae7b0b93..71548e793 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt @@ -21,6 +21,7 @@ internal class CasperRpcNetworkProvider( override val baseUrl: String, private val postfixUrl: String, headerInterceptors: List = emptyList(), + private val blockchain: Blockchain, ) : CasperNetworkProvider { private val api = createRetrofitInstance(baseUrl, headerInterceptors).create(CasperApi::class.java) @@ -28,12 +29,12 @@ internal class CasperRpcNetworkProvider( override suspend fun getBalance(address: String): Result = post( body = CasperRpcBodyFactory.createQueryBalanceBody(address), onSuccess = { response: CasperRpcResponseResult.Balance -> - CasperBalance(balance = BigDecimal(response.balance)) + CasperBalance(value = BigDecimal(response.balance).movePointLeft(blockchain.decimals())) }, onFailure = { // Account is not funded yet if (it.code == ERROR_CODE_QUERY_FAILED) { - Result.Success(CasperBalance(balance = BigDecimal.ZERO)) + Result.Success(CasperBalance(value = BigDecimal.ZERO)) } else { Result.Failure(toDefaultError(it)) } @@ -48,9 +49,11 @@ internal class CasperRpcNetworkProvider( return try { when (val response = api.post(body = body, postfixUrl = postfixUrl)) { is CasperRpcResponse.Success -> { - Result.Success( - data = onSuccess( - moshi.adapter().fromJsonValue(response.result)!!, + runCatching { + moshi.adapter().fromJsonValue(response.result) + }.getOrNull()?.let { Result.Success(onSuccess(it)) } ?: Result.Failure( + BlockchainSdkError.UnsupportedOperation( + "Unknown Casper JSON-RPC response result", ), ) } diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt b/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt index c179e0571..237691019 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt @@ -20,6 +20,7 @@ internal object CasperWalletManagerAssembly : WalletManagerAssembly