From da726c3f5abd3785182d4237385b74a2621d67a1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 20 May 2020 19:43:17 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../blockchains/tezos/TezosAddressService.kt | 37 +++++ .../tezos/TezosTransactionBuilder.kt | 70 +++++++++ .../blockchains/tezos/TezosWalletManager.kt | 109 ++++++++++++++ .../blockchains/tezos/network/TezosApi.kt | 50 +++++++ .../tezos/network/TezosNetworkManager.kt | 134 ++++++++++++++++++ .../tezos/network/TezosProvider.kt | 92 ++++++++++++ .../tezos/network/TezosResponse.kt | 22 +++ .../tangem/blockchain/common/Blockchain.kt | 11 +- .../blockchain/common/WalletManagerFactory.kt | 12 +- .../tangem/blockchain/extensions/Amount.kt | 2 +- .../blockchain/network/RetrofitBuilder.kt | 4 +- 11 files changed, 537 insertions(+), 6 deletions(-) create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosAddressService.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosTransactionBuilder.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosWalletManager.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosApi.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosNetworkManager.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosProvider.kt create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosResponse.kt diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosAddressService.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosAddressService.kt new file mode 100644 index 0000000000..813d80ce33 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosAddressService.kt @@ -0,0 +1,37 @@ +package com.tangem.blockchain.blockchains.tezos + +import com.tangem.blockchain.common.AddressService +import com.tangem.common.extensions.calculateSha256 +import com.tangem.common.extensions.hexToBytes +import org.bitcoinj.core.Base58 +import org.spongycastle.jcajce.provider.digest.Blake2b + +class TezosAddressService : AddressService { + override fun makeAddress(walletPublicKey: ByteArray): String { + val publicKeyHash = Blake2b.Blake2b160().digest(walletPublicKey) + + val tz1Prefix = "06A19F".hexToBytes() + val prefixedHash = tz1Prefix + publicKeyHash + + val checksum = prefixedHash.calculateTezosChecksum() + val prefixedHashWithChecksum = prefixedHash + checksum + + return Base58.encode(prefixedHashWithChecksum) + } + + override fun validate(address: String): Boolean { + val prefixedHashWithChecksum = Base58.decode(address) + if (prefixedHashWithChecksum == null || prefixedHashWithChecksum.size != 27) return false + + val prefixedHash = prefixedHashWithChecksum.copyOf(23) + val checksum = prefixedHashWithChecksum.copyOfRange(23, 27) + + val calculatedChecksum = prefixedHash.calculateTezosChecksum() + + return calculatedChecksum.contentEquals(checksum) + } + + companion object { + fun ByteArray.calculateTezosChecksum() = this.calculateSha256().calculateSha256().copyOfRange(0, 4) + } +} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosTransactionBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosTransactionBuilder.kt new file mode 100644 index 0000000000..8b4503b9ac --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosTransactionBuilder.kt @@ -0,0 +1,70 @@ +package com.tangem.blockchain.blockchains.tezos + +import com.tangem.blockchain.blockchains.tezos.TezosAddressService.Companion.calculateTezosChecksum +import com.tangem.blockchain.blockchains.tezos.network.TezosOperationContent +import com.tangem.blockchain.common.TransactionData +import com.tangem.blockchain.extensions.Result +import com.tangem.blockchain.extensions.bigIntegerValue +import com.tangem.common.extensions.hexToBytes +import com.tangem.common.extensions.toHexString +import org.bitcoinj.core.Base58 +import org.spongycastle.jcajce.provider.digest.Blake2b + +class TezosTransactionBuilder(private val walletPublicKey: ByteArray) { + var counter: Long? = null + + fun buildContents(transactionData: TransactionData, + publicKeyRevealed: Boolean + ): Result> { + if (counter == null) return Result.Failure(Exception("counter is null")) + var counter = counter!! + + val contents = arrayListOf() + + if (!publicKeyRevealed) { + counter++ + val revealOp = TezosOperationContent( + kind = "reveal", + source = transactionData.sourceAddress, + fee = "1300", + counter = counter.toString(), + gas_limit = "10000", + storage_limit = "0", + public_key = encodePublicKey(walletPublicKey) + ) + contents.add(revealOp) + } + + counter++ + val transactionOp = TezosOperationContent( + kind = "transaction", + source = transactionData.sourceAddress, + fee = "1350", + counter = counter.toString(), + gas_limit = "10600", + storage_limit = "277", + destination = transactionData.destinationAddress, + amount = transactionData.amount.bigIntegerValue().toString() + ) + contents.add(transactionOp) + + return Result.Success(contents) + } + + fun buildToSign(forgedContents: String): ByteArray { + val genericOperationWatermark = "03" + return Blake2b.Blake2b256().digest((genericOperationWatermark + forgedContents).hexToBytes()) + } + + fun buildToSend(signature: ByteArray, forgedContents: String) = forgedContents + signature.toHexString() + + private fun encodePublicKey(pkUncompressed: ByteArray): String { + val edpkPrefix = "0D0F25D9".hexToBytes() + val prefixedPubKey = edpkPrefix + pkUncompressed + + val checksum = prefixedPubKey.calculateTezosChecksum() + val prefixedHashWithChecksum = prefixedPubKey + checksum + + return Base58.encode(prefixedHashWithChecksum) + } +} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosWalletManager.kt new file mode 100644 index 0000000000..e1867942e7 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/TezosWalletManager.kt @@ -0,0 +1,109 @@ +package com.tangem.blockchain.blockchains.tezos + +import android.util.Log +import com.tangem.blockchain.blockchains.tezos.network.TezosInfoResponse +import com.tangem.blockchain.blockchains.tezos.network.TezosNetworkManager +import com.tangem.blockchain.common.* +import com.tangem.blockchain.extensions.Result +import com.tangem.blockchain.extensions.SimpleResult +import com.tangem.common.CompletionResult +import com.tangem.common.extensions.isZero +import com.tangem.common.extensions.toHexString +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import java.math.BigDecimal + +class TezosWalletManager( + cardId: String, + wallet: Wallet, + private val transactionBuilder: TezosTransactionBuilder, + private val networkManager: TezosNetworkManager +) : WalletManager(cardId, wallet), TransactionSender { + + private val blockchain = wallet.blockchain + private var publicKeyRevealed: Boolean? = null + + override suspend fun update() { + val response = networkManager.getInfo(wallet.address) + when (response) { + is Result.Success -> updateWallet(response.data) + is Result.Failure -> updateError(response.error) + } + } + + private fun updateWallet(response: TezosInfoResponse) { + Log.d(this::class.java.simpleName, "Balance is ${response.balance}") + wallet.amounts[AmountType.Coin]?.value = response.balance + transactionBuilder.counter = response.counter + } + + private fun updateError(error: Throwable?) { + Log.e(this::class.java.simpleName, error?.message ?: "") + if (error != null) throw error + } + + override suspend fun send(transactionData: TransactionData, signer: TransactionSigner): SimpleResult { + if (publicKeyRevealed == null) return SimpleResult.Failure(Exception("publicKeyRevealed is null")) + + val contents = + when (val response = transactionBuilder.buildContents(transactionData, publicKeyRevealed!!)) { + is Result.Failure -> return SimpleResult.Failure(response.error) + is Result.Success -> response.data + } + val header = + when (val response = networkManager.getHeader()) { + is Result.Failure -> return SimpleResult.Failure(response.error) + is Result.Success -> response.data + } + val forgedContents = //TODO: CHANGE FOR PRODUCTION, this is potential security vulnerability, transaction should be forged locally + when (val response = networkManager.forgeContents(header.hash, contents)) { + is Result.Failure -> return SimpleResult.Failure(response.error) + is Result.Success -> response.data + } + val dataToSign = transactionBuilder.buildToSign(forgedContents) + + val signature = when (val signerResponse = signer.sign(arrayOf(dataToSign), cardId)) { + is CompletionResult.Failure -> return SimpleResult.Failure(signerResponse.error) + is CompletionResult.Success -> signerResponse.data.signature + } + + when (val response = networkManager.checkTransaction(header, contents, signature)) { + is SimpleResult.Failure -> return response + is SimpleResult.Success -> { + val transactionToSend = transactionBuilder.buildToSend(signature,forgedContents) + return networkManager.sendTransaction(transactionToSend) + } + } + } + + override suspend fun getFee(amount: Amount, destination: String): Result> { + var fee: BigDecimal = BigDecimal.valueOf(0.00135) + var error: Result.Failure? = null + + coroutineScope { + val publicKeyRevealedDeferred = async { networkManager.isPublicKeyRevealed(wallet.address) } + val destinationInfoDeferred = async { networkManager.getInfo(destination) } + + when (val result = publicKeyRevealedDeferred.await()) { + is Result.Failure -> error = result + is Result.Success -> { + publicKeyRevealed = result.data + if (!publicKeyRevealed!!) { + fee += BigDecimal.valueOf(0.0013) + } + } + } + + when (val result = destinationInfoDeferred.await()) { + is Result.Failure -> error = result + is Result.Success -> { + if (result.data.balance.isZero()) { + fee += BigDecimal.valueOf(0.257) + } + } + } + } + return if (error == null) Result.Success(listOf(Amount(fee, blockchain))) else error!! + } + +} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosApi.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosApi.kt new file mode 100644 index 0000000000..27b37b48d0 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosApi.kt @@ -0,0 +1,50 @@ +package com.tangem.blockchain.blockchains.tezos.network + +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.Path + +interface TezosApi { + @GET("chains/main/blocks/head/context/contracts/{address}") + suspend fun getAddressData(@Path("address") address: String): TezosAddressResponse + + @GET("chains/main/blocks/head/header") + suspend fun getHeader(): TezosHeaderResponse + + @GET("chains/main/blocks/head/context/contracts/{address}/manager_key") + suspend fun getManagerKey(@Path("address") address: String): String + + @POST("chains/main/blocks/head/helpers/forge/operations") + suspend fun forgeOperations(@Body tezosForgeBody: TezosForgeBody): String + + @POST("chains/main/blocks/head/helpers/preapply/operations") + suspend fun preapplyOperations(@Body tezosPreapplyBodyList: List) + + @POST("injection/operation") + suspend fun sendTransaction(@Body transaction: String) +} + +data class TezosForgeBody( + val branch: String, + val contents: List +) + +data class TezosOperationContent( + val kind: String, + val source: String, + val fee: String, + val counter: String, + val gas_limit: String, + val storage_limit: String, + val public_key: String? = null, + val destination: String? = null, + val amount: String? = null +) + +data class TezosPreapplyBody( + val protocol: String, + val branch: String, + val contents: List, + val signature: String +) \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosNetworkManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosNetworkManager.kt new file mode 100644 index 0000000000..3bca7e5e9d --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosNetworkManager.kt @@ -0,0 +1,134 @@ +package com.tangem.blockchain.blockchains.tezos.network + +import com.tangem.blockchain.extensions.Result +import com.tangem.blockchain.extensions.SimpleResult +import com.tangem.blockchain.network.API_TEZOS +import com.tangem.blockchain.network.API_TEZOS_RESERVE +import com.tangem.blockchain.network.createRetrofitInstance +import retrofit2.HttpException +import java.io.IOException +import java.math.BigDecimal + +class TezosNetworkManager { + private val tezosProvider by lazy { + val api = createRetrofitInstance(API_TEZOS) + .create(TezosApi::class.java) + TezosProvider(api) + } + + private val tezosReserveProvider by lazy { + val api = createRetrofitInstance(API_TEZOS_RESERVE) + .create(TezosApi::class.java) + TezosProvider(api) + } + + var provider = tezosProvider + + private fun changeProvider() { + provider = if (provider == tezosProvider) tezosReserveProvider else tezosProvider + } + + suspend fun getInfo(address: String): Result { + val result = provider.getInfo(address) + when (result) { + is Result.Success -> return result + is Result.Failure -> { + if (result.error is IOException || result.error is HttpException) { + changeProvider() + return provider.getInfo(address) + } else { + return result + } + } + } + } + + suspend fun isPublicKeyRevealed(address: String): Result { + val result = provider.isPublicKeyRevealed(address) + when (result) { + is Result.Success -> return result + is Result.Failure -> { + if (result.error is IOException || result.error is HttpException) { + changeProvider() + return provider.isPublicKeyRevealed(address) + } else { + return result + } + } + } + } + + suspend fun getHeader(): Result { + val result = provider.getHeader() + when (result) { + is Result.Success -> return result + is Result.Failure -> { + if (result.error is IOException || result.error is HttpException) { + changeProvider() + return provider.getHeader() + } else { + return result + } + } + } + } + + suspend fun forgeContents(headerHash: String, contents: List): Result { + val result = provider.forgeContents(headerHash, contents) + when (result) { + is Result.Success -> return result + is Result.Failure -> { + if (result.error is IOException || result.error is HttpException) { + changeProvider() + return provider.forgeContents(headerHash, contents) + } else { + return result + } + } + } + } + + suspend fun checkTransaction( + header: TezosHeader, + contents: List, + signature: ByteArray + ): SimpleResult { + val result = provider.checkTransaction(header, contents, signature) + when (result) { + is SimpleResult.Success -> return result + is SimpleResult.Failure -> { + if (result.error is IOException || result.error is HttpException) { + changeProvider() + return provider.checkTransaction(header, contents, signature) + } else { + return result + } + } + } + } + + suspend fun sendTransaction(transaction: String): SimpleResult { + val result = provider.sendTransaction(transaction) + when (result) { + is SimpleResult.Success -> return result + is SimpleResult.Failure -> { + if (result.error is IOException || result.error is HttpException) { + changeProvider() + return provider.sendTransaction(transaction) + } else { + return result + } + } + } + } +} + +data class TezosInfoResponse( + val balance: BigDecimal, + val counter: Long +) + +data class TezosHeader( + val hash: String, + val protocol: String +) \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosProvider.kt new file mode 100644 index 0000000000..4b264d2857 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosProvider.kt @@ -0,0 +1,92 @@ +package com.tangem.blockchain.blockchains.tezos.network + +import com.tangem.blockchain.blockchains.tezos.TezosAddressService.Companion.calculateTezosChecksum +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.extensions.Result +import com.tangem.blockchain.extensions.SimpleResult +import com.tangem.blockchain.extensions.retryIO +import com.tangem.common.extensions.hexToBytes +import org.bitcoinj.core.Base58 + +class TezosProvider(private val api: TezosApi) { + private val decimals = Blockchain.Tezos.decimals() + + suspend fun getInfo(address: String): Result { + return try { + val addressData = retryIO { api.getAddressData(address) } + Result.Success(TezosInfoResponse( + balance = addressData.balance!!.toBigDecimal().movePointLeft(decimals), + counter = addressData.counter!! + )) + } catch (exception: Exception) { + Result.Failure(exception) + } + } + + suspend fun isPublicKeyRevealed(address: String): Result { + return try { + retryIO { api.getManagerKey(address) } + Result.Success(true) + } catch (exception: Exception) { //TODO: check exception + Result.Success(false) + } + } + + suspend fun getHeader(): Result { + return try { + val headerResponse = retryIO { api.getHeader() } + Result.Success(TezosHeader( + hash = headerResponse.hash!!, + protocol = headerResponse.protocol!! + )) + } catch (exception: Exception) { + Result.Failure(exception) + } + } + + suspend fun forgeContents(headerHash: String, contents: List): Result { + return try { + val forgedContents = retryIO { api.forgeOperations(TezosForgeBody(headerHash, contents)) } + Result.Success(forgedContents) + } catch (exception: Exception) { + Result.Failure(exception) + } + } + + suspend fun checkTransaction( + header: TezosHeader, + contents: List, + signature: ByteArray + ): SimpleResult { + return try { + val tezosPreapplyBody = TezosPreapplyBody( + protocol = header.protocol, + branch = header.hash, + contents = contents, + signature = encodeSignature(signature) + ) + retryIO { api.preapplyOperations(listOf(tezosPreapplyBody)) } + SimpleResult.Success + } catch (exception: Exception) { + SimpleResult.Failure(exception) + } + } + + suspend fun sendTransaction(transaction: String): SimpleResult { + return try { + retryIO { api.sendTransaction(transaction) } + SimpleResult.Success + } catch (exception: Exception) { + SimpleResult.Failure(exception) + } + } + + private fun encodeSignature(signature: ByteArray): String { + val edsigPrefix = "09F5CD8612".hexToBytes() + val prefixedSignature = edsigPrefix + signature + val checksum = prefixedSignature.calculateTezosChecksum() + val prefixedSignatureWithChecksum = prefixedSignature + checksum + + return Base58.encode(prefixedSignatureWithChecksum) + } +} diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosResponse.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosResponse.kt new file mode 100644 index 0000000000..f0ac10e947 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/tezos/network/TezosResponse.kt @@ -0,0 +1,22 @@ +package com.tangem.blockchain.blockchains.tezos.network + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class TezosAddressResponse( + @Json(name = "balance") + var balance: Long? = null, + + @Json(name = "counter") + var counter: Long? = null +) + +@JsonClass(generateAdapter = true) +data class TezosHeaderResponse( + @Json(name = "protocol") + var protocol: String? = null, + + @Json(name = "hash") + var hash: String? = null +) \ No newline at end of file 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 9284ec26b8..d7ba034407 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt @@ -6,6 +6,7 @@ import com.tangem.blockchain.blockchains.bitcoincash.BitcoinCashAddressService import com.tangem.blockchain.blockchains.cardano.CardanoAddressService import com.tangem.blockchain.blockchains.ethereum.EthereumAddressService import com.tangem.blockchain.blockchains.stellar.StellarAddressService +import com.tangem.blockchain.blockchains.tezos.TezosAddressService import com.tangem.blockchain.blockchains.xrp.XrpAddressService enum class Blockchain( @@ -24,11 +25,12 @@ enum class Blockchain( XRP("XRP", "XRP", "XRP Ledger"), Binance("BINANCE", "BNB", "Binance"), BinanceTestnet("BINANCE/test", "BNBt", "Binance"), - Stellar("XLM", "XLM", "Stellar"); + Stellar("XLM", "XLM", "Stellar"), + Tezos("TEZOS", "XTZ", "Tezos"); fun decimals(): Int = when (this) { Bitcoin, BitcoinTestnet, BitcoinCash, Binance, BinanceTestnet, Litecoin -> 8 - Cardano, XRP -> 6 + Cardano, XRP, Tezos -> 6 Ethereum, RSK -> 18 Stellar -> 7 Unknown -> 0 @@ -52,6 +54,7 @@ enum class Blockchain( Binance -> BinanceAddressService() BinanceTestnet -> BinanceAddressService(true) Stellar -> StellarAddressService() + Tezos -> TezosAddressService() } fun getShareUri(address: String): String = when (this) { @@ -63,6 +66,7 @@ enum class Blockchain( fun getExploreUrl(address: String, token: Token? = null): String = when (this) { Binance -> "https://explorer.binance.org/address/$address" + BinanceTestnet -> "https://testnet-explorer.binance.org/address/$address" Bitcoin -> "https://blockchain.info/address/$address" BitcoinTestnet -> "https://live.blockcypher.com/btc-testnet/address/$address" BitcoinCash -> "https://blockchair.com/bitcoin-cash/address/$address" @@ -82,7 +86,8 @@ enum class Blockchain( } Stellar -> "https://stellar.expert/explorer/public/account/$address" XRP -> "https://xrpscan.com/account/$address" - else -> throw Exception("Explore URL not defined!") + Tezos -> "https://tezblock.io/account/$address" + Unknown -> throw Exception("unsupported blockchain") } companion object { 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 2f3d29bc18..1c7af4e354 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt @@ -21,6 +21,9 @@ import com.tangem.blockchain.blockchains.stellar.StellarNetworkManager import com.tangem.blockchain.blockchains.stellar.StellarTransactionBuilder import com.tangem.blockchain.blockchains.stellar.StellarWalletManager +import com.tangem.blockchain.blockchains.tezos.TezosTransactionBuilder +import com.tangem.blockchain.blockchains.tezos.TezosWalletManager +import com.tangem.blockchain.blockchains.tezos.network.TezosNetworkManager import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder import com.tangem.blockchain.blockchains.xrp.XrpWalletManager import com.tangem.blockchain.blockchains.xrp.network.XrpNetworkManager @@ -113,7 +116,14 @@ object WalletManagerFactory { BinanceNetworkManager(true) ) } - else -> return null + Blockchain.Tezos -> { + return TezosWalletManager( + cardId, wallet, + TezosTransactionBuilder(walletPublicKey), + TezosNetworkManager() + ) + } + Blockchain.Unknown -> throw Exception("unsupported blockchain") } } diff --git a/blockchain/src/main/java/com/tangem/blockchain/extensions/Amount.kt b/blockchain/src/main/java/com/tangem/blockchain/extensions/Amount.kt index 9c76097bc5..659630c79c 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/extensions/Amount.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/extensions/Amount.kt @@ -4,7 +4,7 @@ import com.tangem.blockchain.common.Amount import java.math.BigInteger fun Amount.bigIntegerValue(): BigInteger? { - return this.value?.movePointRight(this.decimals.toInt())?.toBigInteger() + return this.value?.movePointRight(this.decimals)?.toBigInteger() } fun Amount.isAboveZero(): Boolean { 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 94d89c0531..8573dff8a7 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt @@ -53,4 +53,6 @@ const val API_ADALITE = "https://explorer3.adalite.io/" const val API_ADALITE_RESERVE = "https://nodes.southeastasia.cloudapp.azure.com/" const val API_RIPPLED = "https://s1.ripple.com:51234/" const val API_RIPPLED_RESERVE = "https://s2.ripple.com:51234/" -const val API_BLOCKCHAIR = "https://api.blockchair.com/" \ No newline at end of file +const val API_BLOCKCHAIR = "https://api.blockchair.com/" +const val API_TEZOS = "https://teznode.letzbake.com" +const val API_TEZOS_RESERVE = "https://mainnet.tezrpc.me" \ No newline at end of file