Skip to content

Commit

Permalink
tonconnect bug fixeds
Browse files Browse the repository at this point in the history
  • Loading branch information
polstianka committed Oct 9, 2024
1 parent f89f2ea commit ec0c03f
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.tonapps.wallet.data.core.entity
import android.os.Parcelable
import android.util.Log
import com.tonapps.blockchain.ton.TonNetwork
import com.tonapps.blockchain.ton.extensions.isValidTonAddress
import com.tonapps.blockchain.ton.extensions.toAccountId
import kotlinx.datetime.Clock
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
Expand All @@ -13,18 +15,27 @@ import kotlin.time.Duration.Companion.seconds

@Parcelize
data class SignRequestEntity(
val fromValue: String?,
private val fromValue: String?,
private val sourceValue: String?,
val validUntil: Long,
val messages: List<RawMessageEntity>,
val network: TonNetwork
): Parcelable {

@IgnoredOnParcel
val from: AddrStd?
get() = fromValue?.let { AddrStd.parse(it) }
get() {
val value = fromValue ?: return null
return try {
AddrStd.parse(value)
} catch (e: Throwable) {
null
}
}

constructor(json: JSONObject) : this(
fromValue = parseFrom(json),
fromValue = json.optString("from"),
sourceValue = json.optString("source"),
validUntil = parseValidUnit(json),
messages = parseMessages(json.getJSONArray("messages")),
network = parseNetwork(json.opt("network"))
Expand All @@ -34,6 +45,31 @@ data class SignRequestEntity(

constructor(value: Any) : this(value.toString())

class Builder {
private var from: AddrStd? = null
private var validUntil: Long? = null
private var network: TonNetwork = TonNetwork.MAINNET
private val messages = mutableListOf<RawMessageEntity>()

fun setFrom(from: AddrStd) = apply { this.from = from }

fun setValidUntil(validUntil: Long) = apply { this.validUntil = validUntil }

fun setNetwork(network: TonNetwork) = apply { this.network = network }

fun addMessage(message: RawMessageEntity) = apply { messages.add(message) }

fun build(): SignRequestEntity {
return SignRequestEntity(
fromValue = from?.toAccountId(),
sourceValue = null,
validUntil = validUntil ?: 0,
messages = messages.toList(),
network = network
)
}
}

companion object {

fun parse(array: JSONArray): List<SignRequestEntity> {
Expand All @@ -59,21 +95,18 @@ data class SignRequestEntity(
val messages = mutableListOf<RawMessageEntity>()
for (i in 0 until array.length()) {
val json = array.getJSONObject(i)
messages.add(RawMessageEntity(json))
val raw = RawMessageEntity(json)
if (0 >= raw.amount) {
throw IllegalArgumentException("Invalid amount: ${raw.amount}")
}
if (!raw.addressValue.isValidTonAddress()) {
throw IllegalArgumentException("Invalid address: ${raw.addressValue}")
}
messages.add(raw)
}
return messages
}

private fun parseFrom(json: JSONObject): String? {
return if (json.has("from")) {
json.getString("from")
} else if (json.has("source")) {
json.getString("source")
} else {
null
}
}

private fun parseNetwork(value: Any?): TonNetwork {
if (value == null) {
return TonNetwork.MAINNET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.tonapps.tonkeeper.manager.tonconnect
import android.content.Context
import android.net.Uri
import android.util.ArrayMap
import android.util.Log
import androidx.core.net.toUri
import com.tonapps.blockchain.ton.extensions.equalsAddress
import com.tonapps.blockchain.ton.proof.TONProof
Expand Down Expand Up @@ -61,9 +62,8 @@ class TonConnectManager(
if (lastAppRequestId >= event.message.id) {
return@mapNotNull null
}
dAppsRepository.setLastAppRequestId(event.connection.clientId, event.message.id)
event
}.shareIn(scope, SharingStarted.Eagerly)
}.shareIn(scope, SharingStarted.Eagerly, 1)

val transactionRequestFlow = eventsFlow.mapNotNull { event ->
if (event.method == BridgeMethod.SEND_TRANSACTION) {
Expand All @@ -76,14 +76,18 @@ class TonConnectManager(
}
null
}
}.flowOn(Dispatchers.IO).shareIn(scope, SharingStarted.Eagerly)
}.flowOn(Dispatchers.IO).shareIn(scope, SharingStarted.Eagerly, 1)

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

fun accountConnectionsFlow(accountId: String, testnet: Boolean = false) = dAppsRepository.connectionsFlow.filterList { connection ->
connection.testnet == testnet && connection.accountId.equalsAddress(accountId)
}

fun setLastAppRequestId(clientId: String, messageId: Long) {
dAppsRepository.setLastAppRequestId(clientId, messageId)
}

fun walletAppsFlow(wallet: WalletEntity) = walletConnectionsFlow(wallet).mapList { it.appUrl }.map { it.distinct() }.map { urls ->
dAppsRepository.getApps(urls)
}.flowOn(Dispatchers.IO)
Expand Down Expand Up @@ -119,10 +123,12 @@ class TonConnectManager(

suspend fun sendBridgeError(connection: AppConnectEntity, error: BridgeError, id: Long) {
bridge.sendError(connection, error, id)
setLastAppRequestId(connection.clientId, id)
}

suspend fun sendTransactionResponseSuccess(connection: AppConnectEntity, boc: String, id: Long) {
bridge.sendTransactionResponseSuccess(connection, boc, id)
setLastAppRequestId(connection.clientId, id)
}

fun isPushEnabled(wallet: WalletEntity, appUrl: Uri): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,6 @@ internal class Bridge(private val api: API) {
return message
}

suspend fun sendConnectError(
connection: AppConnectEntity,
error: BridgeError
): String {
val message = JsonBuilder.connectEventError(error).toString()
send(connection, message)
return message
}

suspend fun sendConnectSuccess(
connection: AppConnectEntity,
wallet: WalletEntity,
proof: TONProof.Result?,
proofError: BridgeError?,
appVersion: String,
): String {
val message = JsonBuilder.connectEventSuccess(wallet, proof, proofError, appVersion).toString()
send(connection, message)
return message
}

suspend fun sendDisconnect(connection: AppConnectEntity): String {
val message = JsonBuilder.disconnectEvent().toString()
send(connection, message)
Expand All @@ -78,24 +57,26 @@ internal class Bridge(private val api: API) {
suspend fun send(
connection: AppConnectEntity,
message: String
) = withContext(Dispatchers.IO) {
): Boolean = withContext(Dispatchers.IO) {
if (connection.type != AppConnectEntity.Type.Internal) {
// val encrypted = connection.encryptMessage(message.toByteArray())
// api.tonconnectSend(connection.publicKeyHex, connection.clientId, encrypted.base64)
send(connection.clientId, connection.keyPair, message)
} else {
true
}
}

suspend fun send(
clientId: String,
keyPair: CryptoBox.KeyPair,
unencryptedMessage: String
) = withContext(Dispatchers.IO) {
): Boolean = withContext(Dispatchers.IO) {
try {
val encryptedMessage = AppConnectEntity.encryptMessage(clientId.hex(), keyPair.privateKey, unencryptedMessage.toByteArray())
api.tonconnectSend(hex(keyPair.publicKey), clientId, encryptedMessage.base64)
true
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
false
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,19 +334,18 @@ class BatteryRechargeViewModel(
}

if (token.isTon) {
val request = SignRequestEntity(
fromValue = wallet.contract.address.toAccountId(),
validUntil = validUntil,
messages = listOf(
RawMessageEntity(
addressValue = fundReceiver,
amount = amount.toLong(),
stateInitValue = null,
payloadValue = payload.base64()
)
),
network = network,
)
val request = SignRequestEntity.Builder()
.setFrom(wallet.contract.address)
.setValidUntil(validUntil)
.addMessage(RawMessageEntity(
addressValue = fundReceiver,
amount = amount.toLong(),
stateInitValue = null,
payloadValue = payload.base64()
))
.setNetwork(network)
.build()

_eventFlow.tryEmit(BatteryRechargeEvent.Sign(request, forceRelayer))
} else {
val queryId = TransferEntity.newWalletQueryId()
Expand All @@ -364,19 +363,19 @@ class BatteryRechargeViewModel(
forwardPayload = payload,
customPayload = customPayload?.customPayload
)
val request = SignRequestEntity(
fromValue = wallet.contract.address.toAccountId(),
validUntil = validUntil,
messages = listOf(
RawMessageEntity(
addressValue = token.balance.walletAddress,
amount = Coins.of(0.1).toLong(),
stateInitValue = null,
payloadValue = jettonPayload.base64()
)
),
network = network,
)

val request = SignRequestEntity.Builder()
.setFrom(wallet.contract.address)
.setValidUntil(validUntil)
.addMessage(RawMessageEntity(
addressValue = token.balance.walletAddress,
amount = Coins.of(0.1).toLong(),
stateInitValue = null,
payloadValue = jettonPayload.base64()
))
.setNetwork(network)
.build()

_eventFlow.tryEmit(BatteryRechargeEvent.Sign(request, forceRelayer))
}
}.catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ class WordsScreen: BaseFragment(R.layout.fragment_init_words) {
lifecycleScope.launch {
val words = getMnemonic()
if (words.isEmpty() || !Mnemonic.isValid(words)) {
navigation?.toast(Localization.incorrect_phrase)
if (TonMnemonic.isValidTONKeychain(words)) {
navigation?.toast(Localization.multi_account_secret_wrong)
} else {
navigation?.toast(Localization.incorrect_phrase)
}
return@launch
}
setLoading()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ package com.tonapps.tonkeeper.ui.screen.root
import android.app.Application
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.net.toUri
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.crashlytics.setCustomKeys
import com.google.firebase.ktx.Firebase
import com.tonapps.blockchain.ton.TonNetwork
import com.tonapps.blockchain.ton.extensions.equalsAddress
import com.tonapps.blockchain.ton.extensions.toAccountId
import com.tonapps.extensions.MutableEffectFlow
import com.tonapps.extensions.locale
import com.tonapps.extensions.setLocales
Expand Down Expand Up @@ -152,10 +156,14 @@ class RootViewModel(
val eventId = message.id
try {
val signRequests = message.params.map { SignRequestEntity(it) }
if (signRequests.isEmpty()) {
throw IllegalArgumentException("Empty sign requests")
}
for (signRequest in signRequests) {
signRequest(eventId, connection, signRequest)
}
} catch (e: Exception) {
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
tonConnectManager.sendBridgeError(connection, BridgeError.BAD_REQUEST, eventId)
}

Expand All @@ -174,6 +182,12 @@ class RootViewModel(
tonConnectManager.sendBridgeError(connection, BridgeError.METHOD_NOT_SUPPORTED, eventId)
return
}

if (signRequest.from != null && !signRequest.from!!.toAccountId().equalsAddress(connection.accountId)) {
tonConnectManager.sendBridgeError(connection, BridgeError.BAD_REQUEST, eventId)
return
}

val wallets = accountRepository.getWalletsByAccountId(
accountId = connection.accountId,
testnet = connection.testnet
Expand Down
Loading

0 comments on commit ec0c03f

Please sign in to comment.