diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd4aed73..f28ca796 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,5 +13,6 @@
### Changed
- Suggest running a recovery when facing account or identity creation errors
- Baker/baking renamed to Validator/validating
+- WalletConnect session proposals are now rejected if the namespace or methods are not supported, or if the wallet contains no accounts.
[Unreleased]: https://github.com/Concordium/cryptox-android/compare/0.6.1-qa.5...HEAD
diff --git a/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectView.kt b/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectView.kt
index 338946b6..72cacfe9 100644
--- a/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectView.kt
+++ b/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectView.kt
@@ -163,6 +163,9 @@ class WalletConnectView(
WalletConnectViewModel.Error.NoSupportedChains ->
R.string.wallet_connect_error_no_supported_chains
+
+ WalletConnectViewModel.Error.UnsupportedMethod ->
+ R.string.wallet_connect_error_unsupported_methods
}
Toast.makeText(activity, errorRes, Toast.LENGTH_SHORT).show()
diff --git a/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectViewModel.kt b/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectViewModel.kt
index 24f29158..f686bcc8 100644
--- a/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectViewModel.kt
+++ b/app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectViewModel.kt
@@ -106,6 +106,11 @@ private constructor(
),
)
+ private val allowedRequestMethods = setOf(
+ REQUEST_METHOD_SIGN_AND_SEND_TRANSACTION,
+ REQUEST_METHOD_SIGN_MESSAGE,
+ )
+
private val accountRepository: AccountRepository by lazy {
AccountRepository(WalletDatabase.getDatabase(getApplication()).accountDao())
}
@@ -289,15 +294,30 @@ private constructor(
allowedChains.contains(chain)
}
+ val proposerPublicKey = sessionProposal.proposerPublicKey
+
if (singleNamespaceEntry == null || singleNamespaceChain == null) {
Log.e("cant_find_supported_chain")
-
mutableEventsFlow.tryEmit(
Event.ShowFloatingError(
Error.NoSupportedChains
)
)
- mutableStateFlow.tryEmit(State.Idle)
+ 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.
+ val requestedMethods = singleNamespaceEntry.value.methods
+ if (!allowedRequestMethods.containsAll(requestedMethods)) {
+ Log.e("Received an unsupported request method: $requestedMethods")
+ mutableEventsFlow.tryEmit(
+ Event.ShowFloatingError(
+ Error.UnsupportedMethod
+ )
+ )
+ rejectSession(proposerPublicKey, "An unsupported method was requested: $requestedMethods, supported methods are $allowedRequestMethods")
return@launch
}
@@ -306,17 +326,16 @@ private constructor(
val accounts = getAvailableAccounts()
if (accounts.isEmpty()) {
Log.d("there_are_no_accounts")
-
mutableEventsFlow.tryEmit(
Event.ShowFloatingError(
Error.NoAccounts
)
)
- mutableStateFlow.tryEmit(State.Idle)
+ rejectSession(proposerPublicKey, "The wallet does not contain any accounts to open a session for")
return@launch
}
- this@WalletConnectViewModel.sessionProposalPublicKey = sessionProposal.proposerPublicKey
+ this@WalletConnectViewModel.sessionProposalPublicKey = proposerPublicKey
this@WalletConnectViewModel.sessionProposalNamespaceKey = singleNamespaceEntry.key
this@WalletConnectViewModel.sessionProposalNamespace = singleNamespaceEntry.value
this@WalletConnectViewModel.sessionProposalNamespaceChain = singleNamespaceChain
@@ -375,20 +394,14 @@ private constructor(
mutableStateFlow.tryEmit(State.Idle)
}
- fun rejectSessionProposal() {
- check(state is State.SessionProposalReview || state is State.AccountSelection) {
- "Session proposal rejection is only possible in the proposal review " +
- "or account selection states"
- }
+ private fun rejectSession(proposerPublicKey: String, reason: String) {
+ val rejectParams = Sign.Params.Reject(
+ proposerPublicKey = proposerPublicKey,
+ reason = reason
+ )
- SignClient.rejectSession(
- Sign.Params.Reject(
- proposerPublicKey = sessionProposalPublicKey,
- reason = "Rejected by user",
- )
- ) { error ->
+ SignClient.rejectSession(rejectParams) { error ->
Log.e("failed_rejecting_session", error.throwable)
-
mutableEventsFlow.tryEmit(
Event.ShowFloatingError(
Error.ResponseFailed
@@ -399,6 +412,14 @@ private constructor(
mutableStateFlow.tryEmit(State.Idle)
}
+ fun rejectSessionProposal() {
+ check(state is State.SessionProposalReview || state is State.AccountSelection) {
+ "Session proposal rejection is only possible in the proposal review " +
+ "or account selection states"
+ }
+ rejectSession(sessionProposalPublicKey, "Rejected by user")
+ }
+
fun onChooseAccountClicked() {
val reviewState = checkNotNull(state as? State.SessionProposalReview) {
"Choose account button can only be clicked in the proposal review state"
@@ -1243,6 +1264,11 @@ private constructor(
*/
object NoSupportedChains : Error
+ /**
+ * The dApp sent a session proposal requesting an unsupported method.
+ */
+ object UnsupportedMethod : Error
+
/**
* The dApp sent a request that can't be parsed.
*/
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a1d4af96..9a4e7874 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -552,6 +552,7 @@
Could not submit the transaction
You must have at least one active account to continue
The wallet does not support the requested chains
+ The wallet does not support the requested methods
Choose another account
Connect to %1$s?
@string/allow