From d972c1635f88b0f2608ddb83f65bd93104407a32 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 2 Mar 2020 14:26:57 +0300 Subject: [PATCH 1/2] Updated on 2026-08-14 --- blockchain/build.gradle | 21 +++++-- .../bitcoin/BitcoinTransactionBuilder.kt | 1 - .../bitcoin/BitcoinWalletManager.kt | 21 ++++--- .../cardano/CardanoWalletManager.kt | 15 ++--- .../tangem/blockchain/common/Blockchain.kt | 6 +- .../com/tangem/blockchain/common/Wallet.kt | 3 + .../tangem/blockchain/common/WalletManager.kt | 6 +- .../blockchain/common/WalletManagerFactory.kt | 37 +++++++----- .../common/extensions/Coroutines.kt | 19 +++--- .../common/network/RetrofitBuilder.kt | 9 ++- .../blockchain/ethereum/EthereumAddress.kt | 2 +- .../ethereum/EthereumWalletManager.kt | 39 ++++++++---- .../network/EthereumNetworkManager.kt | 1 - .../stellar/StellarNetworkManager.kt | 4 +- .../stellar/StellarWalletManager.kt | 31 ++++------ .../blockchain/wallets/CurrencyWallet.kt | 60 ++++++++++++++++--- .../tangem/blockchain/xrp/XrpWalletManager.kt | 24 ++++---- .../xrp/network/XrpNetworkManager.kt | 1 - .../xrp/network/rippled/RippledProvider.kt | 1 - 19 files changed, 187 insertions(+), 114 deletions(-) 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() From 02af4471e3e70381f76e7fe71707819272894150 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 2 Mar 2020 14:30:07 +0300 Subject: [PATCH 2/2] Updated on 2026-08-14 --- blockchain-demo/.gitignore | 1 + blockchain-demo/build.gradle | 63 ++++++ blockchain-demo/proguard-rules.pro | 21 ++ .../ExampleInstrumentedTest.kt | 22 ++ blockchain-demo/src/main/AndroidManifest.xml | 51 +++++ .../blockchain_demo/BlockchainDemoActivity.kt | 188 ++++++++++++++++++ .../drawable-v24/ic_launcher_foreground.xml | 34 ++++ .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++++++ .../res/layout/activity_blockchain_demo.xml | 96 +++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2963 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4905 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2060 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2783 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4490 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6895 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6387 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10413 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9128 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15132 bytes .../src/main/res/values/colors.xml | 7 + .../src/main/res/values/strings.xml | 3 + .../src/main/res/values/styles.xml | 11 + .../src/main/res/xml/nfc_tech_filter.xml | 8 + .../tangem/blockchain_demo/ExampleUnitTest.kt | 16 ++ 26 files changed, 701 insertions(+) create mode 100644 blockchain-demo/.gitignore create mode 100644 blockchain-demo/build.gradle create mode 100644 blockchain-demo/proguard-rules.pro create mode 100644 blockchain-demo/src/androidTest/java/com/tangem/blockchain_demo/ExampleInstrumentedTest.kt create mode 100644 blockchain-demo/src/main/AndroidManifest.xml create mode 100644 blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt create mode 100644 blockchain-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 blockchain-demo/src/main/res/drawable/ic_launcher_background.xml create mode 100644 blockchain-demo/src/main/res/layout/activity_blockchain_demo.xml create mode 100644 blockchain-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 blockchain-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 blockchain-demo/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 blockchain-demo/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 blockchain-demo/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 blockchain-demo/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 blockchain-demo/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 blockchain-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 blockchain-demo/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 blockchain-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 blockchain-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 blockchain-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 blockchain-demo/src/main/res/values/colors.xml create mode 100644 blockchain-demo/src/main/res/values/strings.xml create mode 100644 blockchain-demo/src/main/res/values/styles.xml create mode 100644 blockchain-demo/src/main/res/xml/nfc_tech_filter.xml create mode 100644 blockchain-demo/src/test/java/com/tangem/blockchain_demo/ExampleUnitTest.kt diff --git a/blockchain-demo/.gitignore b/blockchain-demo/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/blockchain-demo/.gitignore @@ -0,0 +1 @@ +/build diff --git a/blockchain-demo/build.gradle b/blockchain-demo/build.gradle new file mode 100644 index 0000000000..6567a8b453 --- /dev/null +++ b/blockchain-demo/build.gradle @@ -0,0 +1,63 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + + + defaultConfig { + applicationId "com.example.blockchain_demo" + minSdkVersion 21 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + + packagingOptions { + exclude 'lib/x86_64/darwin/libscrypt.dylib' + exclude 'lib/x86_64/freebsd/libscrypt.so' + exclude 'lib/x86_64/linux/libscrypt.so' + } + + viewBinding { + enabled = true + } +} + +dependencies { + implementation project(':tangem-core') + implementation project(':tangem-sdk') + implementation project(':blockchain') + + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin" + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.core:core-ktx:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.android.material:material:1.1.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3' + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.3" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/blockchain-demo/proguard-rules.pro b/blockchain-demo/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/blockchain-demo/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/blockchain-demo/src/androidTest/java/com/tangem/blockchain_demo/ExampleInstrumentedTest.kt b/blockchain-demo/src/androidTest/java/com/tangem/blockchain_demo/ExampleInstrumentedTest.kt new file mode 100644 index 0000000000..2a03ebc11f --- /dev/null +++ b/blockchain-demo/src/androidTest/java/com/tangem/blockchain_demo/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.tangem.blockchain_demo + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.blockchain_demo", appContext.packageName) + } +} \ No newline at end of file diff --git a/blockchain-demo/src/main/AndroidManifest.xml b/blockchain-demo/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..9d092d68db --- /dev/null +++ b/blockchain-demo/src/main/AndroidManifest.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt b/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt new file mode 100644 index 0000000000..0028ee31c5 --- /dev/null +++ b/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt @@ -0,0 +1,188 @@ +package com.tangem.blockchain_demo + +import android.os.Bundle +import android.text.Editable +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.tangem.CardManager +import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.extensions.Result +import com.tangem.blockchain.common.extensions.Signer +import com.tangem.blockchain.common.extensions.SimpleResult +import com.tangem.blockchain_demo.databinding.ActivityBlockchainDemoBinding +import com.tangem.commands.Card +import com.tangem.tangem_sdk_new.extensions.init +import com.tangem.tasks.ScanEvent +import com.tangem.tasks.TaskError +import com.tangem.tasks.TaskEvent +import kotlinx.coroutines.* +import java.math.BigDecimal +import kotlin.coroutines.CoroutineContext + +class BlockchainDemoActivity : AppCompatActivity() { + + private lateinit var cardManager: CardManager + private lateinit var signer: TransactionSigner + private lateinit var card: Card + private lateinit var walletManager: WalletManager + private var issuerDataCounter: Int = 1 + + private lateinit var fee: BigDecimal + + private lateinit var binding: ActivityBlockchainDemoBinding + + private val parentJob = Job() + private val exceptionHandler = CoroutineExceptionHandler { _, throwable -> + handleError(throwable.localizedMessage) + } + private val coroutineContext: CoroutineContext + get() = parentJob + Dispatchers.IO + exceptionHandler + private val scope = CoroutineScope(coroutineContext) + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityBlockchainDemoBinding.inflate(layoutInflater) + val view = binding.root + setContentView(view) + + cardManager = CardManager.init(this) + signer = Signer(cardManager) + + binding.btnScan.setOnClickListener { scan() } + + binding.btnCheckFee.setOnClickListener { requestFee() } + + binding.btnSend.setOnClickListener { send() } + } + + + private fun scan() { + cardManager.scanCard { taskEvent -> + when (taskEvent) { + is TaskEvent.Event -> { + when (taskEvent.data) { + is ScanEvent.OnReadEvent -> { + card = (taskEvent.data as ScanEvent.OnReadEvent).card + walletManager = WalletManagerFactory.makeWalletManager(card)!! + getInfo() + } + } + } + is TaskEvent.Completion -> { + if (taskEvent.error != null) { + if (taskEvent.error !is TaskError.UserCancelled) { + handleError(taskEvent.error.toString()) + } + } + } + } + } + } + + private fun getInfo() { + scope.launch { + walletManager.update() + withContext(Dispatchers.Main) { + binding.tvBalance.text = + "${walletManager.wallet.balances[AmountType.Coin]?.value + ?: "error"} ${walletManager.blockchain.currency}" + val token = walletManager.wallet.balances[AmountType.Token] + if (token != null) { + binding.tvBalance.text = token.currencySymbol + " " + token.value + binding.etSumToSend.text = Editable.Factory.getInstance().newEditable( + token.value.toString() + ) + } else { + binding.etSumToSend.text = + Editable.Factory.getInstance().newEditable( + walletManager.wallet.balances[AmountType.Coin]?.value.toString() + ) + } + binding.btnCheckFee.isEnabled = true + } + } + } + + private fun requestFee() { + if (binding.etReceiverAddress.text.isBlank()) { + Toast.makeText(this, "Please enter receiver address", Toast.LENGTH_LONG).show() + return + } else if (binding.etSumToSend.text.isBlank()) { + Toast.makeText(this, "Choose sum to send", Toast.LENGTH_LONG).show() + return + } + + scope.launch { + val feeResult = (walletManager as FeeProvider).getFee( + walletManager.wallet.balances[AmountType.Token] + ?: walletManager.wallet.balances[AmountType.Coin]!!, + binding.etReceiverAddress.text.toString()) + withContext(Dispatchers.Main) { + when (feeResult) { + is Result.Failure -> { + handleError(feeResult.error?.localizedMessage ?: "Error") + } + is Result.Success -> { + binding.btnSend.isEnabled = true + val fees = feeResult.data + if (fees.size == 1) { + binding.tvFee.text = fees[0].value.toString() + fee = fees[0].value ?: BigDecimal(0) + } else { + binding.tvFee.text = fees[0].value.toString() + "\n" + + fees[1].value.toString() + "\n" + + fees[2].value.toString() + fee = fees[1].value ?: BigDecimal(0) + + } + } + } + } + } + } + + private fun send() { + scope.launch { + val result = (walletManager as TransactionSender).send( + formTransactionData(), + signer) + withContext(Dispatchers.Main) { + when (result) { + is SimpleResult.Failure -> { + handleError(result.error?.localizedMessage ?: "Error") + } + is SimpleResult.Success -> { + binding.tvFee.text = "Success" + } + } + } + } + } + + private fun formTransactionData(): TransactionData { + val amount = if (walletManager.wallet.balances[AmountType.Token] != null) { + walletManager.wallet.balances[AmountType.Token]!! + } else { + walletManager.wallet.balances[AmountType.Coin]!!.copy( + value = binding.etSumToSend.text.toString().toBigDecimal() - fee + ) + } + return TransactionData( + amount, + walletManager.wallet.balances[AmountType.Coin]!!.copy(value = fee), + walletManager.wallet.balances[AmountType.Coin]!!.address!!, + binding.etReceiverAddress.text.toString() + ) + } + + private fun handleError(error: String?) { + Toast.makeText(this, error, Toast.LENGTH_LONG).show() + } + + override fun onDestroy() { + super.onDestroy() + scope.cancel() + } +} \ No newline at end of file diff --git a/blockchain-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/blockchain-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000000..1f6bb29060 --- /dev/null +++ b/blockchain-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/blockchain-demo/src/main/res/drawable/ic_launcher_background.xml b/blockchain-demo/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000..0d025f9bf6 --- /dev/null +++ b/blockchain-demo/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/blockchain-demo/src/main/res/layout/activity_blockchain_demo.xml b/blockchain-demo/src/main/res/layout/activity_blockchain_demo.xml new file mode 100644 index 0000000000..faa8ad1d9e --- /dev/null +++ b/blockchain-demo/src/main/res/layout/activity_blockchain_demo.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + +