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/CasperProvidersBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt new file mode 100644 index 000000000..e88c35930 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/CasperProvidersBuilder.kt @@ -0,0 +1,60 @@ +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, + private val blockchain: Blockchain, +) : 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 = { baseUrl, postfixUrl -> + CasperRpcNetworkProvider( + baseUrl = baseUrl, + postfixUrl = postfixUrl, + blockchain = blockchain, + ) + }, + ) + } + + 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)), + ), + blockchain = blockchain, + ) + } + } + + private companion object { + const val POSTFIX_URL = "rpc" + } +} 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..988a858ca --- /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 + * + */ +@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 new file mode 100644 index 000000000..72b758912 --- /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 + private 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.value != wallet.amounts[AmountType.Coin]?.value) { + wallet.recentTransactions.clear() + } + wallet.setCoinValue(balance.value) + } + + 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 + 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 new file mode 100644 index 000000000..459dad51a --- /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 + +internal data class CasperBalance( + val value: BigDecimal, +) 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/CasperNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkProvider.kt new file mode 100644 index 000000000..5ae2e04ab --- /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 + +internal interface CasperNetworkProvider : NetworkProvider { + suspend fun getBalance(address: String): Result +} 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..ca4dbdc3a --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/CasperNetworkService.kt @@ -0,0 +1,19 @@ +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 + +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) + } +} 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..b0b75e2d3 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/converters/CasperBalanceBodyConverter.kt @@ -0,0 +1,14 @@ +package com.tangem.blockchain.blockchains.casper.network.converters + +import com.tangem.blockchain.blockchains.casper.network.request.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/provider/CasperRpcNetworkProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt new file mode 100644 index 000000000..71548e793 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/casper/network/provider/CasperRpcNetworkProvider.kt @@ -0,0 +1,75 @@ +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(), + private val blockchain: Blockchain, +) : 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(value = BigDecimal(response.balance).movePointLeft(blockchain.decimals())) + }, + onFailure = { + // Account is not funded yet + if (it.code == ERROR_CODE_QUERY_FAILED) { + Result.Success(CasperBalance(value = BigDecimal.ZERO)) + } else { + Result.Failure(toDefaultError(it)) + } + }, + ) + + private suspend inline fun post( + body: JsonRPCRequest, + onSuccess: (Data) -> Domain, + onFailure: (CasperRpcResponse.Failure) -> Result, + ): Result { + return try { + when (val response = api.post(body = body, postfixUrl = postfixUrl)) { + is CasperRpcResponse.Success -> { + runCatching { + moshi.adapter().fromJsonValue(response.result) + }.getOrNull()?.let { Result.Success(onSuccess(it)) } ?: Result.Failure( + BlockchainSdkError.UnsupportedOperation( + "Unknown Casper JSON-RPC response result", + ), + ) + } + is CasperRpcResponse.Failure -> 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 + } +} 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..5ede588d3 --- /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 { requireNotNull(it) } + .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/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/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/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..237691019 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/common/assembly/impl/CasperWalletManagerAssembly.kt @@ -0,0 +1,30 @@ +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, + blockchain = blockchain, + ).build(blockchain), + ), + transactionBuilder = CasperTransactionBuilder(this), + ) + } + } +} 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") } } 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())