From f0294072fb2022235f55d5c6afe6b0b90056f9f9 Mon Sep 17 00:00:00 2001 From: abdrasulov Date: Thu, 26 Sep 2024 18:06:57 +0600 Subject: [PATCH] Add conversion for remaining ton transaction types --- app/build.gradle | 10 +- .../bankwallet/core/Interfaces.kt | 2 +- .../core/adapters/BaseTonAdapter.kt | 1 - .../bankwallet/core/adapters/TonAdapter.kt | 24 ++ .../core/adapters/TonTransactionConverter.kt | 48 ++- .../core/factories/AdapterFactory.kt | 7 +- .../core/managers/AdapterManager.kt | 2 +- .../bankwallet/core/managers/FaqManager.kt | 2 +- .../bankwallet/core/managers/GuidesManager.kt | 2 +- .../bankwallet/core/managers/TonKitManager.kt | 28 +- .../balance/BalanceAdapterRepository.kt | 2 +- .../modules/balance/BalanceService.kt | 2 +- .../modules/balance/BalanceViewModel.kt | 2 +- .../transactionInfo/TransactionInfoService.kt | 32 +- .../TransactionInfoViewItemFactory.kt | 286 +++++++++++++----- .../TransactionViewItemFactory.kt | 86 ++---- app/src/main/res/values/strings.xml | 1 + 17 files changed, 364 insertions(+), 173 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d31e6bc2e83..7ad7d8151f1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -179,6 +179,12 @@ android { substitute module('com.tinder.scarlet:message-adapter-gson:0.1.12') using module('com.github.WalletConnect.Scarlet:message-adapter-gson:1.0.0') substitute module('com.tinder.scarlet:lifecycle-android:0.1.12') using module('com.github.WalletConnect.Scarlet:lifecycle-android:1.0.0') } + + resolutionStrategy.eachDependency { details -> + if (details.requested.group == 'com.squareup.okhttp3') { + details.useVersion "4.12.0" + } + } } } @@ -232,7 +238,7 @@ dependencies { implementation 'com.squareup.retrofit2:adapter-rxjava2:2.11.0' implementation 'com.squareup.retrofit2:converter-gson:2.11.0' implementation 'com.squareup.retrofit2:converter-scalars:2.11.0' - implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0' + implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0' implementation 'com.google.code.gson:gson:2.10.1' implementation "androidx.biometric:biometric:$biometric_version" @@ -269,7 +275,7 @@ dependencies { debugImplementation leakCanary // Wallet kits - implementation 'com.github.horizontalsystems:ton-kit-android:b632c02' + implementation 'com.github.horizontalsystems:ton-kit-android:e907480' implementation 'com.github.horizontalsystems:bitcoin-kit-android:47db768' implementation 'com.github.horizontalsystems:ethereum-kit-android:3d83900' implementation 'com.github.horizontalsystems:blockchain-fee-rate-kit-android:1d3bd49' diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt index 50be2267077..52077825f9d 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/Interfaces.kt @@ -63,7 +63,7 @@ import io.horizontalsystems.tronkit.models.Address as TronAddress interface IAdapterManager { val adaptersReadyObservable: Flowable> fun startAdapterManager() - fun refresh() + suspend fun refresh() fun getAdapterForWallet(wallet: Wallet): IAdapter? fun getAdapterForToken(token: Token): IAdapter? fun getBalanceAdapterForWallet(wallet: Wallet): IBalanceAdapter? diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/BaseTonAdapter.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/BaseTonAdapter.kt index af8ec0566ed..0df243f25d7 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/BaseTonAdapter.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/BaseTonAdapter.kt @@ -4,7 +4,6 @@ import io.horizontalsystems.bankwallet.core.IAdapter import io.horizontalsystems.bankwallet.core.IBalanceAdapter import io.horizontalsystems.bankwallet.core.IReceiveAdapter import io.horizontalsystems.bankwallet.core.managers.TonKitWrapper -import io.horizontalsystems.bankwallet.core.managers.network import io.horizontalsystems.bankwallet.core.managers.statusInfo import io.horizontalsystems.tonkit.models.Network diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonAdapter.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonAdapter.kt index 0abb211a06d..2d274e51434 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonAdapter.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonAdapter.kt @@ -124,6 +124,11 @@ class TonTransactionRecord( when (val type = action.type) { is Action.Type.Receive -> type.value is Action.Type.Send -> type.value + is Action.Type.Burn -> type.value + is Action.Type.Mint -> type.value + is Action.Type.ContractCall -> type.value + is Action.Type.ContractDeploy, + is Action.Type.Swap, is Action.Type.Unsupported -> null } } @@ -146,6 +151,25 @@ class TonTransactionRecord( val comment: String?, ) : Type() + data class Burn(val value: TransactionValue) : Type() + + data class Mint(val value: TransactionValue) : Type() + + data class Swap( + val routerName: String?, + val routerAddress: String, + val valueIn: TransactionValue, + val valueOut: TransactionValue + ) : Type() + + data class ContractDeploy(val interfaces: List) : Type() + + data class ContractCall( + val address: String, + val value: TransactionValue, + val operation: String + ) : Type() + data class Unsupported(val type: String) : Type() } } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonTransactionConverter.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonTransactionConverter.kt index 85fd2f3e6f3..be273d46b88 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonTransactionConverter.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/adapters/TonTransactionConverter.kt @@ -1,8 +1,6 @@ package io.horizontalsystems.bankwallet.core.adapters import io.horizontalsystems.bankwallet.core.ICoinManager -import io.horizontalsystems.bankwallet.core.managers.EvmLabelManager -import io.horizontalsystems.bankwallet.core.managers.TonKitWrapper import io.horizontalsystems.bankwallet.entities.TransactionValue import io.horizontalsystems.bankwallet.modules.transactions.TransactionSource import io.horizontalsystems.bankwallet.modules.transactions.TransactionStatus @@ -10,6 +8,7 @@ import io.horizontalsystems.marketkit.models.BlockchainType import io.horizontalsystems.marketkit.models.Token import io.horizontalsystems.marketkit.models.TokenQuery import io.horizontalsystems.marketkit.models.TokenType +import io.horizontalsystems.tonkit.Address import io.horizontalsystems.tonkit.models.AccountAddress import io.horizontalsystems.tonkit.models.Action import io.horizontalsystems.tonkit.models.Event @@ -18,13 +17,11 @@ import java.math.BigDecimal import java.math.BigInteger class TonTransactionConverter( + private val address: Address, private val coinManager: ICoinManager, - private val tonKitWrapper: TonKitWrapper, private val source: TransactionSource, - private val baseToken: Token, - private val evmLabelManager: EvmLabelManager + private val baseToken: Token ) { - val address = tonKitWrapper.tonKit.receiveAddress fun createTransactionRecord(event: Event): TonTransactionRecord { val actions = event.actions.map { action -> @@ -133,6 +130,45 @@ class TonTransactionConverter( } } + action.jettonBurn?.let { jettonBurn -> + return TonTransactionRecord.Action.Type.Burn( + value = jettonValue(jettonBurn.jetton, jettonBurn.amount, true) + ) + } + + action.jettonMint?.let { jettonMint -> + return TonTransactionRecord.Action.Type.Mint( + value = jettonValue(jettonMint.jetton, jettonMint.amount, false) + ) + } + + action.contractDeploy?.let { contractDeploy -> + return TonTransactionRecord.Action.Type.ContractDeploy( + interfaces = contractDeploy.interfaces + ) + } + + action.jettonSwap?.let { jettonSwap -> + return TonTransactionRecord.Action.Type.Swap( + routerName = jettonSwap.router.name, + routerAddress = format(jettonSwap.router), + valueIn = jettonSwap.jettonMasterIn?.let { + jettonValue(it, jettonSwap.amountIn, true) + } ?: tonValue(jettonSwap.tonIn ?: BigInteger.ZERO, true), + valueOut = jettonSwap.jettonMasterOut?.let { + jettonValue(it, jettonSwap.amountOut, false) + } ?: tonValue(jettonSwap.tonOut ?: BigInteger.ZERO, false), + ) + } + + action.smartContractExec?.let { smartContractExec -> + return TonTransactionRecord.Action.Type.ContractCall( + address = format(smartContractExec.contract), + value = tonValue(smartContractExec.tonAttached, true), + operation = smartContractExec.operation + ) + } + return TonTransactionRecord.Action.Type.Unsupported(action.type.name) } } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/factories/AdapterFactory.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/factories/AdapterFactory.kt index 745313b4752..74b9a7efc84 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/factories/AdapterFactory.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/factories/AdapterFactory.kt @@ -214,7 +214,12 @@ class AdapterFactory( fun tonTransactionsAdapter(source: TransactionSource): ITransactionsAdapter? { val tonKitWrapper = tonKitManager.getTonKitWrapper(source.account) val baseToken = coinManager.getToken(TokenQuery(BlockchainType.Ton, TokenType.Native)) ?: return null - val tonTransactionConverter = TonTransactionConverter(coinManager, tonKitWrapper, source, baseToken, evmLabelManager) + val tonTransactionConverter = TonTransactionConverter( + tonKitWrapper.tonKit.receiveAddress, + coinManager, + source, + baseToken + ) return TonTransactionsAdapter(tonKitWrapper, tonTransactionConverter) } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/AdapterManager.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/AdapterManager.kt index 34a6e82ca46..7c130d52e4b 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/AdapterManager.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/AdapterManager.kt @@ -100,7 +100,7 @@ class AdapterManager( initAdapters(walletManager.activeWallets) } - override fun refresh() { + override suspend fun refresh() { handler.post { adaptersMap.values.forEach { it.refresh() } } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/FaqManager.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/FaqManager.kt index 6b853133838..5c2ad24bf90 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/FaqManager.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/FaqManager.kt @@ -53,7 +53,7 @@ object FaqManager { val response = OkHttpClient().newCall(request).execute() val listType = object : TypeToken>() {}.type - val list: List = gson.fromJson(response.body.charStream(), listType) + val list: List = gson.fromJson(response.body?.charStream(), listType) response.close() list diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/GuidesManager.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/GuidesManager.kt index 552f7c2bf90..020af588bd8 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/GuidesManager.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/GuidesManager.kt @@ -28,7 +28,7 @@ object GuidesManager { .build() val response = OkHttpClient().newCall(request).execute() - val categories = gson.fromJson(response.body.charStream(), Array::class.java) + val categories = gson.fromJson(response.body?.charStream(), Array::class.java) response.close() categories diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/TonKitManager.kt b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/TonKitManager.kt index 4fb4239fe8d..e8fc6a90a05 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/TonKitManager.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/core/managers/TonKitManager.kt @@ -24,7 +24,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch class TonKitManager( - private val backgroundManager: BackgroundManager + private val backgroundManager: BackgroundManager, ) { private val scope = CoroutineScope(Dispatchers.Default) private var job: Job? = null @@ -77,7 +77,7 @@ class TonKitManager( private fun createKitInstance( accountType: AccountType.Mnemonic, - account: Account + account: Account, ): TonKitWrapper { val hdWallet = HDWallet(accountType.seed, 607, HDWallet.Purpose.BIP44, Curve.Ed25519) val privateKey = hdWallet.privateKey(0) @@ -94,7 +94,7 @@ class TonKitManager( private fun createKitInstance( accountType: AccountType.TonAddress, - account: Account + account: Account, ): TonKitWrapper { val walletType = TonKit.WalletType.Watch(accountType.address) val kit = TonKit.getInstance(walletType, Network.MainNet, App.instance, account.id) @@ -137,24 +137,10 @@ class TonKitManager( class TonKitWrapper(val tonKit: TonKit) -fun TonKit.refresh() { -} - -private suspend fun TonKit.start() { - this.sync() -} - -private fun TonKit.stop() { -} - -val TonKit.network: Network - get() = Network.MainNet - -fun TonKit.statusInfo(): Map { - return buildMap { -// put("Balance Sync State", balanceState) -// put("Transaction Sync State", transactionsState) - } +fun TonKit.statusInfo() = buildMap { + put("Sync State", syncStateFlow.value) + put("Event Sync State", eventSyncStateFlow.value) + put("Jetton Sync State", jettonSyncStateFlow.value) } val Jetton.tokenType diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceAdapterRepository.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceAdapterRepository.kt index 4b61c6b9908..56469134dfc 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceAdapterRepository.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceAdapterRepository.kt @@ -116,7 +116,7 @@ class BalanceAdapterRepository( return null } - fun refresh() { + suspend fun refresh() { adapterManager.refresh() } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceService.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceService.kt index 24a1718863d..311d7bfe40d 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceService.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceService.kt @@ -178,7 +178,7 @@ class BalanceService( sortAndEmitItems() } - fun refresh() { + suspend fun refresh() { xRateRepository.refresh() adapterRepository.refresh() } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceViewModel.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceViewModel.kt index 28cf5bdcbb3..c11d19b657c 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceViewModel.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/balance/BalanceViewModel.kt @@ -182,7 +182,7 @@ class BalanceViewModel( stat(page = StatPage.Balance, event = StatEvent.Refresh) - viewModelScope.launch { + viewModelScope.launch(Dispatchers.Default) { isRefreshing = true emitState() diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoService.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoService.kt index e57575cd083..3599d3da65a 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoService.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoService.kt @@ -76,7 +76,37 @@ class TransactionInfoService( val coinUids = mutableListOf() val txCoinTypes = when (val tx = transactionRecord) { - is TonTransactionRecord -> listOf(tx.mainValue?.coinUid, tx.fee.coinUid) + is TonTransactionRecord -> buildList { + add(tx.mainValue?.coinUid) + add(tx.fee.coinUid) + + tx.actions.forEach { action -> + val actionType = action.type + when (actionType) { + is TonTransactionRecord.Action.Type.Burn -> { + add(actionType.value.coinUid) + } + is TonTransactionRecord.Action.Type.ContractCall -> { + add(actionType.value.coinUid) + } + is TonTransactionRecord.Action.Type.Mint -> { + add(actionType.value.coinUid) + } + is TonTransactionRecord.Action.Type.Receive -> { + add(actionType.value.coinUid) + } + is TonTransactionRecord.Action.Type.Send -> { + add(actionType.value.coinUid) + } + is TonTransactionRecord.Action.Type.Swap -> { + add(actionType.valueIn.coinUid) + add(actionType.valueOut.coinUid) + } + is TonTransactionRecord.Action.Type.ContractDeploy, + is TonTransactionRecord.Action.Type.Unsupported -> Unit + } + } + } is EvmIncomingTransactionRecord -> listOf(tx.value.coinUid) is EvmOutgoingTransactionRecord -> listOf(tx.fee?.coinUid, tx.value.coinUid) is SwapTransactionRecord -> listOf(tx.fee, tx.valueIn, tx.valueOut).map { it?.coinUid } diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoViewItemFactory.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoViewItemFactory.kt index 5c3b3976f0a..701b006ea08 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoViewItemFactory.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactionInfo/TransactionInfoViewItemFactory.kt @@ -69,7 +69,7 @@ class TransactionInfoViewItemFactory( private val evmLabelManager: EvmLabelManager, private val resendEnabled: Boolean, private val contactsRepo: ContactsRepository, - private val blockchainType: BlockchainType + private val blockchainType: BlockchainType, ) { private val zeroAddress = "0x0000000000000000000000000000000000000000" @@ -110,9 +110,15 @@ class TransactionInfoViewItemFactory( ) ) actionType.comment?.let { - itemsForAction.add(Value(getString(R.string.TransactionInfo_Memo), it)) + itemsForAction.add( + Value( + getString(R.string.TransactionInfo_Memo), + it + ) + ) } } + is TonTransactionRecord.Action.Type.Receive -> { itemsForAction.addAll( getReceiveSectionItems( @@ -123,34 +129,58 @@ class TransactionInfoViewItemFactory( ) ) actionType.comment?.let { - itemsForAction.add(Value(getString(R.string.TransactionInfo_Memo), it)) + itemsForAction.add( + Value( + getString(R.string.TransactionInfo_Memo), + it + ) + ) } } - is TonTransactionRecord.Action.Type.Unsupported -> { - itemsForAction.add(Value("Action", actionType.type)) + + is TonTransactionRecord.Action.Type.Burn -> { + itemsForAction.addAll( + getSendSectionItems( + value = actionType.value, + toAddress = null, + coinPrice = rates[actionType.value.coinUid], + hideAmount = transactionItem.hideAmount + ) + ) } -// case let .burn(value): -// viewItems = sendSection(source: record.source, transactionValue: value, to: zeroAddress, rates: item.rates, balanceHidden: balanceHidden) -// -// case let .mint(value): -// viewItems = receiveSection(source: record.source, transactionValue: value, from: zeroAddress, rates: item.rates, balanceHidden: balanceHidden) -// -// case let .swap(routerName, routerAddress, valueIn, valueOut): -// viewItems = [ -// amount(source: record.source, title: youPayString(status: status), subtitle: fullBadge(transactionValue: valueIn), transactionValue: valueIn, rate: _rate(valueIn), type: type(value: valueIn, .outgoing), balanceHidden: balanceHidden), -// amount(source: record.source, title: youGetString(status: status), subtitle: fullBadge(transactionValue: valueOut), transactionValue: valueOut, rate: _rate(valueOut), type: type(value: valueOut, .incoming), balanceHidden: balanceHidden), -// .service(value: routerName ?? routerAddress.shortened), -// ] -// -// if let priceString = priceString(valueIn: valueIn, valueOut: valueOut, coinPriceIn: _rate(valueIn)) { -// viewItems.append(.price(price: priceString)) -// } -// + + is TonTransactionRecord.Action.Type.Mint -> { + itemsForAction.addAll( + getReceiveSectionItems( + value = actionType.value, + fromAddress = zeroAddress, + coinPrice = rates[actionType.value.coinUid], + hideAmount = transactionItem.hideAmount, + ) + ) + } + + is TonTransactionRecord.Action.Type.Swap -> { + itemsForAction.addAll( + getSwapEventSectionItems( + valueIn = actionType.valueIn, + valueOut = actionType.valueOut, + rates = rates, + amount = null, + hideAmount = transactionItem.hideAmount, + hasRecipient = false + ) + ) + } + + is TonTransactionRecord.Action.Type.ContractDeploy -> { // case let .contractDeploy(interfaces): // viewItems = [ // .actionTitle(iconName: nil, iconDimmed: false, title: "transactions.contract_deploy".localized, subTitle: interfaces.joined(separator: ", ")), // ] -// + } + + is TonTransactionRecord.Action.Type.ContractCall -> { // case let .contractCall(address, value, operation): // viewItems = [ // .actionTitle(iconName: record.source.blockchainType.iconPlain32, iconDimmed: false, title: "transactions.contract_call".localized, subTitle: operation), @@ -158,10 +188,11 @@ class TransactionInfoViewItemFactory( // ] // // viewItems.append(contentsOf: sendSection(source: record.source, transactionValue: value, to: nil, rates: item.rates, balanceHidden: balanceHidden)) -// -// case let .unsupported(type): -// viewItems = [.fee(title: "Action", value: type)] -// } + } + + is TonTransactionRecord.Action.Type.Unsupported -> { + itemsForAction.add(Value("Action", actionType.type)) + } } if (action.status == TransactionStatus.Failed) { @@ -286,7 +317,13 @@ class TransactionInfoViewItemFactory( ) is ContractCallTransactionRecord -> { - itemSections.add(getContractMethodSectionItems(transaction.method, transaction.contractAddress, transaction.blockchainType)) + itemSections.add( + getContractMethodSectionItems( + transaction.method, + transaction.contractAddress, + transaction.blockchainType + ) + ) for (event in transaction.outgoingEvents) { itemSections.add( @@ -314,7 +351,13 @@ class TransactionInfoViewItemFactory( } is TronContractCallTransactionRecord -> { - itemSections.add(getContractMethodSectionItems(transaction.method, transaction.contractAddress, transaction.blockchainType)) + itemSections.add( + getContractMethodSectionItems( + transaction.method, + transaction.contractAddress, + transaction.blockchainType + ) + ) for (event in transaction.outgoingEvents) { itemSections.add( @@ -397,7 +440,8 @@ class TransactionInfoViewItemFactory( itemSections.add( listOf( Transaction( - transaction.transaction.contract?.label ?: getString(R.string.Transactions_ContractCall), + transaction.transaction.contract?.label + ?: getString(R.string.Transactions_ContractCall), "", TransactionViewItem.Icon.Platform(transaction.blockchainType).iconRes ) @@ -415,21 +459,33 @@ class TransactionInfoViewItemFactory( ) ) - miscItemsSection.addAll(getBitcoinSectionItems(transaction, transactionItem.lastBlockInfo)) + miscItemsSection.addAll( + getBitcoinSectionItems( + transaction, + transactionItem.lastBlockInfo + ) + ) addMemoItem(transaction.memo, miscItemsSection) } is BitcoinOutgoingTransactionRecord -> { sentToSelf = transaction.sentToSelf - itemSections.add(getSendSectionItems( - value = transaction.value, - toAddress = transaction.to, - coinPrice = rates[transaction.value.coinUid], - hideAmount = transactionItem.hideAmount, - sentToSelf = transaction.sentToSelf - )) - - miscItemsSection.addAll(getBitcoinSectionItems(transaction, transactionItem.lastBlockInfo)) + itemSections.add( + getSendSectionItems( + value = transaction.value, + toAddress = transaction.to, + coinPrice = rates[transaction.value.coinUid], + hideAmount = transactionItem.hideAmount, + sentToSelf = transaction.sentToSelf + ) + ) + + miscItemsSection.addAll( + getBitcoinSectionItems( + transaction, + transactionItem.lastBlockInfo + ) + ) addMemoItem(transaction.memo, miscItemsSection) } @@ -524,10 +580,24 @@ class TransactionInfoViewItemFactory( itemSections.add(getStatusSectionItems(transaction, status, rates)) if (transaction is EvmTransactionRecord && !transaction.foreignTransaction && status == TransactionStatus.Pending && resendEnabled) { - itemSections.add(listOf(SpeedUpCancel(transactionHash = transaction.transactionHash, blockchainType = transaction.blockchainType))) + itemSections.add( + listOf( + SpeedUpCancel( + transactionHash = transaction.transactionHash, + blockchainType = transaction.blockchainType + ) + ) + ) itemSections.add(listOf(TransactionInfoViewItem.Description(translator.getString(R.string.TransactionInfo_SpeedUpDescription)))) } else if (transaction is BitcoinOutgoingTransactionRecord && transaction.replaceable && resendEnabled) { - itemSections.add(listOf(SpeedUpCancel(transactionHash = transaction.transactionHash, blockchainType = transaction.blockchainType))) + itemSections.add( + listOf( + SpeedUpCancel( + transactionHash = transaction.transactionHash, + blockchainType = transaction.blockchainType + ) + ) + ) itemSections.add(listOf(TransactionInfoViewItem.Description(translator.getString(R.string.TransactionInfo_SpeedUpDescription)))) } itemSections.add(getExplorerSectionItems(transactionItem.explorerData)) @@ -536,12 +606,13 @@ class TransactionInfoViewItemFactory( } private fun getContact(address: String?): Contact? { - return contactsRepo.getContactsFiltered(blockchainType, addressQuery = address).firstOrNull() + return contactsRepo.getContactsFiltered(blockchainType, addressQuery = address) + .firstOrNull() } private fun addMemoItem( memo: String?, - miscItemsSection: MutableList + miscItemsSection: MutableList, ) { if (!memo.isNullOrBlank()) { miscItemsSection.add( @@ -555,10 +626,11 @@ class TransactionInfoViewItemFactory( fromAddress: String?, coinPrice: CurrencyValue?, hideAmount: Boolean, - nftMetadata: Map = mapOf() + nftMetadata: Map = mapOf(), ): List { val mint = fromAddress == zeroAddress - val title: String = if (mint) getString(R.string.Transactions_Mint) else getString(R.string.Transactions_Receive) + val title: String = + if (mint) getString(R.string.Transactions_Mint) else getString(R.string.Transactions_Receive) val amount: TransactionInfoViewItem val rate: TransactionInfoViewItem? @@ -582,7 +654,13 @@ class TransactionInfoViewItemFactory( if (!mint && fromAddress != null) { val contact = getContact(fromAddress) items.add( - Address(getString(R.string.TransactionInfo_From), fromAddress, contact == null, blockchainType, StatSection.AddressFrom) + Address( + getString(R.string.TransactionInfo_From), + fromAddress, + contact == null, + blockchainType, + StatSection.AddressFrom + ) ) contact?.let { items.add( @@ -602,23 +680,36 @@ class TransactionInfoViewItemFactory( coinPrice: CurrencyValue?, hideAmount: Boolean, sentToSelf: Boolean = false, - nftMetadata: Map = mapOf() + nftMetadata: Map = mapOf(), ): List { val burn = toAddress == zeroAddress - val title: String = if (burn) getString(R.string.Transactions_Burn) else getString(R.string.Transactions_Send) + val title: String = + if (burn) getString(R.string.Transactions_Burn) else getString(R.string.Transactions_Send) val amount: TransactionInfoViewItem val rate: TransactionInfoViewItem? when (value) { is TransactionValue.NftValue -> { - amount = getNftAmount(title, value, if (sentToSelf) null else false, hideAmount, nftMetadata[value.nftUid]) + amount = getNftAmount( + title, + value, + if (sentToSelf) null else false, + hideAmount, + nftMetadata[value.nftUid] + ) rate = null } else -> { - amount = getAmount(coinPrice, value, if (sentToSelf) null else false, hideAmount, AmountType.Sent) + amount = getAmount( + coinPrice, + value, + if (sentToSelf) null else false, + hideAmount, + AmountType.Sent + ) rate = getHistoricalRate(coinPrice, value) } } @@ -628,7 +719,13 @@ class TransactionInfoViewItemFactory( if (!burn && toAddress != null) { val contact = getContact(toAddress) items.add( - Address(getString(R.string.TransactionInfo_To), toAddress, contact == null, blockchainType, StatSection.AddressTo) + Address( + getString(R.string.TransactionInfo_To), + toAddress, + contact == null, + blockchainType, + StatSection.AddressTo + ) ) contact?.let { @@ -647,7 +744,7 @@ class TransactionInfoViewItemFactory( rates: Map, amount: SwapTransactionRecord.Amount?, hideAmount: Boolean, - hasRecipient: Boolean + hasRecipient: Boolean, ) = buildList { valueIn?.let { add( @@ -679,7 +776,7 @@ class TransactionInfoViewItemFactory( rates: Map, exchangeAddress: String, valueOut: TransactionValue?, - valueIn: TransactionValue? + valueIn: TransactionValue?, ): List { val items: MutableList = mutableListOf( Value( @@ -808,7 +905,13 @@ class TransactionInfoViewItemFactory( value.badge, AmountType.Approved ), - Address(getString(R.string.TransactionInfo_Spender), spenderAddress, contact == null, blockchainType, StatSection.AddressSpender) + Address( + getString(R.string.TransactionInfo_Spender), + spenderAddress, + contact == null, + blockchainType, + StatSection.AddressSpender + ) ) contact?.let { @@ -821,7 +924,7 @@ class TransactionInfoViewItemFactory( private fun getContractMethodSectionItems( method: String?, contractAddress: String, - blockchainType: BlockchainType + blockchainType: BlockchainType, ) = listOf( Transaction( method ?: getString(R.string.Transactions_ContractCall), @@ -830,7 +933,10 @@ class TransactionInfoViewItemFactory( ) ) - private fun getBitcoinSectionItems(transaction: BitcoinTransactionRecord, lastBlockInfo: LastBlockInfo?): List { + private fun getBitcoinSectionItems( + transaction: BitcoinTransactionRecord, + lastBlockInfo: LastBlockInfo?, + ): List { val items: MutableList = mutableListOf() transaction.conflictingHash?.let { conflictingHash -> @@ -857,10 +963,13 @@ class TransactionInfoViewItemFactory( private fun getStatusSectionItems( transaction: TransactionRecord, status: TransactionStatus, - rates: Map + rates: Map, ): List { val items: MutableList = mutableListOf( - Value(getString(R.string.TransactionInfo_Date), dateHelper.getFullDate(Date(transaction.timestamp * 1000))), + Value( + getString(R.string.TransactionInfo_Date), + dateHelper.getFullDate(Date(transaction.timestamp * 1000)) + ), Status(status) ) @@ -929,12 +1038,16 @@ class TransactionInfoViewItemFactory( private fun getExplorerSectionItems(explorerData: TransactionInfoModule.ExplorerData): List = listOf( Explorer( - translator.getString(R.string.TransactionInfo_ButtonViewOnExplorerName, explorerData.title), + translator.getString( + R.string.TransactionInfo_ButtonViewOnExplorerName, + explorerData.title + ), explorerData.url ) ) - private fun getDoubleSpendViewItem(transactionHash: String, conflictingHash: String) = DoubleSpend(transactionHash, conflictingHash) + private fun getDoubleSpendViewItem(transactionHash: String, conflictingHash: String) = + DoubleSpend(transactionHash, conflictingHash) private fun getLockStateItem(lockState: TransactionLockState?): TransactionInfoViewItem? { return lockState?.let { @@ -978,20 +1091,23 @@ class TransactionInfoViewItemFactory( } } ?: "---" val fiatValueColored = ColoredValue(valueInFiat, ColorName.Grey) - val coinValueFormatted = if (hideAmount) "*****" else value.decimalValue?.let { decimalValue -> - val sign = when (incoming) { - true -> "+" - false -> "-" - else -> "" - } - val valueWithCoinCode = numberFormatter.formatCoinFull(decimalValue.abs(), value.coinCode, 8) - if (amount is SwapTransactionRecord.Amount.Extremum && incoming != null) { - val suffix = if (incoming) getString(R.string.Swap_AmountMin) else getString(R.string.Swap_AmountMax) - "$sign$valueWithCoinCode $suffix" - } else { - "$sign$valueWithCoinCode" - } - } ?: "---" + val coinValueFormatted = + if (hideAmount) "*****" else value.decimalValue?.let { decimalValue -> + val sign = when (incoming) { + true -> "+" + false -> "-" + else -> "" + } + val valueWithCoinCode = + numberFormatter.formatCoinFull(decimalValue.abs(), value.coinCode, 8) + if (amount is SwapTransactionRecord.Amount.Extremum && incoming != null) { + val suffix = + if (incoming) getString(R.string.Swap_AmountMin) else getString(R.string.Swap_AmountMax) + "$sign$valueWithCoinCode $suffix" + } else { + "$sign$valueWithCoinCode" + } + } ?: "---" val color = if (hasRecipient && incoming == true) { ColorName.Lucian @@ -1022,7 +1138,7 @@ class TransactionInfoViewItemFactory( value: TransactionValue.NftValue, incoming: Boolean?, hideAmount: Boolean, - nftMetadata: NftAssetBriefMetadata? + nftMetadata: NftAssetBriefMetadata?, ): TransactionInfoViewItem { val valueFormatted = if (hideAmount) "*****" else value.decimalValue.let { decimalValue -> val sign = when { @@ -1031,7 +1147,8 @@ class TransactionInfoViewItemFactory( decimalValue > BigDecimal.ZERO -> "+" else -> "" } - val valueWithCoinCode = numberFormatter.formatCoinFull(decimalValue.abs(), value.coinCode, 8) + val valueWithCoinCode = + numberFormatter.formatCoinFull(decimalValue.abs(), value.coinCode, 8) "$sign$valueWithCoinCode" } @@ -1069,7 +1186,10 @@ class TransactionInfoViewItemFactory( return Value(getString(R.string.TransactionInfo_HistoricalRate), rateValue) } - private fun getFee(transactionValue: TransactionValue, rate: CurrencyValue?): TransactionInfoViewItem { + private fun getFee( + transactionValue: TransactionValue, + rate: CurrencyValue?, + ): TransactionInfoViewItem { val feeAmountString = getFeeAmountString(rate, transactionValue) return Value(getString(R.string.TransactionInfo_Fee), feeAmountString) @@ -1078,20 +1198,24 @@ class TransactionInfoViewItemFactory( private fun getFeeItem( transactionValue: TransactionValue, rate: CurrencyValue?, - status: TransactionStatus + status: TransactionStatus, ): TransactionInfoViewItem { val feeAmountString = getFeeAmountString(rate, transactionValue) val feeTitle: String = when (status) { TransactionStatus.Pending -> getString(R.string.TransactionInfo_FeeEstimated) is TransactionStatus.Processing, TransactionStatus.Failed, - TransactionStatus.Completed -> getString(R.string.TransactionInfo_Fee) + TransactionStatus.Completed, + -> getString(R.string.TransactionInfo_Fee) } return Value(feeTitle, feeAmountString) } - private fun getFeeAmountString(rate: CurrencyValue?, transactionValue: TransactionValue): String { + private fun getFeeAmountString( + rate: CurrencyValue?, + transactionValue: TransactionValue, + ): String { val feeInFiat = rate?.let { transactionValue.decimalValue?.let { decimalValue -> numberFormatter.formatFiatFull( diff --git a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionViewItemFactory.kt b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionViewItemFactory.kt index 2cdbb0b52fc..6e895378044 100644 --- a/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionViewItemFactory.kt +++ b/app/src/main/java/io/horizontalsystems/bankwallet/modules/transactions/TransactionViewItemFactory.kt @@ -6,6 +6,7 @@ import io.horizontalsystems.bankwallet.core.adapters.TonTransactionRecord import io.horizontalsystems.bankwallet.core.managers.BalanceHiddenManager import io.horizontalsystems.bankwallet.core.managers.EvmLabelManager import io.horizontalsystems.bankwallet.core.providers.Translator +import io.horizontalsystems.bankwallet.core.shorten import io.horizontalsystems.bankwallet.entities.CurrencyValue import io.horizontalsystems.bankwallet.entities.TransactionValue import io.horizontalsystems.bankwallet.entities.nft.NftAssetBriefMetadata @@ -116,14 +117,13 @@ class TransactionViewItemFactory( is TransactionValue.CoinValue, is TransactionValue.RawValue, + is TransactionValue.JettonValue, is TransactionValue.TokenValue -> { frontRectangle = false frontUrl = primaryValue.coinIconUrl frontAlternativeUrl = primaryValue.alternativeCoinIconUrl frontPlaceHolder = primaryValue.coinIconPlaceholder } - - is TransactionValue.JettonValue -> TODO() } } else { frontRectangle = false @@ -474,10 +474,6 @@ class TransactionViewItemFactory( sentToSelf = actionType.sentToSelf iconX = singleValueIconType(actionType.value) - -// if let currencyValue = item.currencyValue { -// secondaryValue = BaseTransactionsViewModel.Value(text: currencyString(from: currencyValue), type: .secondary) -// } } is TonTransactionRecord.Action.Type.Receive -> { title = Translator.getString(R.string.Transactions_Receive) @@ -488,10 +484,6 @@ class TransactionViewItemFactory( primaryValue = getColoredValue(actionType.value, ColorName.Remus) iconX = singleValueIconType(actionType.value) - -// if let currencyValue = item.currencyValue { -// secondaryValue = BaseTransactionsViewModel.Value(text: currencyString(from: currencyValue), type: .secondary) -// } } is TonTransactionRecord.Action.Type.Unsupported -> { title = Translator.getString(R.string.Transactions_TonTransaction) @@ -501,51 +493,39 @@ class TransactionViewItemFactory( iconX = TransactionViewItem.Icon.Platform(record.blockchainType) - + } + is TonTransactionRecord.Action.Type.Burn -> { + iconX = singleValueIconType(actionType.value) + title = Translator.getString(R.string.Transactions_Burn) + subtitle = actionType.value.fullName + primaryValue = getColoredValue(actionType.value, ColorName.Lucian) + } + is TonTransactionRecord.Action.Type.ContractCall -> { + iconX = TransactionViewItem.Icon.Platform(record.blockchainType) + title = Translator.getString(R.string.Transactions_ContractCall) + subtitle = actionType.address.shorten() + primaryValue = getColoredValue(actionType.value, ColorName.Lucian) + } + is TonTransactionRecord.Action.Type.ContractDeploy -> { + iconX = TransactionViewItem.Icon.Platform(record.blockchainType) + title = Translator.getString(R.string.Transactions_ContractDeploy) + subtitle = actionType.interfaces.joinToString() + primaryValue = null + } + is TonTransactionRecord.Action.Type.Mint -> { + iconX = singleValueIconType(actionType.value) + title = Translator.getString(R.string.Transactions_Mint) + subtitle = actionType.value.fullName + primaryValue = getColoredValue(actionType.value, ColorName.Remus) + } + is TonTransactionRecord.Action.Type.Swap -> { + iconX = doubleValueIconType(actionType.valueOut, actionType.valueIn) + title = Translator.getString(R.string.Transactions_Swap) + subtitle = actionType.routerName ?: actionType.routerAddress.shorten() + primaryValue = getColoredValue(actionType.valueOut, ColorName.Remus) + secondaryValue = getColoredValue(actionType.valueIn, ColorName.Lucian) } } -// switch action.type { -// case let .send(value, to, _sentToSelf, _): -// case let .receive(value, from, _): -// case let .burn(value): -// iconType = singleValueIconType(source: record.source, value: value) -// title = "transactions.burn".localized -// subTitle = value.fullName -// primaryValue = BaseTransactionsViewModel.Value(text: coinString(from: value), type: type(value: value, .outgoing)) -// -// if let currencyValue = item.currencyValue { -// secondaryValue = BaseTransactionsViewModel.Value(text: currencyString(from: currencyValue), type: .secondary) -// } -// case let .mint(value): -// iconType = singleValueIconType(source: record.source, value: value) -// title = "transactions.mint".localized -// subTitle = value.fullName -// primaryValue = BaseTransactionsViewModel.Value(text: coinString(from: value), type: type(value: value, .incoming)) -// -// if let currencyValue = item.currencyValue { -// secondaryValue = BaseTransactionsViewModel.Value(text: currencyString(from: currencyValue), type: .secondary) -// } -// case let .swap(routerName, routerAddress, valueIn, valueOut): -// iconType = doubleValueIconType(source: record.source, primaryValue: valueOut, secondaryValue: valueIn) -// title = "transactions.swap".localized -// subTitle = routerName ?? routerAddress.shortened -// primaryValue = BaseTransactionsViewModel.Value(text: coinString(from: valueOut), type: type(value: valueOut, .incoming)) -// secondaryValue = BaseTransactionsViewModel.Value(text: coinString(from: valueIn), type: type(value: valueIn, .outgoing)) -// case let .contractDeploy(interfaces): -// iconType = .localIcon(imageName: item.record.source.blockchainType.iconPlain32) -// title = "transactions.contract_deploy".localized -// subTitle = interfaces.joined(separator: ", ") -// case let .contractCall(address, value, _): -// iconType = .localIcon(imageName: item.record.source.blockchainType.iconPlain32) -// title = "transactions.contract_call".localized -// subTitle = address.shortened -// primaryValue = BaseTransactionsViewModel.Value(text: coinString(from: value), type: type(value: value, .outgoing)) -// -// if let currencyValue = item.currencyValue { -// secondaryValue = BaseTransactionsViewModel.Value(text: currencyString(from: currencyValue), type: .secondary) -// } -// case let .unsupported(type): -// } } else { iconX = TransactionViewItem.Icon.Platform(record.blockchainType) title = Translator.getString(R.string.Transactions_TonTransaction) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db809a52892..e8eb8169b3b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -829,6 +829,7 @@ Contract Call External Call Contract Creation + Contract Deploy to %s from %s unlimited %s