Skip to content

Commit

Permalink
bug fixeds
Browse files Browse the repository at this point in the history
  • Loading branch information
polstianka committed Oct 9, 2024
1 parent c8fea66 commit 57d7d0e
Show file tree
Hide file tree
Showing 25 changed files with 275 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ class DAppsRepository(
return result
}

suspend fun getConnections(): List<AppConnectEntity> {
return database.getConnections()
}

fun getLastAppRequestId(clientId: String): Long {
return database.getLastAppRequestId(clientId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ sealed class DeepLinkRoute {
address = uri.pathOrNull ?: throw IllegalArgumentException("Address is required"),
amount = uri.queryPositiveLong("amount"),
text = uri.query("text"),
jettonAddress = uri.query("jettonAddress"),
jettonAddress = uri.query("jettonAddress") ?: uri.query("jetton"),
bin = uri.query("bin")
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ fun RawMessageEntity.getWalletTransfer(
payload
}
// builder.bounceable = address.isBounceable()
builder.coins = coins
if (newCustomPayload != null) {
val defCoins = Coins.of(0.5)
if (defCoins.amount.value > coins.amount.value) {
builder.coins = defCoins
} else {
builder.coins = coins
}
} else {
builder.coins = coins
}
return builder.build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.tonapps.blockchain.ton.proof.TONProof
import com.tonapps.extensions.appVersionName
import com.tonapps.extensions.filterList
import com.tonapps.extensions.flat
import com.tonapps.extensions.flatter
import com.tonapps.extensions.hasQuery
import com.tonapps.extensions.mapList
import com.tonapps.network.simple
Expand All @@ -19,6 +20,7 @@ import com.tonapps.tonkeeper.manager.push.PushManager
import com.tonapps.tonkeeper.manager.tonconnect.bridge.Bridge
import com.tonapps.tonkeeper.manager.tonconnect.bridge.JsonBuilder
import com.tonapps.tonkeeper.manager.tonconnect.bridge.model.BridgeError
import com.tonapps.tonkeeper.manager.tonconnect.bridge.model.BridgeEvent
import com.tonapps.tonkeeper.manager.tonconnect.bridge.model.BridgeMethod
import com.tonapps.tonkeeper.manager.tonconnect.exceptions.ManifestException
import com.tonapps.tonkeeper.ui.screen.tonconnect.TonConnectScreen
Expand All @@ -31,7 +33,10 @@ import com.tonapps.wallet.data.dapps.entities.AppEntity
import com.tonapps.wallet.localization.Localization
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
Expand All @@ -43,6 +48,7 @@ import uikit.extensions.activity
import uikit.extensions.addForResult
import uikit.navigation.NavigationActivity
import java.util.concurrent.CancellationException
import java.util.concurrent.atomic.AtomicBoolean

class TonConnectManager(
private val scope: CoroutineScope,
Expand All @@ -52,18 +58,17 @@ class TonConnectManager(
) {

private val bridge: Bridge = Bridge(api)
private val bridgeConnected = AtomicBoolean(false)
private var bridgeJob: Job? = null

private val eventsFlow = dAppsRepository.connectionsFlow
.map { it.chunked(10) }
.flat { chunks ->
chunks.map { bridge.eventsFlow(it, dAppsRepository.lastEventId) }
}.mapNotNull { event ->
val lastAppRequestId = dAppsRepository.getLastAppRequestId(event.connection.clientId)
if (lastAppRequestId >= event.message.id) {
return@mapNotNull null
}
event
}.shareIn(scope, SharingStarted.Eagerly, 1)
private val _eventsFlow = MutableSharedFlow<BridgeEvent>(replay = 1)
private val eventsFlow = _eventsFlow.asSharedFlow().mapNotNull { event ->
val lastAppRequestId = dAppsRepository.getLastAppRequestId(event.connection.clientId)
if (lastAppRequestId >= event.message.id) {
return@mapNotNull null
}
event
}.shareIn(scope, SharingStarted.Eagerly, 1)

val transactionRequestFlow = eventsFlow.mapNotNull { event ->
if (event.method == BridgeMethod.SEND_TRANSACTION) {
Expand All @@ -78,6 +83,42 @@ class TonConnectManager(
}
}.flowOn(Dispatchers.IO).shareIn(scope, SharingStarted.Eagerly, 0)

fun connectBridge() {
if (bridgeConnected.get()) {
return
}
bridgeJob?.cancel()
bridgeConnected.set(true)

bridgeJob = scope.launch(Dispatchers.IO) {
val connections = dAppsRepository.getConnections().chunked(50)
if (connections.isEmpty()) {
return@launch
}
val flow = connections.map { bridge.eventsFlow(it, dAppsRepository.lastEventId) }.flatter()
flow.collect {
if (bridgeConnected.get()) {
_eventsFlow.emit(it)
}
}
}
}

fun disconnectBridge() {
if (!bridgeConnected.get()) {
return
}
bridgeJob?.cancel()
bridgeConnected.set(false)
}

private fun reconnectBridge() {
if (bridgeConnected.get()) {
disconnectBridge()
connectBridge()
}
}

fun walletConnectionsFlow(wallet: WalletEntity) = accountConnectionsFlow(wallet.accountId, wallet.testnet)

fun accountConnectionsFlow(accountId: String, testnet: Boolean = false) = dAppsRepository.connectionsFlow.filterList { connection ->
Expand Down Expand Up @@ -231,6 +272,8 @@ class TonConnectManager(
)

activity.runOnUiThread {
reconnectBridge()

DAppPushToggleWorker.run(
context = activity,
wallet = response.wallet,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ class BatteryRechargeScreen(wallet: WalletEntity): BaseListWalletScreen<ScreenCo
private fun onSuccess() {
requireContext().showToast(Localization.battery_please_wait)
navigation?.openURL("tonkeeper://activity")
navigation?.removeByClass(BatteryScreen::class.java)
finish()
navigation?.removeByClass({
finish()
}, BatteryScreen::class.java)
}

private fun sign(request: SignRequestEntity, forceRelayer: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ class RootActivity: BaseWalletActivity() {
App.applyConfiguration(resources.configuration)
}

override fun onResume() {
super.onResume()
viewModel.connectTonConnectBridge()
}

override fun onPause() {
super.onPause()
viewModel.disconnectTonConnectBridge()
}

private fun pinState(state: LockScreen.State) {
if (state == LockScreen.State.None) {
lockView.visibility = View.GONE
Expand Down Expand Up @@ -189,14 +199,15 @@ class RootActivity: BaseWalletActivity() {
text = event.text,
wallet = event.wallet
)
is RootEvent.CloseCurrentTonConnect -> {
removeByClass(SendTransactionScreen::class.java)
removeByClass(TonConnectScreen::class.java)
}
is RootEvent.CloseCurrentTonConnect -> closeCurrentTonConnect {}
else -> { }
}
}

private fun closeCurrentTonConnect(runnable: Runnable) {
removeByClass(runnable, SendTransactionScreen::class.java, TonConnectScreen::class.java)
}

private fun openSend(
wallet: WalletEntity,
targetAddress: String? = null,
Expand Down Expand Up @@ -273,10 +284,12 @@ class RootActivity: BaseWalletActivity() {

override fun add(fragment: BaseFragment) {
if (fragment is SendTransactionScreen || fragment is TonConnectScreen) {
removeByClass(SendTransactionScreen::class.java)
removeByClass(TonConnectScreen::class.java)
closeCurrentTonConnect {
super.add(fragment)
}
} else {
super.add(fragment)
}
super.add(fragment)
}

override fun openURL(url: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.tonapps.tonkeeper.ui.screen.root

import android.net.Uri
import com.tonapps.tonkeeper.manager.tonconnect.bridge.model.BridgeEvent
import com.tonapps.wallet.data.dapps.entities.AppConnectEntity

data class RootSignTransaction(
val connection: AppConnectEntity,
val message: BridgeEvent.Message,
val returnUri: Uri?
) {

val hash: String
get() = "${connection.clientId}_${message.id}"

val id: Long
get() = message.id

val params: List<String>
get() = message.params
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import com.tonapps.wallet.data.purchase.PurchaseRepository
import com.tonapps.wallet.data.settings.SettingsRepository
import com.tonapps.wallet.localization.Localization
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.combine
Expand All @@ -83,6 +84,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.time.Duration.Companion.seconds

class RootViewModel(
app: Application,
Expand All @@ -108,8 +110,20 @@ class RootViewModel(
private val _eventFlow = MutableEffectFlow<RootEvent?>()
val eventFlow = _eventFlow.asSharedFlow().filterNotNull()

private val ignoreTonConnectTransaction = mutableListOf<String>()

init {
tonConnectManager.transactionRequestFlow.collectFlow(::sendTransaction)
tonConnectManager.transactionRequestFlow.map { (connection, message) ->
val tx = RootSignTransaction(connection, message, savedState.returnUri)
savedState.returnUri = null
tx
}.filter { !ignoreTonConnectTransaction.contains(it.hash) }.collectFlow {
_eventFlow.tryEmit(RootEvent.CloseCurrentTonConnect)
viewModelScope.launch {
ignoreTonConnectTransaction.add(it.hash)
signTransaction(it)
}
}

settingsRepository.languageFlow.collectFlow {
context.setLocales(settingsRepository.localeList)
Expand Down Expand Up @@ -150,28 +164,32 @@ class RootViewModel(
}.flowOn(Dispatchers.IO).launchIn(viewModelScope)
}

private suspend fun sendTransaction(pair: Pair<AppConnectEntity, BridgeEvent.Message>) {
_eventFlow.tryEmit(RootEvent.CloseCurrentTonConnect)
fun connectTonConnectBridge() {
tonConnectManager.connectBridge()
}

fun disconnectTonConnectBridge() {
tonConnectManager.disconnectBridge()
}

val (connection, message) = pair
val eventId = message.id
private suspend fun signTransaction(tx: RootSignTransaction) {
val eventId = tx.id
try {
val signRequests = message.params.map { SignRequestEntity(it) }
val signRequests = tx.params.map { SignRequestEntity(it) }
if (signRequests.isEmpty()) {
throw IllegalArgumentException("Empty sign requests")
}
for (signRequest in signRequests) {
signRequest(eventId, connection, signRequest)
signRequest(eventId, tx.connection, signRequest)
}
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
tonConnectManager.sendBridgeError(connection, BridgeError.BAD_REQUEST, eventId)
tonConnectManager.sendBridgeError(tx.connection, BridgeError.BAD_REQUEST, eventId)
}

savedState.returnUri?.let {
tx.returnUri?.let {
context.safeExternalOpenUri(it)
}
savedState.returnUri = null
}

private suspend fun signRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,9 @@ class SendScreen(wallet: WalletEntity) : WalletContextScreen(R.layout.fragment_s
private fun setSuccess() {
processTaskView.state = ProcessTaskView.State.SUCCESS
navigation?.openURL("tonkeeper://activity")
navigation?.removeByClass(TokenScreen::class.java)
postDelayed(2000, ::finish)
navigation?.removeByClass({
postDelayed(2000, ::finish)
}, TokenScreen::class.java)
}

private fun setDefault() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,12 @@ class SendViewModel(
onContinue()
}
}
} else if (isNft) {
if (!withRelayer && fee.value > tonBalance.value) {
showInsufficientBalance(tonBalance, fee)
} else {
onContinue()
}
} else {
val totalAmount = fee + TransferEntity.BASE_FORWARD_AMOUNT
if (!withRelayer && totalAmount.value > tonBalance.value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.tonapps.tonkeeper.extensions.getTitle
import com.tonapps.tonkeeper.koin.walletViewModel
import com.tonapps.tonkeeper.manager.tonconnect.bridge.model.BridgeError
import com.tonapps.tonkeeper.ui.base.WalletContextScreen
import com.tonapps.tonkeeper.ui.screen.send.InsufficientFundsDialog
import com.tonapps.tonkeeperx.R
import com.tonapps.uikit.color.accentOrangeColor
import com.tonapps.uikit.color.textSecondaryColor
Expand Down Expand Up @@ -50,6 +51,10 @@ class SendTransactionScreen(wallet: WalletEntity) : WalletContextScreen(R.layout

private val args: SendTransactionArgs by lazy { SendTransactionArgs(requireArguments()) }

private val insufficientFundsDialog: InsufficientFundsDialog by lazy {
InsufficientFundsDialog(requireContext())
}

override val viewModel: SendTransactionViewModel by walletViewModel {
parametersOf(args.request, args.batteryTransactionType, args.forceRelayer)
}
Expand Down Expand Up @@ -166,10 +171,15 @@ class SendTransactionScreen(wallet: WalletEntity) : WalletContextScreen(R.layout
}

private fun applyState(state: SendTransactionState) {
if (state is SendTransactionState.Details) {
applyDetails(state)
} else if (state is SendTransactionState.Failed) {
setErrorTask(BridgeError.UNKNOWN)
when (state) {
is SendTransactionState.Details -> applyDetails(state)
is SendTransactionState.Failed -> setErrorTask(BridgeError.UNKNOWN)
is SendTransactionState.FailedEmulation -> finish()
is SendTransactionState.InsufficientBalance -> {
insufficientFundsDialog.show(state.wallet, state.balance, state.required, state.withRechargeBattery, state.singleWallet)
finish()
}
else -> { }
}
}

Expand Down
Loading

0 comments on commit 57d7d0e

Please sign in to comment.