diff --git a/core/android/src/main/kotlin/com/walletconnect/android/internal/Validator.kt b/core/android/src/main/kotlin/com/walletconnect/android/internal/Validator.kt index 000b72fa8..90ffec76d 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/internal/Validator.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/internal/Validator.kt @@ -2,6 +2,7 @@ package com.walletconnect.android.internal +import com.walletconnect.android.internal.common.model.Expiry import com.walletconnect.android.internal.common.model.RelayProtocolOptions import com.walletconnect.android.internal.common.model.SymmetricKey import com.walletconnect.android.internal.common.model.WalletConnectUri @@ -39,6 +40,8 @@ internal object Validator { val relayData: String? = mapOfQueryParameters["relay-data"] + val expiry: String? = mapOfQueryParameters["expiryTimestamp"] + var symKey = "" mapOfQueryParameters["symKey"]?.let { symKey = it } ?: return null if (symKey.isEmpty()) return null @@ -47,6 +50,7 @@ internal object Validator { topic = Topic(pairUri.userInfo), relay = RelayProtocolOptions(protocol = relayProtocol, data = relayData), symKey = SymmetricKey(symKey), + expiry = if (expiry != null) Expiry(expiry.toLong()) else null /*registeredMethods = mapOfQueryParameters["methods"]!!*/ //TODO: Will add back later after discussion about how we want to handle registered methods ) } diff --git a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/Pairing.kt b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/Pairing.kt index 571cbd471..015db6d2c 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/Pairing.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/Pairing.kt @@ -19,18 +19,18 @@ data class Pairing( val isActive: Boolean get() = (expiry.seconds - CURRENT_TIME_IN_SECONDS) > FIVE_MINUTES_IN_SECONDS - constructor(topic: Topic, relay: RelayProtocolOptions, symmetricKey: SymmetricKey, registeredMethods: String) : this( + constructor(topic: Topic, relay: RelayProtocolOptions, symmetricKey: SymmetricKey, registeredMethods: String, expiry: Expiry) : this( topic = topic, - expiry = Expiry(INACTIVE_PAIRING), + expiry = expiry, relayProtocol = relay.protocol, relayData = relay.data, - uri = WalletConnectUri(topic, symmetricKey, relay).toAbsoluteString(), + uri = WalletConnectUri(topic, symmetricKey, relay, expiry = expiry).toAbsoluteString(), registeredMethods = registeredMethods ) constructor(uri: WalletConnectUri, registeredMethods: String) : this( topic = uri.topic, - expiry = Expiry(INACTIVE_PAIRING), + expiry = uri.expiry ?: Expiry(INACTIVE_PAIRING), relayProtocol = uri.relay.protocol, relayData = uri.relay.data, uri = uri.toAbsoluteString(), diff --git a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/WalletConnectUri.kt b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/WalletConnectUri.kt index cad599038..504b7797e 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/WalletConnectUri.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/internal/common/model/WalletConnectUri.kt @@ -9,6 +9,7 @@ data class WalletConnectUri( val symKey: SymmetricKey, val relay: RelayProtocolOptions, val version: String = "2", + val expiry: Expiry? // val registeredMethods: String, // TODO: We'll review later how we want to handle registered methods ) { fun toAbsoluteString(): String = @@ -19,6 +20,9 @@ data class WalletConnectUri( if (relay.data != null) { query = "$query&relay-data=${relay.data}" } + if (expiry != null) { + query = "$query&expiryTimestamp=${expiry.seconds}" + } return query } } \ No newline at end of file diff --git a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt index 1c111572e..1eee7a6da 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/pairing/engine/domain/PairingEngine.kt @@ -29,9 +29,11 @@ import com.walletconnect.android.internal.common.scope import com.walletconnect.android.internal.common.storage.metadata.MetadataStorageRepositoryInterface import com.walletconnect.android.internal.common.storage.pairing.PairingStorageRepositoryInterface import com.walletconnect.android.internal.utils.CURRENT_TIME_IN_SECONDS +import com.walletconnect.android.internal.utils.CoreValidator.isExpired import com.walletconnect.android.internal.utils.DAY_IN_SECONDS import com.walletconnect.android.internal.utils.THIRTY_SECONDS import com.walletconnect.android.pairing.engine.model.EngineDO +import com.walletconnect.android.pairing.model.INACTIVE_PAIRING import com.walletconnect.android.pairing.model.PairingJsonRpcMethod import com.walletconnect.android.pairing.model.PairingParams import com.walletconnect.android.pairing.model.PairingRpc @@ -115,7 +117,7 @@ internal class PairingEngine( val symmetricKey: SymmetricKey = crypto.generateAndStoreSymmetricKey(pairingTopic) val relay = RelayProtocolOptions() val registeredMethods = setOfRegisteredMethods.joinToString(",") { it } - val inactivePairing = Pairing(pairingTopic, relay, symmetricKey, registeredMethods) + val inactivePairing = Pairing(pairingTopic, relay, symmetricKey, registeredMethods, Expiry(INACTIVE_PAIRING)) return inactivePairing.runCatching { logger.log("Pairing created successfully") @@ -146,17 +148,21 @@ internal class PairingEngine( try { logger.log("Pairing started: ${inactivePairing.topic}") + if (walletConnectUri.expiry?.isExpired() == true) { + logger.error("Pairing expired: ${inactivePairing.topic.value}") + return onFailure(ExpiredPairingException("Pairing expired: ${walletConnectUri.topic.value}")) + } if (pairingRepository.getPairingOrNullByTopic(inactivePairing.topic) != null) { val pairing = pairingRepository.getPairingOrNullByTopic(inactivePairing.topic) if (!pairing!!.isNotExpired()) { - logger.error("Pairing expired: ${inactivePairing.topic}") - return onFailure(ExpiredPairingException("Pairing expired: ${pairing.topic}")) + logger.error("Pairing expired: ${inactivePairing.topic.value}") + return onFailure(ExpiredPairingException("Pairing expired: ${pairing.topic.value}")) } if (pairing.isActive) { - logger.error("Pairing already exists error: ${inactivePairing.topic}") + logger.error("Pairing already exists error: ${inactivePairing.topic.value}") return onFailure(PairWithExistingPairingIsNotAllowed(PAIRING_NOT_ALLOWED_MESSAGE)) } else { - logger.log("Emitting activate pairing: ${inactivePairing.topic}") + logger.log("Emitting activate pairing: ${inactivePairing.topic.value}") scope.launch { supervisorScope { _activePairingTopicFlow.emit(inactivePairing.topic) @@ -168,16 +174,17 @@ internal class PairingEngine( pairingRepository.insertPairing(inactivePairing) } + logger.log("Subscribing pairing topic: ${inactivePairing.topic.value}") jsonRpcInteractor.subscribe(topic = inactivePairing.topic, onSuccess = { - logger.log("Subscribe pairing topic success: ${inactivePairing.topic}") + logger.log("Subscribe pairing topic success: ${inactivePairing.topic.value}") onSuccess() }, onFailure = { error -> - logger.error("Subscribe pairing topic error: ${inactivePairing.topic}, error: $error") + logger.error("Subscribe pairing topic error: ${inactivePairing.topic.value}, error: $error") return@subscribe onFailure(error) }) } catch (e: Exception) { - logger.error("Subscribe pairing topic error: ${inactivePairing.topic}, error: $e") + logger.error("Subscribe pairing topic error: ${inactivePairing.topic.value}, error: $e") crypto.removeKeys(walletConnectUri.topic.value) jsonRpcInteractor.unsubscribe(inactivePairing.topic) onFailure(e) diff --git a/core/android/src/main/kotlin/com/walletconnect/android/pairing/model/PairingExpiration.kt b/core/android/src/main/kotlin/com/walletconnect/android/pairing/model/PairingExpiration.kt index bba89fdb4..1d6c76842 100644 --- a/core/android/src/main/kotlin/com/walletconnect/android/pairing/model/PairingExpiration.kt +++ b/core/android/src/main/kotlin/com/walletconnect/android/pairing/model/PairingExpiration.kt @@ -3,8 +3,8 @@ package com.walletconnect.android.pairing.model import com.walletconnect.android.internal.utils.CURRENT_TIME_IN_SECONDS -import com.walletconnect.android.internal.utils.FIVE_MINUTES_IN_SECONDS import com.walletconnect.android.internal.utils.MONTH_IN_SECONDS +import com.walletconnect.android.internal.utils.THIRTY_SECONDS -val INACTIVE_PAIRING: Long get() = CURRENT_TIME_IN_SECONDS + FIVE_MINUTES_IN_SECONDS +val INACTIVE_PAIRING: Long get() = CURRENT_TIME_IN_SECONDS + THIRTY_SECONDS//FIVE_MINUTES_IN_SECONDS val ACTIVE_PAIRING: Long get() = CURRENT_TIME_IN_SECONDS + MONTH_IN_SECONDS \ No newline at end of file diff --git a/core/android/src/test/kotlin/com/walletconnect/android/internal/ValidatorTest.kt b/core/android/src/test/kotlin/com/walletconnect/android/internal/ValidatorTest.kt index 0015165b5..ccc0c6652 100644 --- a/core/android/src/test/kotlin/com/walletconnect/android/internal/ValidatorTest.kt +++ b/core/android/src/test/kotlin/com/walletconnect/android/internal/ValidatorTest.kt @@ -14,7 +14,7 @@ internal class ValidatorTest { @Test fun `validate WC uri test`() { val validUri = - "wc:7f6e504bfad60b485450578e05678ed3e8e8c4751d3c6160be17160d63ec90f9@2?relay-protocol=irn&symKey=587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303" + "wc:7f6e504bfad60b485450578e05678ed3e8e8c4751d3c6160be17160d63ec90f9@2?relay-protocol=irn&symKey=587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303&expiryTimestamp=1705667684" Validator.validateWCUri("").apply { assertEquals(null, this) } Validator.validateWCUri(validUri).apply { @@ -23,6 +23,7 @@ internal class ValidatorTest { assertEquals("irn", this!!.relay.protocol) assertEquals("587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303", this.symKey.keyAsHex) assertEquals("2", this.version) + assertEquals(1705667684L, expiry) } val noTopicInvalidUri = @@ -64,6 +65,7 @@ internal class ValidatorTest { Topic("11112222244444"), SymmetricKey("0x12321321312312312321"), RelayProtocolOptions("irn", "teeestData"), + expiry = null ) assertEquals(uri.toAbsoluteString(), "wc:11112222244444@2?relay-protocol=irn&relay-data=teeestData&symKey=0x12321321312312312321") @@ -72,8 +74,9 @@ internal class ValidatorTest { Topic("11112222244444"), SymmetricKey("0x12321321312312312321"), RelayProtocolOptions("irn"), + expiry = 1705667684 ) - assertEquals(uri2.toAbsoluteString(), "wc:11112222244444@2?relay-protocol=irn&symKey=0x12321321312312312321") + assertEquals(uri2.toAbsoluteString(), "wc:11112222244444@2?relay-protocol=irn&expiryTimestamp=1705667684&symKey=0x12321321312312312321") } } \ No newline at end of file diff --git a/product/walletconnectmodal/src/main/kotlin/com/walletconnect/wcmodal/ui/WalletConnectModalViewModel.kt b/product/walletconnectmodal/src/main/kotlin/com/walletconnect/wcmodal/ui/WalletConnectModalViewModel.kt index f1c288ea0..cae2b4848 100644 --- a/product/walletconnectmodal/src/main/kotlin/com/walletconnect/wcmodal/ui/WalletConnectModalViewModel.kt +++ b/product/walletconnectmodal/src/main/kotlin/com/walletconnect/wcmodal/ui/WalletConnectModalViewModel.kt @@ -82,6 +82,7 @@ internal class WalletConnectModalViewModel : ViewModel() { fun saveRecentWallet(wallet: Wallet) { walletsDataStore.updateRecentWallet(wallet.id) } + fun clearSearch() = walletsDataStore.clearSearch() fun getWallet(walletId: String?) = walletsDataStore.getWallet(walletId) diff --git a/sample/dapp/src/main/kotlin/com/walletconnect/sample/dapp/ui/routes/composable_routes/chain_selection/ChainSelectionRoute.kt b/sample/dapp/src/main/kotlin/com/walletconnect/sample/dapp/ui/routes/composable_routes/chain_selection/ChainSelectionRoute.kt index a93e4f7a5..2240c4c73 100644 --- a/sample/dapp/src/main/kotlin/com/walletconnect/sample/dapp/ui/routes/composable_routes/chain_selection/ChainSelectionRoute.kt +++ b/sample/dapp/src/main/kotlin/com/walletconnect/sample/dapp/ui/routes/composable_routes/chain_selection/ChainSelectionRoute.kt @@ -91,7 +91,6 @@ fun ChainSelectionRoute(navController: NavController) { is PairingSelectionResult.SelectedPairing -> { viewModel.connectToWallet(it.position, onSuccess = { - println("Proposal sent successfully") }, onError = { error ->