Skip to content

Commit

Permalink
Merge branch 'main' into release/1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
zaiatsartem committed Nov 29, 2024
2 parents 68a8c99 + 492df3b commit dcc9b73
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 94 deletions.
10 changes: 4 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -311,12 +311,10 @@ dependencies {
androidTestImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation "android.arch.persistence.room:testing:1.1.1"

// WalletConnect.
// Further updates require regression testing.
// Update to 1.32.0+2.32.0 requires fixing
// opening links from a mobile browser and request spam prevention.
implementation "com.walletconnect:android-core:1.13.0"
implementation "com.walletconnect:sign:2.11.0"
// Reown (formerly WalletConnect)
implementation(platform "com.reown:android-bom:1.0.0")
implementation "com.reown:android-core"
implementation "com.reown:sign"

// Scarlet Gson adapter required for Spaceseven wallet connection.
implementation("com.tinder.scarlet:message-adapter-gson:0.1.12") {
Expand Down
13 changes: 7 additions & 6 deletions app/src/main/java/com/concordium/wallet/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import android.content.Context
import com.concordium.wallet.core.notifications.AnnouncementNotificationManager
import com.concordium.wallet.data.backend.ws.WsCreds
import com.concordium.wallet.util.Log
import com.walletconnect.android.Core
import com.walletconnect.android.CoreClient
import com.walletconnect.android.relay.ConnectionType
import com.walletconnect.android.relay.NetworkClientTimeout
import com.walletconnect.sign.client.Sign
import com.walletconnect.sign.client.SignClient
import com.reown.android.Core
import com.reown.android.CoreClient
import com.reown.android.relay.ConnectionType
import com.reown.android.relay.NetworkClientTimeout
import com.reown.sign.client.Sign
import com.reown.sign.client.SignClient
import java.util.concurrent.TimeUnit

class App : Application() {
Expand Down Expand Up @@ -62,6 +62,7 @@ class App : Application() {
networkClientTimeout = NetworkClientTimeout(40, TimeUnit.SECONDS),
application = this,
metaData = appMetaData,
telemetryEnabled = false,
onError = { error ->
println("WalletConnect -> CORE ERROR ${error.throwable.stackTraceToString()}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed
import com.concordium.wallet.App
import com.concordium.wallet.util.toHex
import com.walletconnect.util.hexToBytes
import com.reown.util.hexToBytes
import javax.crypto.SecretKey

class AuthPreferences(val context: Context) :
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.concordium.wallet.data.util

import com.walletconnect.util.hexToBytes
import com.reown.util.hexToBytes
import okio.utf8Size

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.concordium.wallet.ui.cis2.retrofit.MetadataApiInstance
import com.concordium.wallet.ui.common.BackendErrorHandler
import com.concordium.wallet.util.Log
import com.concordium.wallet.util.toBigInteger
import com.walletconnect.util.Empty
import com.reown.util.Empty
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import com.concordium.wallet.ui.walletconnect.WalletConnectViewModel.State
import com.concordium.wallet.util.Log
import com.concordium.wallet.util.PrettyPrint.prettyPrint
import com.concordium.wallet.util.toHex
import com.walletconnect.util.hexToBytes
import com.reown.util.hexToBytes

class WalletConnectSignMessageRequestHandler(
private val respondSuccess: (result: String) -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import com.concordium.wallet.ui.walletconnect.delegate.LoggingWalletConnectCoreD
import com.concordium.wallet.ui.walletconnect.delegate.LoggingWalletConnectWalletDelegate
import com.concordium.wallet.util.KeyCreationVersion
import com.concordium.wallet.util.Log
import com.walletconnect.android.Core
import com.walletconnect.android.CoreClient
import com.walletconnect.sign.client.Sign
import com.walletconnect.sign.client.SignClient
import com.reown.android.Core
import com.reown.android.CoreClient
import com.reown.sign.client.Sign
import com.reown.sign.client.SignClient
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -202,7 +202,7 @@ private constructor(
Log.d(
"initialized:" +
"\npairingsCount=${CoreClient.Pairing.getPairings().size}," +
"\nsettledSessionsCount=${SignClient.getListOfSettledSessions().size}"
"\nactiveSessionsCount=${SignClient.getListOfActiveSessions().size}"
)

handleNextOldestPendingSessionRequest()
Expand Down Expand Up @@ -306,44 +306,48 @@ private constructor(
private fun onRequestWcUriReceived() {
// When receiving the request URI, enter the request waiting state.
// The request will arrive soon over the websocket.
mutableStateFlow.tryEmit(State.WaitingForSessionRequest)
if (state !is State.SessionRequestReview) {
mutableStateFlow.tryEmit(State.WaitingForSessionRequest)
}
}

override fun onConnectionStateChange(state: Sign.Model.ConnectionState) {
defaultWalletDelegate.onConnectionStateChange(state)
connectionAvailabilityFlow.tryEmit(state.isAvailable)
}

override fun onSessionProposal(sessionProposal: Sign.Model.SessionProposal) =
viewModelScope.launch {
defaultWalletDelegate.onSessionProposal(sessionProposal)

// Find a single allowed namespace and chain.
val singleNamespaceEntry =
sessionProposal.requiredNamespaces.entries.find { (_, namespace) ->
namespace.chains?.any { chain ->
allowedChains.contains(chain)
} == true
}
val singleNamespaceChain = singleNamespaceEntry?.value?.chains?.find { chain ->
allowedChains.contains(chain)
override fun onSessionProposal(
sessionProposal: Sign.Model.SessionProposal,
verifyContext: Sign.Model.VerifyContext
) = viewModelScope.launch {
defaultWalletDelegate.onSessionProposal(sessionProposal, verifyContext)

// Find a single allowed namespace and chain.
val singleNamespaceEntry =
sessionProposal.requiredNamespaces.entries.find { (_, namespace) ->
namespace.chains?.any { chain ->
allowedChains.contains(chain)
} == true
}
val singleNamespaceChain = singleNamespaceEntry?.value?.chains?.find { chain ->
allowedChains.contains(chain)
}

val proposerPublicKey = sessionProposal.proposerPublicKey
val proposerPublicKey = sessionProposal.proposerPublicKey

if (singleNamespaceEntry == null || singleNamespaceChain == null) {
Log.e("cant_find_supported_chain")
mutableEventsFlow.tryEmit(
Event.ShowFloatingError(
Error.NoSupportedChains
)
)
rejectSession(
proposerPublicKey,
"The session proposal did not contain a valid namespace. Allowed namespaces are: $allowedChains"
if (singleNamespaceEntry == null || singleNamespaceChain == null) {
Log.e("cant_find_supported_chain")
mutableEventsFlow.tryEmit(
Event.ShowFloatingError(
Error.NoSupportedChains
)
return@launch
}
)
rejectSession(
proposerPublicKey,
"The session proposal did not contain a valid namespace. Allowed namespaces are: $allowedChains"
)
return@launch
}

// Check if the proposer requests unsupported methods, and reject the session proposal
// if that is the case.
Expand Down Expand Up @@ -525,9 +529,11 @@ private constructor(
)
}

override fun onSessionRequest(sessionRequest: Sign.Model.SessionRequest) {
defaultWalletDelegate.onSessionRequest(sessionRequest)

override fun onSessionRequest(
sessionRequest: Sign.Model.SessionRequest,
verifyContext: Sign.Model.VerifyContext
) {
defaultWalletDelegate.onSessionRequest(sessionRequest, verifyContext)
val sessionRequestPeerMetadata: Core.Model.AppMetaData? = sessionRequest.peerMetaData
if (sessionRequestPeerMetadata == null) {
Log.e("missing_app_metadata_in_session_request")
Expand All @@ -540,42 +546,40 @@ private constructor(
return
}

if (state is State.Idle || state is State.WaitingForSessionRequest) {
// Only handle the request if not doing anything else.
// Otherwise, the request will be handled as a pending one
// once the current affair is finished.
handleSessionRequest(
topic = sessionRequest.topic,
id = sessionRequest.request.id,
method = sessionRequest.request.method,
params = sessionRequest.request.params,
peerMetadata = sessionRequestPeerMetadata
)
} else {
// We do not want to queue more than one request for each topic (dApp),
// as the dApp may be broken and spam requests.
// At this point, topic pending requests may already contain this sessionRequest.
val topicPendingRequests = SignClient.getPendingRequests(sessionRequest.topic)
if (topicPendingRequests.isEmpty() || topicPendingRequests.size == 1) {
Log.d(
"session_request_to_be_handled_later:" +
"\nrequestId=${sessionRequest.request.id}" +
"\nrequestTopic=${sessionRequest.topic}"
// We do not want to queue more than one request for each topic (dApp),
// as the dApp may be broken and spam requests.
// At this point, topic pending requests may already contain this sessionRequest.
val topicPendingRequests = SignClient.getPendingSessionRequests(sessionRequest.topic)
if (topicPendingRequests.isEmpty() || topicPendingRequests.size == 1) {
// Only handle the request if the session ID is different from the current one
// Otherwise, ignore the re-processing call
if (sessionRequest.request.id != this.sessionRequestId) {
handleSessionRequest(
topic = sessionRequest.topic,
id = sessionRequest.request.id,
method = sessionRequest.request.method,
params = sessionRequest.request.params,
peerMetadata = sessionRequestPeerMetadata
)
} else {
Log.w(
"received_next_session_request_in_topic_before_current_is_handled:" +
"\nrequestId=${sessionRequest.request.id}" +
"\nrequestTopic=${sessionRequest.topic}"
)

respondError(
message = "Subsequent requests are rejected until the current one is handled: " +
topicPendingRequests.first().requestId,
sessionRequestId = sessionRequest.request.id,
sessionRequestTopic = sessionRequest.topic,
"received_next_session_request_in_topic_with_the_same_id" +
"\ndon't handle the request again"
)
}
} else {
Log.w(
"received_next_session_request_in_topic_before_current_is_handled:" +
"\nrequestId=${topicPendingRequests.last().request.id}" +
"\nrequestTopic=${topicPendingRequests.last().topic}"
)

respondError(
message = "Subsequent requests are rejected until the current one is handled: " +
topicPendingRequests.first().request.id,
sessionRequestId = topicPendingRequests.last().request.id,
sessionRequestTopic = topicPendingRequests.last().topic,
)
}
}

Expand Down Expand Up @@ -624,7 +628,7 @@ private constructor(

// Find the session that the request matches. The session will allow us to extract
// the account that the request is for.
val currentSession = SignClient.getSettledSessionByTopic(topic)
val currentSession = SignClient.getActiveSessionByTopic(topic)
if (currentSession == null) {
Log.e("Received a request for a topic where we did not find the session: Topic=$topic")

Expand Down Expand Up @@ -753,11 +757,12 @@ private constructor(
}

private fun handleNextOldestPendingSessionRequest() {
val settledSessions = SignClient.getListOfSettledSessions()
val activeSessions = SignClient.getListOfActiveSessions()
val pendingRequestWithMetaData: Pair<Sign.Model.PendingRequest, Core.Model.AppMetaData?>? =
settledSessions
activeSessions
.map { session ->
SignClient.getPendingRequests(session.topic)
SignClient.getPendingSessionRequests(session.topic)
.filterIsInstance<Sign.Model.PendingRequest>() // Ensure the type matches
.filter { pendingRequest ->
// Do not include requests just handled.
pendingRequest.requestId !in handledRequests
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.concordium.wallet.ui.walletconnect.delegate

import com.concordium.wallet.util.Log
import com.walletconnect.android.Core
import com.walletconnect.android.CoreClient
import com.reown.android.Core
import com.reown.android.CoreClient

open class LoggingWalletConnectCoreDelegate: CoreClient.CoreDelegate {
override fun onPairingDelete(deletedPairing: Core.Model.DeletedPairing) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.concordium.wallet.ui.walletconnect.delegate

import com.concordium.wallet.util.Log
import com.walletconnect.sign.client.Sign
import com.walletconnect.sign.client.SignClient
import com.reown.sign.client.Sign
import com.reown.sign.client.SignClient

class LoggingWalletConnectWalletDelegate : SignClient.WalletDelegate {
override fun onConnectionStateChange(state: Sign.Model.ConnectionState) {
Expand All @@ -23,14 +23,27 @@ class LoggingWalletConnectWalletDelegate : SignClient.WalletDelegate {
)
}

override fun onSessionProposal(sessionProposal: Sign.Model.SessionProposal) {
override fun onSessionExtend(session: Sign.Model.Session) {
Log.d(
"session_extended:" +
"\nextended=$session"
)
}

override fun onSessionProposal(
sessionProposal: Sign.Model.SessionProposal,
verifyContext: Sign.Model.VerifyContext
) {
Log.d(
"received_session_proposal:" +
"\nproposal=$sessionProposal"
)
}

override fun onSessionRequest(sessionRequest: Sign.Model.SessionRequest) {
override fun onSessionRequest(
sessionRequest: Sign.Model.SessionRequest,
verifyContext: Sign.Model.VerifyContext
) {
Log.d(
"received_session_request:" +
"\nrequestId=${sessionRequest.request.id}"
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.0'
classpath 'com.android.tools.build:gradle:8.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.4.2'
classpath 'com.google.firebase:firebase-appdistribution-gradle:2.2.0'
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
android.suppressUnsupportedCompileSdk=34

0 comments on commit dcc9b73

Please sign in to comment.