diff --git a/blockchain/build.gradle b/blockchain/build.gradle index ad3b46b318..1c30f07eaa 100644 --- a/blockchain/build.gradle +++ b/blockchain/build.gradle @@ -2,6 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' + android { compileSdkVersion 29 buildToolsVersion "29.0.2" @@ -24,6 +25,13 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } } dependencies { @@ -33,11 +41,12 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin" implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.1.0' + implementation 'androidx.core:core-ktx:1.2.0' implementation 'com.squareup.retrofit2:retrofit:2.7.0' implementation 'com.squareup.retrofit2:converter-moshi:2.6.0' implementation 'com.squareup.moshi:moshi:1.9.2' + implementation "com.squareup.moshi:moshi-kotlin:1.9.2" kapt("com.squareup.moshi:moshi-kotlin-codegen:1.9.2") implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2' @@ -45,21 +54,21 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.3" implementation 'org.bitcoinj:bitcoinj-core:0.15.2' - implementation 'com.github.stellar:java-stellar-sdk:0.13.0' + implementation 'com.github.stellar:java-stellar-sdk:0.14.0' implementation "com.madgag.spongycastle:core:1.58.0.0" implementation "com.madgag.spongycastle:prov:1.58.0.0" - ext.kethereum_version = '0.79.5' - implementation "com.github.walleth.kethereum:functions:$kethereum_version" + ext.kethereum_version = '0.81.2' + implementation "com.github.walleth.kethereum:extensions_kotlin:$kethereum_version" + implementation "com.github.walleth.kethereum:extensions_transactions:$kethereum_version" + implementation "com.github.walleth.kethereum:erc55:$kethereum_version" implementation "com.github.walleth.kethereum:keccak_shortcut:$kethereum_version" implementation "com.github.walleth.kethereum:wallet:$kethereum_version" implementation "com.github.walleth.kethereum:crypto_impl_spongycastle:$kethereum_version" implementation "com.github.walleth.kethereum:crypto:$kethereum_version" implementation "com.github.walleth.kethereum:crypto_api:$kethereum_version" implementation "com.github.walleth.kethereum:model:$kethereum_version" - implementation 'com.github.komputing.khex:core:1.0.0-RC6' - implementation 'com.github.komputing.khex:extensions:1.0.0-RC6' implementation 'co.nstant.in:cbor:0.8' diff --git a/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinTransactionBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinTransactionBuilder.kt index d066fa259e..664c45fa0d 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinTransactionBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinTransactionBuilder.kt @@ -2,7 +2,6 @@ package com.tangem.blockchain.bitcoin import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.extensions.Result -import com.tangem.blockchain.common.extensions.toCanonicalised import org.bitcoinj.core.* import org.bitcoinj.crypto.TransactionSignature import org.bitcoinj.script.Script diff --git a/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinWalletManager.kt index a1779ce5ae..58ae155e27 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/bitcoin/BitcoinWalletManager.kt @@ -15,7 +15,7 @@ import java.math.BigDecimal class BitcoinWalletManager( private val cardId: String, private val walletPublicKey: ByteArray, - walletConfig: WalletConfig, + override var wallet: CurrencyWallet, isTestNet: Boolean = false ) : WalletManager, TransactionSender, @@ -23,11 +23,13 @@ class BitcoinWalletManager( override val blockchain = if (isTestNet) Blockchain.BitcoinTestnet else Blockchain.Bitcoin private val address = blockchain.makeAddress(walletPublicKey) - private val currencyWallet = CurrencyWallet(walletConfig, address) - override var wallet: Wallet = currencyWallet private val transactionBuilder = BitcoinTransactionBuilder(isTestNet) private val networkManager = BitcoinNetworkManager(isTestNet) + init { + wallet.balances[AmountType.Coin] = Amount(null, blockchain) + } + override suspend fun update() { val response = networkManager.getInfo(address) when (response) { @@ -38,23 +40,24 @@ class BitcoinWalletManager( private fun updateWallet(response: BitcoinAddressResponse) { Log.d(this::class.java.simpleName, "Balance is ${response.balance}") - currencyWallet.balances[AmountType.Coin]?.value = response.balance + wallet.balances[AmountType.Coin]?.value = response.balance transactionBuilder.unspentOutputs = response.unspentTransactions if (response.hasUnconfirmed) { - if (currencyWallet.pendingTransactions.isEmpty()) { - currencyWallet.pendingTransactions.add(TransactionData( + if (wallet.pendingTransactions.isEmpty()) { + wallet.pendingTransactions.add(TransactionData( Amount(blockchain.currency, decimals = blockchain.decimals), null, "unknown", - currencyWallet.address)) + wallet.address)) } } else { - currencyWallet.pendingTransactions.clear() + wallet.pendingTransactions.clear() } } 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 { @@ -73,7 +76,7 @@ class BitcoinWalletManager( } } - override suspend fun getFee(amount: Amount, source: String, destination: String): Result> { + override suspend fun getFee(amount: Amount, destination: String): Result> { when (val result = networkManager.getFee()) { is Result.Failure -> return result is Result.Success -> { diff --git a/blockchain/src/main/java/com/tangem/blockchain/cardano/CardanoWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/cardano/CardanoWalletManager.kt index e5c7b71a70..edf2acefbb 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/cardano/CardanoWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/cardano/CardanoWalletManager.kt @@ -1,6 +1,5 @@ package com.tangem.blockchain.cardano -import android.util.Base64 import android.util.Log import com.tangem.blockchain.cardano.network.CardanoAddressResponse import com.tangem.blockchain.cardano.network.CardanoNetworkManager @@ -10,20 +9,17 @@ import com.tangem.blockchain.common.extensions.SimpleResult import com.tangem.blockchain.common.extensions.encodeBase64NoWrap import com.tangem.blockchain.wallets.CurrencyWallet import com.tangem.tasks.TaskEvent -import java.math.BigDecimal class CardanoWalletManager( private val cardId: String, private val walletPublicKey: ByteArray, - walletConfig: WalletConfig + override var wallet: CurrencyWallet ) : WalletManager, TransactionSender, FeeProvider { override val blockchain = Blockchain.Cardano private val address = blockchain.makeAddress(walletPublicKey) - private val currencyWallet = CurrencyWallet(walletConfig, address) - override var wallet: Wallet = currencyWallet private val transactionBuilder = CardanoTransactionBuilder() private val networkManager = CardanoNetworkManager() @@ -37,13 +33,14 @@ class CardanoWalletManager( private fun updateWallet(response: CardanoAddressResponse) { Log.d(this::class.java.simpleName, "Balance is ${response.balance.toString()}") - currencyWallet.balances[AmountType.Coin]?.value = + wallet.balances[AmountType.Coin]?.value = response.balance.toBigDecimal().movePointLeft(blockchain.decimals.toInt()) transactionBuilder.unspentOutputs = response.unspentOutputs } 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 { @@ -58,13 +55,13 @@ class CardanoWalletManager( } } - override suspend fun getFee(amount: Amount, source: String, destination: String): Result> { + override suspend fun getFee(amount: Amount, destination: String): Result> { val a = 0.155381 val b = 0.000043946 val size = transactionBuilder.getEstimateSize( - TransactionData(amount, null, source, destination), walletPublicKey + TransactionData(amount, null, address, destination), walletPublicKey ) val fee = (a + b * size).toBigDecimal() - return Result.Success(listOf(Amount(blockchain.currency, fee, source, blockchain.decimals))) + return Result.Success(listOf(Amount(blockchain.currency, fee, address, blockchain.decimals))) } } \ 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 ac90c477bd..37333c2768 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt @@ -2,13 +2,15 @@ package com.tangem.blockchain.common import com.tangem.blockchain.bitcoin.BitcoinAddressFactory import com.tangem.blockchain.bitcoin.BitcoinAddressValidator -import com.tangem.blockchain.ethereum.EthereumAddressFactory -import com.tangem.blockchain.ethereum.EthereumAddressValidator import com.tangem.blockchain.cardano.CardanoAddressFactory import com.tangem.blockchain.cardano.CardanoAddressValidator +import com.tangem.blockchain.ethereum.EthereumAddressFactory +import com.tangem.blockchain.ethereum.EthereumAddressValidator + import com.tangem.blockchain.stellar.StellarAddressFactory import com.tangem.blockchain.xrp.XrpAddressFactory import com.tangem.blockchain.xrp.XrpAddressValidator + import java.math.BigDecimal enum class Blockchain( diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/Wallet.kt b/blockchain/src/main/java/com/tangem/blockchain/common/Wallet.kt index 68f9855e05..6cca63b075 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/Wallet.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/Wallet.kt @@ -30,6 +30,9 @@ data class Amount( address: String? = null, type: AmountType = AmountType.Coin ) : this(blockchain.currency, value, address, blockchain.decimals, type) + + constructor(token: Token, value: BigDecimal? = null) : + this(token.symbol, value, token.contractAddress, token.decimals, AmountType.Token) } data class TransactionData( diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManager.kt index 967385e85b..c39d9b6c0e 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManager.kt @@ -2,12 +2,12 @@ package com.tangem.blockchain.common import com.tangem.blockchain.common.extensions.Result import com.tangem.blockchain.common.extensions.SimpleResult +import com.tangem.blockchain.wallets.CurrencyWallet import com.tangem.commands.SignResponse import com.tangem.tasks.TaskEvent -import kotlinx.coroutines.flow.Flow interface WalletManager { - var wallet: Wallet + var wallet: CurrencyWallet val blockchain: Blockchain suspend fun update() @@ -22,5 +22,5 @@ interface TransactionSigner { } interface FeeProvider { - suspend fun getFee(amount: Amount, source: String, destination: String): Result> + suspend fun getFee(amount: Amount, destination: String): Result> } \ 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 90d8b57cf9..6c9b4105f8 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt @@ -1,10 +1,12 @@ package com.tangem.blockchain.common import com.tangem.blockchain.bitcoin.BitcoinWalletManager +import com.tangem.blockchain.cardano.CardanoWalletManager import com.tangem.blockchain.ethereum.Chain import com.tangem.blockchain.ethereum.EthereumWalletManager -import com.tangem.blockchain.cardano.CardanoWalletManager + import com.tangem.blockchain.stellar.StellarWalletManager +import com.tangem.blockchain.wallets.CurrencyWallet import com.tangem.blockchain.xrp.XrpWalletManager import com.tangem.commands.Card @@ -13,53 +15,56 @@ object WalletManagerFactory { fun makeWalletManager(card: Card): WalletManager? { val walletPublicKey: ByteArray = card.walletPublicKey ?: return null val blockchainName: String = card.cardData?.blockchainName ?: return null + val blockchain = Blockchain.fromId(blockchainName) - when { - blockchainName == Blockchain.Bitcoin.id -> { + val token = getToken(card) + val wallet = CurrencyWallet.newInstance(blockchain, blockchain.makeAddress(walletPublicKey), token) + + + when (blockchain) { + Blockchain.Bitcoin -> { return BitcoinWalletManager( cardId = card.cardId, walletPublicKey = walletPublicKey, - walletConfig = WalletConfig(true, true) + wallet = wallet ) } - blockchainName == Blockchain.BitcoinTestnet.id -> { + Blockchain.BitcoinTestnet -> { return BitcoinWalletManager( cardId = card.cardId, walletPublicKey = walletPublicKey, - walletConfig = WalletConfig(true, true), + wallet = wallet, isTestNet = true ) } - blockchainName == Blockchain.Ethereum.id -> { + Blockchain.Ethereum -> { val chain = Chain.Mainnet return EthereumWalletManager( cardId = card.cardId, walletPublicKey = walletPublicKey, - walletConfig = WalletConfig(true, true), + wallet = wallet, chain = chain ) } - blockchainName == Blockchain.Stellar.id -> { - val token = getToken(card) + Blockchain.Stellar -> { return StellarWalletManager( cardId = card.cardId, walletPublicKey = walletPublicKey, - walletConfig = WalletConfig(true, token == null), - token = token + wallet = wallet ) } - blockchainName == Blockchain.Cardano.id -> { + Blockchain.Cardano -> { return CardanoWalletManager( cardId = card.cardId, walletPublicKey = walletPublicKey, - walletConfig = WalletConfig(false, true) + wallet = wallet ) } - blockchainName == Blockchain.XRP.id -> { + Blockchain.XRP -> { return XrpWalletManager( cardId = card.cardId, walletPublicKey = walletPublicKey, - walletConfig = WalletConfig(true, true) + wallet = wallet ) } else -> return null diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/extensions/Coroutines.kt b/blockchain/src/main/java/com/tangem/blockchain/common/extensions/Coroutines.kt index 03d2b2f009..cdf9edd92e 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/extensions/Coroutines.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/extensions/Coroutines.kt @@ -4,12 +4,11 @@ import com.tangem.CardManager import com.tangem.blockchain.common.TransactionSigner import com.tangem.commands.SignResponse import com.tangem.tasks.TaskEvent -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.delay +import kotlinx.coroutines.suspendCancellableCoroutine import java.io.IOException import kotlin.coroutines.resume -import kotlin.coroutines.suspendCoroutine + suspend fun retryIO( times: Int = 3, @@ -56,11 +55,11 @@ sealed class SimpleResult { } class Signer(private val cardManager: CardManager) : TransactionSigner { - override suspend fun sign(hashes: Array, cardId: String): TaskEvent = coroutineScope { - async { - suspendCancellableCoroutine> { continuation -> - cardManager.sign(hashes, cardId) { if (continuation.isActive) continuation.resume(it) } + override suspend fun sign(hashes: Array, cardId: String): TaskEvent = + suspendCancellableCoroutine { continuation -> + cardManager.sign(hashes, cardId) { result -> + if (continuation.isActive) continuation.resume(result) + } } - }.await() - } } + diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/network/RetrofitBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/common/network/RetrofitBuilder.kt index 9834fc8cb9..afcffa0bfb 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/network/RetrofitBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/network/RetrofitBuilder.kt @@ -1,5 +1,7 @@ package com.tangem.blockchain.common.network +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.tangem.blockchain.BuildConfig import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor @@ -18,11 +20,16 @@ private fun createHttpLoggingInterceptor(): HttpLoggingInterceptor { return logging } +private val moshi: Moshi by lazy { + Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() +} fun createRetrofitInstance(baseUrl: String): Retrofit = Retrofit.Builder() .baseUrl(baseUrl) - .addConverterFactory(MoshiConverterFactory.create()) + .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(okHttpClient) .build() diff --git a/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumAddress.kt b/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumAddress.kt index 200a1ca465..a301ee7e1c 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumAddress.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumAddress.kt @@ -1,7 +1,7 @@ package com.tangem.blockchain.ethereum import org.kethereum.crypto.toAddress -import org.kethereum.functions.isValid +import org.kethereum.erc55.isValid import org.kethereum.model.Address import org.kethereum.model.PublicKey diff --git a/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumWalletManager.kt index e7bad943ba..d7c26e526e 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/ethereum/EthereumWalletManager.kt @@ -1,6 +1,8 @@ package com.tangem.blockchain.ethereum +import android.util.Log import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.extensions.Result import com.tangem.blockchain.common.extensions.SimpleResult import com.tangem.blockchain.ethereum.network.EthereumNetworkManager @@ -12,7 +14,7 @@ import org.kethereum.DEFAULT_GAS_LIMIT import org.kethereum.crypto.api.ec.ECDSASignature import org.kethereum.crypto.determineRecId import org.kethereum.crypto.impl.ec.canonicalise -import org.kethereum.functions.encodeRLP +import org.kethereum.extensions.transactions.encodeRLP import org.kethereum.keccakshortcut.keccak import org.kethereum.model.* import java.math.BigDecimal @@ -22,22 +24,32 @@ class EthereumWalletManager( private val cardId: String, private val walletPublicKey: ByteArray, chain: Chain, - walletConfig: WalletConfig + token: Token? = null, + override var wallet: CurrencyWallet ) : WalletManager, TransactionSender, FeeProvider { override val blockchain: Blockchain = Blockchain.Ethereum private val address = blockchain.makeAddress(walletPublicKey) - private val currencyWallet = CurrencyWallet(walletConfig, address) - override var wallet: Wallet = currencyWallet private val builder = EthereumTransactionBuilder(chain) private val networkManager = EthereumNetworkManager() private var pendingTxCount = -1L private var txCount = -1L + init { + if (token != null) wallet.balances[AmountType.Token] = + Amount( + token.symbol, + null, + token.contractAddress, + token.decimals, + AmountType.Token) + wallet.balances[AmountType.Coin] = Amount(null, blockchain) + } + override suspend fun update() { - val result = networkManager.getInfo(address, currencyWallet.balances[AmountType.Token]?.address) + val result = networkManager.getInfo(address, wallet.balances[AmountType.Token]?.address) when (result) { is Result.Failure -> updateError(result.error) is Result.Success -> updateWallet(result.data) @@ -45,23 +57,24 @@ class EthereumWalletManager( } private fun updateWallet(data: EthereumResponse) { - currencyWallet.balances[AmountType.Coin]?.value = data.balance - currencyWallet.balances[AmountType.Token]?.value = data.tokenBalance + wallet.balances[AmountType.Coin]?.value = data.balance + wallet.balances[AmountType.Token]?.value = data.tokenBalance txCount = data.txCount pendingTxCount = data.pendingTxCount if (txCount == pendingTxCount) { - currencyWallet.pendingTransactions.forEach { it.status = TransactionStatus.Confirmed } - } else if (currencyWallet.pendingTransactions.isEmpty()) { - currencyWallet.pendingTransactions.add(TransactionData( + wallet.pendingTransactions.forEach { it.status = TransactionStatus.Confirmed } + } else if (wallet.pendingTransactions.isEmpty()) { + wallet.pendingTransactions.add(TransactionData( Amount(blockchain.currency, decimals = blockchain.decimals), null, "unknown", - currencyWallet.address)) + wallet.address)) } } 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 { @@ -76,7 +89,7 @@ class EthereumWalletManager( } } - override suspend fun getFee(amount: Amount, source: String, destination: String): Result> { + override suspend fun getFee(amount: Amount, destination: String): Result> { val result = networkManager.getFee(getGasLimit(amount).value) when (result) { is Result.Success -> { diff --git a/blockchain/src/main/java/com/tangem/blockchain/ethereum/network/EthereumNetworkManager.kt b/blockchain/src/main/java/com/tangem/blockchain/ethereum/network/EthereumNetworkManager.kt index c141f51aef..b7318ba032 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/ethereum/network/EthereumNetworkManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/ethereum/network/EthereumNetworkManager.kt @@ -12,7 +12,6 @@ import kotlinx.coroutines.coroutineScope import org.kethereum.ETH_IN_WEI import java.math.BigDecimal import java.math.BigInteger -import java.math.RoundingMode class EthereumNetworkManager { diff --git a/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarNetworkManager.kt b/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarNetworkManager.kt index 87102f42e6..85e5cfbd04 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarNetworkManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarNetworkManager.kt @@ -54,7 +54,7 @@ class StellarNetworkManager(isTestNet: Boolean) { coroutineScope { val accountResponseDefered = async(Dispatchers.IO) { stellarServer.accounts().account(accountId) } val ledgerResponseDeferred = async(Dispatchers.IO) { - val latestLedger: Int = stellarServer.root().coreLatestLedger + val latestLedger: Int = stellarServer.root().historyLatestLedger stellarServer.ledgers().ledger(latestLedger.toLong()) } @@ -67,7 +67,7 @@ class StellarNetworkManager(isTestNet: Boolean) { null } else { accountResponse.balances - .find { it.assetType != "native" && it.assetCode == assetCode } + .find { it.assetType != "native" && it.assetIssuer == assetCode } ?.balance?.toBigDecimal() ?: return@coroutineScope Result.Failure(Exception("Stellar Balance not found")) } diff --git a/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarWalletManager.kt index a8b02ccf97..e65278fa35 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/stellar/StellarWalletManager.kt @@ -1,5 +1,6 @@ package com.tangem.blockchain.stellar +import android.util.Log import com.tangem.blockchain.common.* import com.tangem.blockchain.common.extensions.Result import com.tangem.blockchain.common.extensions.SimpleResult @@ -11,8 +12,7 @@ import java.util.* class StellarWalletManager( private val cardId: String, walletPublicKey: ByteArray, - walletConfig: WalletConfig, - token: Token? = null, + override var wallet: CurrencyWallet, isTestNet: Boolean = false ) : WalletManager, TransactionSender, @@ -20,26 +20,14 @@ class StellarWalletManager( override val blockchain: Blockchain = Blockchain.Stellar private val address = blockchain.makeAddress(walletPublicKey) - private val currencyWallet = CurrencyWallet(walletConfig, address) - override var wallet: Wallet = currencyWallet private val networkManager = StellarNetworkManager(isTestNet) private val builder = StellarTransactionBuilder(networkManager, walletPublicKey) private var baseFee = BASE_FEE private var baseReserve = BASE_RESERVE private var sequence = 0L - init { - if (token != null) currencyWallet.balances[AmountType.Token] = - Amount( - token.symbol, - null, - token.contractAddress, - token.decimals, - AmountType.Token) - } - override suspend fun update() { - val result = networkManager.getInfo(address, currencyWallet.balances[AmountType.Token]?.address) + val result = networkManager.getInfo(address, wallet.balances[AmountType.Token]?.address) when (result) { is Result.Failure -> updateError(result.error) is Result.Success -> updateWallet(result.data) @@ -47,15 +35,15 @@ class StellarWalletManager( } private fun updateWallet(data: StellarResponse) { - currencyWallet.balances[AmountType.Coin]?.value = data.balance - currencyWallet.balances[AmountType.Token]?.value = data.assetBalance - currencyWallet.balances[AmountType.Reserve]?.value = data.baseReserve + wallet.balances[AmountType.Coin]?.value = data.balance + wallet.balances[AmountType.Token]?.value = data.assetBalance + wallet.balances[AmountType.Reserve]?.value = data.baseReserve sequence = data.sequence baseFee = data.baseFee baseReserve = data.baseReserve val currentTime = Calendar.getInstance().timeInMillis - currencyWallet.pendingTransactions.forEach { transaction -> + wallet.pendingTransactions.forEach { transaction -> if (transaction.date?.timeInMillis ?: 0 - currentTime > 10) { transaction.status = TransactionStatus.Confirmed } @@ -63,7 +51,8 @@ class StellarWalletManager( } 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 { @@ -77,7 +66,7 @@ class StellarWalletManager( } } - override suspend fun getFee(amount: Amount, source: String, destination: String): Result> { + override suspend fun getFee(amount: Amount, destination: String): Result> { return Result.Success(listOf( Amount(baseFee, blockchain) )) diff --git a/blockchain/src/main/java/com/tangem/blockchain/wallets/CurrencyWallet.kt b/blockchain/src/main/java/com/tangem/blockchain/wallets/CurrencyWallet.kt index 218964d51c..e308ac49e0 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/wallets/CurrencyWallet.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/wallets/CurrencyWallet.kt @@ -4,17 +4,63 @@ import com.tangem.blockchain.common.* import java.util.* class CurrencyWallet( - override val config: WalletConfig, - override val address: String, - override val exploreUrl: String? = null, - override val shareUrl: String? = null, - val pendingTransactions: MutableList = mutableListOf(), - val balances: MutableMap = mutableMapOf(), - val isTestnet: Boolean = false + val blockchain: Blockchain, + address: String, + override val config: WalletConfig ) : Wallet, TransactionValidator { + override val exploreUrl: String? = null + override val shareUrl: String? = null + override val address: String + get() = balances[AmountType.Coin]!!.address!! + + val pendingTransactions: MutableList = mutableListOf() + val balances: MutableMap = mutableMapOf() + + init { + addAmount(Amount(null, blockchain, address)) + } override fun validateTransaction(amount: Amount, fee: Amount?): EnumSet { TODO("not implemented") } + + fun addAmount(amount: Amount) { + balances[amount.type] = amount + } + + fun addPendingTransaction(transaction: TransactionData) { + pendingTransactions.add(transaction.copy(date = Calendar.getInstance())) + } + + companion object { + fun newInstance(blockchain: Blockchain, address: String, token: Token?): CurrencyWallet { + + return when (blockchain) { + Blockchain.Bitcoin, Blockchain.XRP -> { + val config = WalletConfig(true, true) + CurrencyWallet(blockchain, address, config) + } + Blockchain.Cardano -> { + val config = WalletConfig(false, true) + CurrencyWallet(blockchain, address, config) + } + Blockchain.Ethereum -> { + val config = WalletConfig(true, token == null) + val wallet = CurrencyWallet(blockchain, address, config) + if (token != null) wallet.addAmount(Amount(token)) + wallet + } + Blockchain.Stellar -> { + val config = WalletConfig(false, token == null) + val wallet = CurrencyWallet(blockchain, address, config) + if (token != null) wallet.addAmount(Amount(token)) + wallet.addAmount(Amount(null, blockchain, address, AmountType.Reserve)) + wallet + } + else -> throw Exception("Unsupported blockchain") + } + + } + } } \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/xrp/XrpWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/xrp/XrpWalletManager.kt index f2ea7fa7d3..bba2e26427 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/xrp/XrpWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/xrp/XrpWalletManager.kt @@ -12,18 +12,21 @@ import com.tangem.tasks.TaskEvent class XrpWalletManager( private val cardId: String, private val walletPublicKey: ByteArray, - walletConfig: WalletConfig + override var wallet: CurrencyWallet ) : WalletManager, TransactionSender, FeeProvider { override val blockchain = Blockchain.XRP private val address = blockchain.makeAddress(walletPublicKey) - private val currencyWallet = CurrencyWallet(walletConfig, address) - override var wallet: Wallet = currencyWallet private val transactionBuilder = XrpTransactionBuilder(walletPublicKey) private val networkManager = XrpNetworkManager() + init { + wallet.balances[AmountType.Coin] = Amount(null, blockchain) + wallet.balances[AmountType.Reserve] = Amount(null, blockchain, type = AmountType.Reserve) + } + override suspend fun update() { val result = networkManager.getInfo(address) when (result) { @@ -34,30 +37,31 @@ class XrpWalletManager( private fun updateWallet(response: XrpInfoResponse) { Log.d(this::class.java.simpleName, "Balance is ${response.balance}") - currencyWallet.balances[AmountType.Reserve]?.value = response.reserveBase + wallet.balances[AmountType.Reserve]?.value = response.reserveBase if (!response.accountFound) { updateError(Exception("Account not found")) //TODO rework, add reserve return } - currencyWallet.balances[AmountType.Coin]?.value = response.balance - response.reserveBase + wallet.balances[AmountType.Coin]?.value = response.balance - response.reserveBase transactionBuilder.sequence = response.sequence if (response.hasUnconfirmed) { - if (currencyWallet.pendingTransactions.isEmpty()) { - currencyWallet.pendingTransactions.add(TransactionData( + if (wallet.pendingTransactions.isEmpty()) { + wallet.pendingTransactions.add(TransactionData( Amount(blockchain.currency, decimals = blockchain.decimals), null, "unknown", - currencyWallet.address)) + wallet.address)) } } else { - currencyWallet.pendingTransactions.clear() + wallet.pendingTransactions.clear() } } 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 { @@ -72,7 +76,7 @@ class XrpWalletManager( } } - override suspend fun getFee(amount: Amount, source: String, destination: String): Result> { + override suspend fun getFee(amount: Amount, destination: String): Result> { val result = networkManager.getFee() when (result) { is Result.Failure -> return result diff --git a/blockchain/src/main/java/com/tangem/blockchain/xrp/network/XrpNetworkManager.kt b/blockchain/src/main/java/com/tangem/blockchain/xrp/network/XrpNetworkManager.kt index c7aa738a23..8066fe1bea 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/xrp/network/XrpNetworkManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/xrp/network/XrpNetworkManager.kt @@ -1,6 +1,5 @@ package com.tangem.blockchain.xrp.network -import com.tangem.blockchain.bitcoin.network.BitcoinFee import com.tangem.blockchain.common.extensions.Result import com.tangem.blockchain.common.extensions.SimpleResult import com.tangem.blockchain.common.network.API_RIPPLED diff --git a/blockchain/src/main/java/com/tangem/blockchain/xrp/network/rippled/RippledProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/xrp/network/rippled/RippledProvider.kt index ee0c499ce0..73e67cd19c 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/xrp/network/rippled/RippledProvider.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/xrp/network/rippled/RippledProvider.kt @@ -8,7 +8,6 @@ import com.tangem.blockchain.xrp.network.XrpFeeResponse import com.tangem.blockchain.xrp.network.XrpInfoResponse import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope -import java.math.BigDecimal class RippledProvider(private val api: RippledApi) { private val decimals = Blockchain.XRP.decimals.toInt()