From 6106b652c7fce5f211334e3e7899f59c60f8ca3f Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 20 Oct 2022 12:46:41 +0200 Subject: [PATCH 01/30] Remove unnecessary files from copiedFromSing dir. Fix imports to reach compatibility with androidCore module --- ReadMe.md | 1 + auth/sdk/build.gradle.kts | 2 +- .../auth/engine/domain/AuthEngine.kt | 38 +-- .../chat/client/ChatInterface.kt | 15 - .../walletconnect/chat/client/ChatProtocol.kt | 13 +- .../BouncyCastleKeyManagementRepository.kt | 45 ++- .../{json_rpc/model => }/JsonRpcMethod.kt | 2 +- .../{json_rpc/data => }/JsonRpcSerializer.kt | 9 +- .../{crypto/data/keystore => }/KeyChain.kt | 13 +- .../copiedFromSign/KeyManagementRepository.kt | 29 ++ .../copiedFromSign/{crypto => }/KeyStore.kt | 6 +- .../RelayDOJsonRpcResultJsonAdapter.kt | 3 +- .../core/adapters/ExpiryAdapter.kt | 39 --- .../core/adapters/JSONObjectAdapter.kt | 34 --- .../core/adapters/SubscriptionIdAdapter.kt | 39 --- .../core/adapters/TopicAdapter.kt | 39 --- .../core/adapters/TtlAdapter.kt | 39 --- .../core/exceptions/Messages.kt | 38 --- .../exceptions/client/ClientExceptions.kt | 29 -- .../core/exceptions/peer/PeerError.kt | 100 ------- .../core/exceptions/peer/PeerReason.kt | 14 - .../copiedFromSign/core/model/client/Relay.kt | 162 ---------- .../core/model/type/ClientParams.kt | 3 - .../core/model/type/JsonRpcClientSync.kt | 8 - .../core/model/type/SerializableJsonRpc.kt | 3 - .../core/model/type/enums/EnvelopeType.kt | 5 - .../core/model/vo/CommonObjects.kt | 23 -- .../core/model/vo/IriudiumParamsVO.kt | 5 - .../core/model/vo/jsonRpc/JsonRpcHistoryVO.kt | 9 - .../model/vo/jsonRpc/JsonRpcResponseVO.kt | 28 -- .../core/model/vo/sync/ParticipantsVO.kt | 10 - .../core/model/vo/sync/PendingRequestVO.kt | 9 - .../core/model/vo/sync/WCRequestVO.kt | 11 - .../core/model/vo/sync/WCResponseVO.kt | 12 - .../core/scope/WalletConnectScope.kt | 15 - .../chat/copiedFromSign/core/utils/Time.kt | 12 - .../chat/copiedFromSign/crypto/Codec.kt | 12 - .../crypto/KeyManagementRepository.kt | 29 -- .../crypto/data/codec/ChaChaPolyCodec.kt | 161 ---------- .../chat/copiedFromSign/di/CommonModule.kt | 47 --- .../chat/copiedFromSign/di/CryptoModule.kt | 32 -- .../chat/copiedFromSign/di/DITags.kt | 11 - .../chat/copiedFromSign/di/NetworkModule.kt | 72 ----- .../chat/copiedFromSign/di/RelayerModule.kt | 28 -- .../chat/copiedFromSign/di/StorageModule.kt | 60 ---- .../json_rpc/domain/RelayerInteractor.kt | 282 ------------------ .../json_rpc/model/RelayerDO.kt | 36 --- .../json_rpc/model/RelayerMapper.kt | 46 --- .../copiedFromSign/network/RelayInterface.kt | 32 -- .../network/adapter/FlowStreamAdapter.kt | 30 -- .../network/connection/ConnectionEvent.kt | 5 - .../network/connection/ConnectionType.kt | 5 - .../controller/ConnectionController.kt | 26 -- .../lifecycle/ManualConnectionLifecycle.kt | 30 -- .../network/domain/RelayClient.kt | 181 ----------- .../network/model/JsonRpcRelay.kt | 9 - .../copiedFromSign/network/model/RelayDTO.kt | 214 ------------- .../network/model/RelayMapper.kt | 54 ---- .../network/service/RelayService.kt | 46 --- .../copiedFromSign/storage/JsonRpcHistory.kt | 60 ---- .../copiedFromSign/util/KotlinExtensions.kt | 9 - .../chat/copiedFromSign/util/Logger.kt | 39 --- .../chat/copiedFromSign/util/NetworkState.kt | 26 -- .../chat/copiedFromSign/util/Time.kt | 9 - .../chat/copiedFromSign/util/UtilFunctions.kt | 57 ---- .../chat/core/model/vo/Common.kt | 2 +- .../core/model/vo/clientsync/ChatRpcVO.kt | 4 +- .../vo/clientsync/params/ChatParamsVO.kt | 2 +- .../keyserver/model/KeyserverMapper.kt | 4 +- .../chat/engine/domain/ChatEngine.kt | 96 +++--- .../chat/storage/ChatStorageRepository.kt | 2 +- .../sign/engine/domain/SignEngine.kt | 124 ++++---- 72 files changed, 209 insertions(+), 2535 deletions(-) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/{crypto/data/repository => }/BouncyCastleKeyManagementRepository.kt (79%) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/{json_rpc/model => }/JsonRpcMethod.kt (87%) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/{json_rpc/data => }/JsonRpcSerializer.kt (79%) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/{crypto/data/keystore => }/KeyChain.kt (83%) create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt rename chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/{crypto => }/KeyStore.kt (73%) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/{core/adapters => }/RelayDOJsonRpcResultJsonAdapter.kt (97%) delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/ExpiryAdapter.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/JSONObjectAdapter.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/SubscriptionIdAdapter.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TopicAdapter.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TtlAdapter.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/Messages.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/client/ClientExceptions.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerError.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerReason.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/client/Relay.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/ClientParams.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/JsonRpcClientSync.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/SerializableJsonRpc.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/enums/EnvelopeType.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/CommonObjects.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/IriudiumParamsVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcHistoryVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcResponseVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/ParticipantsVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/PendingRequestVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCRequestVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCResponseVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/scope/WalletConnectScope.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/utils/Time.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/Codec.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyManagementRepository.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/codec/ChaChaPolyCodec.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CommonModule.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CryptoModule.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/DITags.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/NetworkModule.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/RelayerModule.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/StorageModule.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/domain/RelayerInteractor.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerDO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerMapper.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/RelayInterface.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/adapter/FlowStreamAdapter.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionEvent.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionType.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/controller/ConnectionController.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/lifecycle/ManualConnectionLifecycle.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/domain/RelayClient.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/JsonRpcRelay.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayDTO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayMapper.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/service/RelayService.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/storage/JsonRpcHistory.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/KotlinExtensions.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Logger.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/NetworkState.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Time.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/UtilFunctions.kt diff --git a/ReadMe.md b/ReadMe.md index e2909effa9..8025350855 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -10,6 +10,7 @@ WalletConnect v2 protocols for Android applications. * [Core SDK](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/androidCore) * [Sign SDK](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/sign) * [Auth SDK](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/auth) +* [Chat SDK] TBD ## License WalletConnect v2 is released under the Apache 2.0 license. [See LICENSE](https://github.com/WalletConnect/WalletConnectKotlinV2/blob/feature/develop/LICENSE) for details. diff --git a/auth/sdk/build.gradle.kts b/auth/sdk/build.gradle.kts index 4de7e373c4..ac0e891516 100644 --- a/auth/sdk/build.gradle.kts +++ b/auth/sdk/build.gradle.kts @@ -20,7 +20,7 @@ android { minSdk = MIN_SDK targetSdk = TARGET_SDK - buildConfigField(type = "String", name= "sdkVersion", value = "\"1.0.0-alpha01\"") + buildConfigField(type = "String", name = "sdkVersion", value = "\"1.0.0-alpha01\"") buildConfigField("String", "PROJECT_ID", "\"${System.getenv("WC_CLOUD_PROJECT_ID") ?: ""}\"") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt index 78844727be..85273a75d3 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt @@ -41,7 +41,7 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch internal class AuthEngine( - private val relayer: JsonRpcInteractor, + private val jsonRpcInteractor: JsonRpcInteractor, private val crypto: KeyManagementRepository, private val storage: AuthStorageRepository, private val metaData: AppMetaData, @@ -64,7 +64,7 @@ internal class AuthEngine( } internal fun handleInitializationErrors(onError: (WalletConnectException) -> Unit) { - relayer.initializationErrorsFlow.onEach { walletConnectException -> onError(walletConnectException) }.launchIn(scope) + jsonRpcInteractor.initializationErrorsFlow.onEach { walletConnectException -> onError(walletConnectException) }.launchIn(scope) } internal fun request( @@ -93,10 +93,10 @@ internal class AuthEngine( val irnParams = IrnParams(Tags.AUTH_REQUEST, Ttl(DAY_IN_SECONDS), true) onPairing(walletConnectUri.toAbsoluteString()) - relayer.publishJsonRpcRequests(pairingTopic, irnParams, authRequest, + jsonRpcInteractor.publishJsonRpcRequests(pairingTopic, irnParams, authRequest, onSuccess = { Logger.log("Auth request sent successfully on topic:$pairingTopic, awaiting response on topic:$responseTopic") // todo: Remove after Alpha - relayer.subscribe(responseTopic) + jsonRpcInteractor.subscribe(responseTopic) pairingTopicToResponseTopicMap[pairingTopic] = responseTopic }, onFailure = { error -> @@ -126,10 +126,10 @@ internal class AuthEngine( try { storage.insertPairing(activePairing) - relayer.subscribe(activePairing.topic) + jsonRpcInteractor.subscribe(activePairing.topic) } catch (e: SQLiteException) { crypto.removeKeys(walletConnectUri.topic.value) - relayer.unsubscribe(activePairing.topic) + jsonRpcInteractor.unsubscribe(activePairing.topic) } } @@ -137,7 +137,7 @@ internal class AuthEngine( respond: Respond, onFailure: (Throwable) -> Unit, ) { - val jsonRpcHistoryEntry = relayer.getPendingJsonRpcHistoryEntryById(respond.id) + val jsonRpcHistoryEntry = jsonRpcInteractor.getPendingJsonRpcHistoryEntryById(respond.id) if (jsonRpcHistoryEntry == null) { Logger.error(MissingAuthRequestException.message) onFailure(MissingAuthRequestException) @@ -165,7 +165,7 @@ internal class AuthEngine( crypto.setSymmetricKey(responseTopic, symmetricKey) val irnParams = IrnParams(Tags.AUTH_REQUEST_RESPONSE, Ttl(DAY_IN_SECONDS), false) - relayer.publishJsonRpcResponse( + jsonRpcInteractor.publishJsonRpcResponse( responseTopic, irnParams, response, envelopeType = EnvelopeType.ONE, participants = Participants(senderPublicKey, receiverPublicKey), onSuccess = { Logger.log("Success Responded on topic: $responseTopic") }, onFailure = { Logger.error("Error Responded on topic: $responseTopic") } @@ -173,7 +173,7 @@ internal class AuthEngine( } internal fun getResponseById(id: Long): Response? { - return relayer.getResponseById(id)?.let { response -> + return jsonRpcInteractor.getResponseById(id)?.let { response -> when (response) { is JsonRpcResponse.JsonRpcResult -> { val (header, payload, signature) = (response.result as AuthParams.ResponseParams) @@ -189,7 +189,7 @@ internal class AuthEngine( if (issuer == null) { throw MissingIssuerException } - return relayer.getPendingJsonRpcHistoryEntries() + return jsonRpcInteractor.getPendingJsonRpcHistoryEntries() .map { jsonRpcHistoryEntry -> jsonRpcHistoryEntry.toPendingRequest(issuer) } } @@ -201,7 +201,7 @@ internal class AuthEngine( } } else { val irnParams = IrnParams(Tags.AUTH_REQUEST_RESPONSE, Ttl(DAY_IN_SECONDS), false) - relayer.respondWithError(wcRequest, PeerError.MissingIssuer, irnParams) + jsonRpcInteractor.respondWithError(wcRequest, PeerError.MissingIssuer, irnParams) } } @@ -243,7 +243,7 @@ internal class AuthEngine( private fun collectJsonRpcRequests() { scope.launch { - relayer.clientSyncJsonRpc.collect { request -> + jsonRpcInteractor.clientSyncJsonRpc.collect { request -> when (val params = request.params) { is AuthParams.RequestParams -> onAuthRequest(request, params) } @@ -253,7 +253,7 @@ internal class AuthEngine( private fun collectJsonRpcResponses() { scope.launch { - relayer.peerResponse.collect { response -> + jsonRpcInteractor.peerResponse.collect { response -> when (response.params) { is AuthParams.RequestParams -> onAuthRequestResponse(response) } @@ -262,7 +262,7 @@ internal class AuthEngine( } private fun resubscribeToSequences() { - relayer.isConnectionAvailable + jsonRpcInteractor.isConnectionAvailable .onEach { isAvailable -> _engineEvent.emit(ConnectionState(isAvailable)) } .filter { isAvailable: Boolean -> isAvailable } .onEach { @@ -275,7 +275,7 @@ internal class AuthEngine( } private fun resubscribeToPendingRequestsTopics() { - pairingTopicToResponseTopicMap.onEach { (_: Topic, responseTopic: Topic) -> relayer.subscribe(responseTopic) } + pairingTopicToResponseTopicMap.onEach { (_: Topic, responseTopic: Topic) -> jsonRpcInteractor.subscribe(responseTopic) } } private fun resubscribeToPairings() { @@ -285,25 +285,25 @@ internal class AuthEngine( listOfExpiredPairing .map { pairing -> pairing.topic } .onEach { pairingTopic -> - relayer.unsubscribe(pairingTopic) + jsonRpcInteractor.unsubscribe(pairingTopic) crypto.removeKeys(pairingTopic.value) storage.deletePairing(pairingTopic) } listOfValidPairing .map { pairing -> pairing.topic } - .onEach { pairingTopic -> relayer.subscribe(pairingTopic) } + .onEach { pairingTopic -> jsonRpcInteractor.subscribe(pairingTopic) } } private fun setupSequenceExpiration() { storage.onPairingExpired = { topic -> - relayer.unsubscribe(topic) + jsonRpcInteractor.unsubscribe(topic) crypto.removeKeys(topic.value) } } private fun collectInternalErrors() { - relayer.internalErrors + jsonRpcInteractor.internalErrors .onEach { exception -> _engineEvent.emit(SDKError(exception)) } .launchIn(scope) } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt index e827025844..e313252940 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt @@ -24,19 +24,4 @@ interface ChatInterface { fun getInvites(getInvites: Chat.Params.GetInvites): Map fun getThreads(getThreads: Chat.Params.GetThreads): Map fun getMessages(getMessages: Chat.Params.GetMessages): List - /*** - TODO: Relay should be extracted to core along with websocket interface - interface Websocket { - val relay: Relay - - fun open(onError: (String) -> Unit) { - relay.connect { errorMessage -> onError(errorMessage) } - } - - fun close(onError: (String) -> Unit) { - relay.disconnect { errorMessage -> onError(errorMessage) } - } - } - ***/ - } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index 20e0177f62..b5f43a5480 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -1,17 +1,19 @@ package com.walletconnect.chat.client +import com.walletconnect.android.common.di.commonModule +import com.walletconnect.android.common.scope +import com.walletconnect.android.impl.di.cryptoModule +import com.walletconnect.android.impl.di.networkModule import com.walletconnect.chat.client.mapper.toClient import com.walletconnect.chat.client.mapper.toEngineDO import com.walletconnect.chat.client.mapper.toVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey -import com.walletconnect.chat.copiedFromSign.core.scope.scope -import com.walletconnect.chat.copiedFromSign.di.* import com.walletconnect.chat.core.model.vo.AccountIdVO import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO import com.walletconnect.chat.di.engineModule import com.walletconnect.chat.di.keyServerModule import com.walletconnect.chat.engine.domain.ChatEngine import com.walletconnect.chat.engine.model.EngineDO +import com.walletconnect.foundation.common.model.PublicKey import kotlinx.coroutines.launch import org.koin.android.ext.koin.androidContext import org.koin.core.KoinApplication @@ -19,7 +21,6 @@ import org.koin.core.KoinApplication internal class ChatProtocol : ChatInterface { private val wcKoinApp: KoinApplication = KoinApplication.init() private lateinit var chatEngine: ChatEngine -// val relay: Relay by lazy { wcKoinApp.koin.get() } //TODO: Figure out how to get relay as in Sign in here companion object { val instance = ChatProtocol() @@ -38,8 +39,8 @@ internal class ChatProtocol : ChatInterface { // networkModule(serverUrl, relay, connectionType.toRelayConnectionType()), //todo: add serverUrl as init param networkModule("serverUrl"), //TODO: refactor, network module should be initialized in RelayClient - relayerModule(), - storageModule(), +// relayerModule(), +// storageModule(), com.walletconnect.chat.di.storageModule(), // TODO: Refactor storage module into one engineModule() ) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/repository/BouncyCastleKeyManagementRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/BouncyCastleKeyManagementRepository.kt similarity index 79% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/repository/BouncyCastleKeyManagementRepository.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/BouncyCastleKeyManagementRepository.kt index d2bc5015ae..695f4527a4 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/repository/BouncyCastleKeyManagementRepository.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/BouncyCastleKeyManagementRepository.kt @@ -1,15 +1,14 @@ @file:JvmSynthetic -package com.walletconnect.chat.copiedFromSign.crypto.data.repository - -import com.walletconnect.chat.copiedFromSign.core.model.vo.PrivateKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.SymmetricKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.crypto.KeyManagementRepository -import com.walletconnect.chat.copiedFromSign.crypto.KeyStore -import com.walletconnect.chat.copiedFromSign.util.bytesToHex -import com.walletconnect.chat.copiedFromSign.util.hexToBytes +package com.walletconnect.chat.copiedFromSign + +import com.walletconnect.android.impl.common.model.SymmetricKey +import com.walletconnect.foundation.common.model.Key +import com.walletconnect.foundation.common.model.PrivateKey +import com.walletconnect.foundation.common.model.PublicKey +import com.walletconnect.foundation.common.model.Topic +import com.walletconnect.util.bytesToHex +import com.walletconnect.util.hexToBytes import org.bouncycastle.crypto.digests.SHA256Digest import org.bouncycastle.crypto.generators.HKDFBytesGenerator import org.bouncycastle.crypto.params.HKDFParameters @@ -17,22 +16,22 @@ import org.bouncycastle.math.ec.rfc7748.X25519 import java.security.MessageDigest import java.security.SecureRandom import javax.crypto.KeyGenerator -import com.walletconnect.chat.copiedFromSign.core.model.vo.Key as WCKey +//todo: use KeyChain from android_common internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStore) : KeyManagementRepository { - override fun generateSymmetricKey(topic: TopicVO): SymmetricKey { + override fun generateSymmetricKey(topic: Topic): SymmetricKey { val symmetricKey = createSymmetricKey().bytesToHex() keyChain.setSymmetricKey(topic.value, SymmetricKey(symmetricKey)) return SymmetricKey(symmetricKey) } - override fun setSymmetricKey(topic: TopicVO, symmetricKey: SymmetricKey) { + override fun setSymmetricKey(topic: Topic, symmetricKey: SymmetricKey) { keyChain.setSymmetricKey(topic.value, symmetricKey) } - override fun getSymmetricKey(topic: TopicVO): SymmetricKey { + override fun getSymmetricKey(topic: Topic): SymmetricKey { val symmetricKey = keyChain.getSymmetricKey(topic.value) return SymmetricKey(symmetricKey) @@ -67,7 +66,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } } - override fun getKeyAgreement(topic: TopicVO): Pair { + override fun getKeyAgreement(topic: Topic): Pair { val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" val (selfPublic, peerPublic) = keyChain.getKeys(tag) @@ -75,7 +74,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } // Added with Chat SDK - override fun setKeyAgreement(topic: TopicVO, self: PublicKey, peer: PublicKey) { + override fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) { val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" keyChain.setKeys(tag, self, peer) } @@ -84,8 +83,8 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor keyChain.setKeys(publicKey.keyAsHex, publicKey, privateKey) } - internal fun getKeyPair(wcKey: WCKey): Pair { - val (publicKeyHex, privateKeyHex) = keyChain.getKeys(wcKey.keyAsHex) + internal fun getKeyPair(key: Key): Pair { + val (publicKeyHex, privateKeyHex) = keyChain.getKeys(key.keyAsHex) return Pair(PublicKey(publicKeyHex), PrivateKey(privateKeyHex)) } @@ -144,7 +143,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } // Added with Chat SDK - override fun setInviteSelfPublicKey(topic: TopicVO, publicKey: PublicKey) { + override fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) { keyChain.setInviteSelfPublicKey(SELF_INVITE_PUBLIC_KEY, publicKey) keyChain.setPublicKey("$INVITE_CONTEXT${topic.value}", publicKey) } @@ -160,7 +159,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } // Added with Chat SDK - override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): TopicVO { + override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic { val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer) val topic = generateTopicFromSymmetricKey(symmetricKey) setKeyAgreement(topic, self, peer) @@ -168,8 +167,8 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } // Added with Chat SDK - private fun generateTopicFromSymmetricKey(symmetricKey: SymmetricKey): TopicVO { - val topic = TopicVO(sha256(symmetricKey.keyAsHex)) + private fun generateTopicFromSymmetricKey(symmetricKey: SymmetricKey): Topic { + val topic = Topic(sha256(symmetricKey.keyAsHex)) keyChain.setSymmetricKey(topic.value.lowercase(), symmetricKey) return topic } @@ -179,5 +178,5 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor // Added with Chat SDK - override fun getInvitePublicKey(topic: TopicVO): PublicKey = PublicKey(keyChain.getPublicKey("$INVITE_CONTEXT${topic.value}")) + override fun getInvitePublicKey(topic: Topic): PublicKey = PublicKey(keyChain.getPublicKey("$INVITE_CONTEXT${topic.value}")) } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/JsonRpcMethod.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcMethod.kt similarity index 87% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/JsonRpcMethod.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcMethod.kt index 7f1b1c1307..6d74c1039d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/JsonRpcMethod.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcMethod.kt @@ -1,4 +1,4 @@ -package com.walletconnect.chat.copiedFromSign.json_rpc.model +package com.walletconnect.chat.copiedFromSign //TODO: Should there be a copy for every SDK with specific methods or one file with all methods. internal object JsonRpcMethod { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/data/JsonRpcSerializer.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcSerializer.kt similarity index 79% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/data/JsonRpcSerializer.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcSerializer.kt index 6788dc8f7b..b259993bf2 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/data/JsonRpcSerializer.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcSerializer.kt @@ -1,13 +1,10 @@ @file:JvmSynthetic -package com.walletconnect.chat.copiedFromSign.json_rpc.data +package com.walletconnect.chat.copiedFromSign import com.squareup.moshi.Moshi -import com.walletconnect.chat.copiedFromSign.core.model.type.ClientParams -import com.walletconnect.chat.copiedFromSign.core.model.type.SerializableJsonRpc -import com.walletconnect.chat.copiedFromSign.json_rpc.model.JsonRpcMethod -import com.walletconnect.chat.copiedFromSign.json_rpc.model.RelayerDO -import com.walletconnect.chat.copiedFromSign.util.Empty +import com.walletconnect.android.common.SerializableJsonRpc +import com.walletconnect.android.impl.common.model.type.ClientParams import com.walletconnect.chat.core.model.vo.clientsync.ChatRpcVO //TODO: Should there be a copy for every SDK with specific methods or one file with all methods. diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/keystore/KeyChain.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyChain.kt similarity index 83% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/keystore/KeyChain.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyChain.kt index cdefe0f708..c12a919d73 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/keystore/KeyChain.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyChain.kt @@ -1,15 +1,14 @@ @file:JvmSynthetic -package com.walletconnect.chat.copiedFromSign.crypto.data.keystore +package com.walletconnect.chat.copiedFromSign import android.content.SharedPreferences -import com.walletconnect.chat.copiedFromSign.core.model.vo.Key -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey -import com.walletconnect.chat.copiedFromSign.crypto.KeyStore -import com.walletconnect.chat.copiedFromSign.util.Empty -import com.walletconnect.chat.copiedFromSign.util.bytesToHex -import com.walletconnect.chat.copiedFromSign.util.hexToBytes +import com.walletconnect.foundation.common.model.Key +import com.walletconnect.util.Empty +import com.walletconnect.util.bytesToHex +import com.walletconnect.util.hexToBytes +//todo: use KeyChain from android_common internal class KeyChain(private val sharedPreferences: SharedPreferences) : KeyStore { override fun setSymmetricKey(tag: String, key: Key) { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt new file mode 100644 index 0000000000..fe344c7dee --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt @@ -0,0 +1,29 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.copiedFromSign + +import com.walletconnect.android.impl.common.model.SymmetricKey +import com.walletconnect.foundation.common.model.PrivateKey +import com.walletconnect.foundation.common.model.PublicKey +import com.walletconnect.foundation.common.model.Topic + +internal interface KeyManagementRepository { + fun generateSymmetricKey(topic: Topic): SymmetricKey + fun setSymmetricKey(topic: Topic, symmetricKey: SymmetricKey) + fun getSymmetricKey(topic: Topic): SymmetricKey + + fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey + fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic + fun getKeyAgreement(topic: Topic): Pair + fun generateKeyPair(): PublicKey + + fun removeKeys(tag: String) + + //Added with Chat SDK + fun generateInviteSelfKeyPair(): Pair + fun getInviteSelfPublicKey(): PublicKey + fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) + fun getHash(string: String): String + fun getInvitePublicKey(topic: Topic): PublicKey + fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) +} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyStore.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyStore.kt similarity index 73% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyStore.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyStore.kt index ffa5f60b86..8b1b13307a 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyStore.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyStore.kt @@ -1,9 +1,9 @@ @file:JvmSynthetic -package com.walletconnect.chat.copiedFromSign.crypto +package com.walletconnect.chat.copiedFromSign -import com.walletconnect.chat.copiedFromSign.core.model.vo.Key -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey +import com.walletconnect.foundation.common.model.Key +import com.walletconnect.foundation.common.model.PublicKey internal interface KeyStore { fun setSymmetricKey(tag: String, key: Key) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/RelayDOJsonRpcResultJsonAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/RelayDOJsonRpcResultJsonAdapter.kt similarity index 97% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/RelayDOJsonRpcResultJsonAdapter.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/RelayDOJsonRpcResultJsonAdapter.kt index 81861d1ce9..a8cbea6c9c 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/RelayDOJsonRpcResultJsonAdapter.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/RelayDOJsonRpcResultJsonAdapter.kt @@ -1,13 +1,12 @@ @file:JvmSynthetic -package com.walletconnect.chat.copiedFromSign.core.adapters +package com.walletconnect.chat.copiedFromSign import com.squareup.moshi.JsonAdapter import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import com.squareup.moshi.Moshi import com.squareup.moshi.internal.Util -import com.walletconnect.chat.copiedFromSign.json_rpc.model.RelayerDO import com.walletconnect.chat.core.model.vo.clientsync.params.ChatParamsVO import org.json.JSONArray import org.json.JSONObject diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/ExpiryAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/ExpiryAdapter.kt deleted file mode 100644 index 68841fe710..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/ExpiryAdapter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.adapters - -import com.squareup.moshi.* -import com.walletconnect.chat.copiedFromSign.core.model.vo.ExpiryVO - -internal object ExpiryAdapter: JsonAdapter() { - - @JvmSynthetic - @FromJson - @Qualifier - override fun fromJson(reader: JsonReader): ExpiryVO? { - reader.isLenient = true - var seconds: Long? = null - - if (reader.hasNext() && reader.peek() == JsonReader.Token.NUMBER) { - seconds = reader.nextLong() - } - - return if (seconds != null) { - ExpiryVO(seconds) - } else { - null - } - } - - @JvmSynthetic - @ToJson - override fun toJson(writer: JsonWriter, @Qualifier value: ExpiryVO?) { - if (value != null) { - writer.value(value.seconds) - } else { - writer.value(0) - } - } - - @Retention(AnnotationRetention.RUNTIME) - @JsonQualifier - internal annotation class Qualifier -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/JSONObjectAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/JSONObjectAdapter.kt deleted file mode 100644 index f3fc07e74c..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/JSONObjectAdapter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.adapters - -import com.squareup.moshi.* -import okio.Buffer -import org.json.JSONException -import org.json.JSONObject - -internal object JSONObjectAdapter: JsonAdapter() { - - @JvmSynthetic - @FromJson - @Qualifier - override fun fromJson(reader: JsonReader): JSONObject? { - // Here we're expecting the JSON object, it is processed as Map by Moshi - return (reader.readJsonValue() as? Map)?.let { data -> - try { - JSONObject(data) - } catch (e: JSONException) { - // Handle error if arises - JSONObject("") - } - } - } - - @JvmSynthetic - @ToJson - override fun toJson(writer: JsonWriter, @Qualifier value: JSONObject?) { - value?.let { writer.value(Buffer().writeUtf8(value.toString())) } - } - - @Retention(AnnotationRetention.RUNTIME) - @JsonQualifier - annotation class Qualifier -} diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/SubscriptionIdAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/SubscriptionIdAdapter.kt deleted file mode 100644 index e150b4e5fa..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/SubscriptionIdAdapter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.adapters - -import com.squareup.moshi.* -import com.walletconnect.chat.copiedFromSign.core.model.vo.SubscriptionIdVO - -internal object SubscriptionIdAdapter: JsonAdapter() { - - @JvmSynthetic - @FromJson - @Qualifier - override fun fromJson(reader: JsonReader): SubscriptionIdVO? { - reader.isLenient = true - var subscriptionId: String? = null - - if (reader.hasNext() && reader.peek() == JsonReader.Token.STRING) { - subscriptionId = reader.nextString() - } - - return if (subscriptionId != null) { - SubscriptionIdVO(subscriptionId) - } else { - null - } - } - - @JvmSynthetic - @ToJson - override fun toJson(writer: JsonWriter, @Qualifier value: SubscriptionIdVO?) { - if (value != null) { - writer.value(value.id) - } else { - writer.value("") - } - } - - @Retention(AnnotationRetention.RUNTIME) - @JsonQualifier - annotation class Qualifier -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TopicAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TopicAdapter.kt deleted file mode 100644 index 393bd3749b..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TopicAdapter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.adapters - -import com.squareup.moshi.* -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO - -internal object TopicAdapter: JsonAdapter() { - - @JvmSynthetic - @FromJson - @Qualifier - override fun fromJson(reader: JsonReader): TopicVO? { - reader.isLenient = true - var topicValue: String? = null - - if (reader.hasNext() && reader.peek() == JsonReader.Token.STRING) { - topicValue = reader.nextString() - } - - return if (topicValue != null) { - TopicVO(topicValue) - } else { - null - } - } - - @JvmSynthetic - @ToJson - override fun toJson(writer: JsonWriter, @Qualifier value: TopicVO?) { - if (value != null) { - writer.value(value.value) - } else { - writer.value("") - } - } - - @Retention(AnnotationRetention.RUNTIME) - @JsonQualifier - annotation class Qualifier -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TtlAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TtlAdapter.kt deleted file mode 100644 index 8fcb7dfebb..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/adapters/TtlAdapter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.adapters - -import com.squareup.moshi.* -import com.walletconnect.chat.copiedFromSign.core.model.vo.TtlVO - -internal object TtlAdapter : JsonAdapter() { - - @JvmSynthetic - @FromJson - @Qualifier - override fun fromJson(reader: JsonReader): TtlVO? { - reader.isLenient = true - var seconds: Long? = null - - if (reader.hasNext() && reader.peek() == JsonReader.Token.NUMBER) { - seconds = reader.nextLong() - } - - return if (seconds != null) { - TtlVO(seconds) - } else { - null - } - } - - @JvmSynthetic - @ToJson - override fun toJson(writer: JsonWriter, @Qualifier value: TtlVO?) { - if (value != null) { - writer.value(value.seconds) - } else { - writer.value(0) - } - } - - @Retention(AnnotationRetention.RUNTIME) - @JsonQualifier - annotation class Qualifier -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/Messages.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/Messages.kt deleted file mode 100644 index bb8a540788..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/Messages.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.exceptions - -internal const val NO_SEQUENCE_FOR_TOPIC_MESSAGE: String = "Cannot find sequence for given topic: " -internal const val PAIRING_NOW_ALLOWED_MESSAGE: String = "Pair with existing pairing is not allowed" -internal const val UNAUTHORIZED_UPDATE_MESSAGE: String = - "The update() was called by the unauthorized peer. Must be called by controller client." -internal const val UNAUTHORIZED_EXTEND_MESSAGE: String = - "The extend() was called by the unauthorized peer. Must be called by controller client." -internal const val UNAUTHORIZED_EMIT_MESSAGE: String = - "The emit() was called by the unauthorized peer. Must be called by controller client." -internal const val SESSION_IS_NOT_ACKNOWLEDGED_MESSAGE: String = "Session is not acknowledged, topic: " - -internal const val NAMESPACE_CHAINS_MISSING_MESSAGE: String = "Chains must not be empty" -internal const val NAMESPACE_CHAINS_CAIP_2_MESSAGE: String = "Chains must be CAIP-2 compliant" -internal const val NAMESPACE_CHAINS_WRONG_NAMESPACE_MESSAGE: String = "Chains must be defined in matching namespace" -internal const val NAMESPACE_EXTENSION_CHAINS_MISSING_MESSAGE: String = "Extension chains must not be empty" -internal const val NAMESPACE_KEYS_CAIP_2_MESSAGE: String = "Namespace formatting must match CAIP-2" - -internal const val NAMESPACE_MISSING_PROPOSAL_MESSAGE: String = "No proposal for Session Namespace" -internal const val NAMESPACE_ACCOUNTS_MISSING_MESSAGE: String = "Accounts must not be empty" -internal const val NAMESPACE_ACCOUNTS_CAIP_10_MESSAGE: String = "Accounts must be CAIP-10 compliant" -internal const val NAMESPACE_METHODS_MISSING_MESSAGE: String = "All methods must be approved" -internal const val NAMESPACE_EVENTS_MISSING_MESSAGE: String = "All events must be approved" -internal const val NAMESPACE_ACCOUNTS_MISSING_FOR_CHAINS_MESSAGE: String = "All chains must have at least one account" -internal const val NAMESPACE_ACCOUNTS_WRONG_NAMESPACE_MESSAGE: String = "Accounts must be defined in matching namespace" -internal const val NAMESPACE_EXTENSION_ACCOUNTS_MISSING_MESSAGE: String = "Extension accounts must not be empty" -internal const val NAMESPACE_KEYS_MISSING_MESSAGE: String = "All namespaces must be approved" - -internal const val UNAUTHORIZED_METHOD_MESSAGE: String = "Unauthorized method is not authorized for given chain" -internal const val UNAUTHORIZED_EVENT_MESSAGE: String = "Unauthorized event is not authorized for given chain" -internal const val INVALID_EVENT_MESSAGE: String = "Event name and data fields cannot be empty. ChainId must be CAIP-2 compliant" -internal const val INVALID_REQUEST_MESSAGE: String = "Request topic, method and params fields cannot be empty. ChainId must be CAIP-2 compliant" -internal const val MALFORMED_PAIRING_URI_MESSAGE: String = "Pairing URI string is invalid." -internal const val INVALID_EXTEND_TIME: String = "Extend time is out of range" -internal const val NO_SESSION_PROPOSAL: String = "No session proposal for proposer publicKey: " - -internal const val WRONG_CONNECTION_TYPE: String = "Wrong connection type. Please, choose manual connection on initialisation." -internal const val DISCONNECT_MESSAGE: String = "User disconnected" \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/client/ClientExceptions.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/client/ClientExceptions.kt deleted file mode 100644 index 5feb9f830e..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/client/ClientExceptions.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.exceptions.client - -import com.walletconnect.android.exception.WalletConnectException - -//sealed class WalletConnectException(override val message: String?) : Exception(message) { -// class GenericException(override val message: String?) : WalletConnectException(message) -// class InternalError(override val message: String?): WalletConnectException(message) - - class UnauthorizedPeerException(override val message: String?) : WalletConnectException(message) - class UnauthorizedMethodException(override val message: String?) : WalletConnectException(message) - class UnauthorizedEventException(override val message: String?) : WalletConnectException(message) - - class InvalidNamespaceException(override val message: String?) : WalletConnectException(message) - class InvalidProjectIdException(override val message: String?) : WalletConnectException(message) - class InvalidEventException(override val message: String?) : WalletConnectException(message) - class InvalidRequestException(override val message: String?) : WalletConnectException(message) - - class ProjectIdDoesNotExistException(override val message: String?) : WalletConnectException(message) - class MalformedWalletConnectUri(override val message: String?) : WalletConnectException(message) - class NotSettledSessionException(override val message: String?) : WalletConnectException(message) - class CannotFindSequenceForTopic(override val message: String?) : WalletConnectException(message) - class PairWithExistingPairingIsNotAllowed(override val message: String?) : WalletConnectException(message) - class CannotFindSessionProposalException(override val message: String?) : WalletConnectException(message) - class MissingInternetConnectionException(override val message: String?) : WalletConnectException(message) - -// class UnknownEnvelopeTypeException(override val message: String?) : WalletConnectException(message) -// class MissingParticipantsException(override val message: String?) : WalletConnectException(message) -// class MissingReceiverPublicKeyException(override val message: String?) : WalletConnectException(message) -////} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerError.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerError.kt deleted file mode 100644 index dd948a79ed..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerError.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.exceptions.peer - -internal sealed class PeerError { - abstract val message: String - abstract val code: Int - - //Validation errors - - data class InvalidMethod(val reason: String) : PeerError() { - override val message: String = "Invalid session request: $reason" - override val code: Int = 1001 - } - - data class InvalidEvent(val reason: String) : PeerError() { - override val message: String = "Invalid event request: $reason" - override val code: Int = 1002 - } - - data class InvalidUpdateRequest(val reason: String) : PeerError() { - override val message: String = "Invalid update namespace request: $reason" - override val code: Int = 1003 - } - - data class InvalidExtendRequest(val reason: String) : PeerError() { - override val message = "Invalid session extend request: $reason" - override val code: Int = 1004 - } - - //Authorization errors - - data class UnauthorizedMethod(val reason: String) : PeerError() { - override val message: String = "Unauthorized session request: $reason" - override val code: Int = 3001 - } - - data class UnauthorizedEvent(val reason: String) : PeerError() { - override val message: String = "Unauthorized event request: $reason" - override val code: Int = 3002 - } - - data class UnauthorizedUpdateRequest(val sequence: String) : PeerError() { - override val message: String = "Unauthorized update $sequence namespace request" - override val code: Int = 3003 - } - - data class UnauthorizedExtendRequest(val sequence: String) : PeerError() { - override val message: String = "Unauthorized $sequence extend request" - override val code: Int = 3004 - } - - data class UnauthorizedEventEmit(val sequence: String) : PeerError() { - override val message: String = "Unauthorized $sequence event emit" - override val code: Int = 3006 - } - - //Rejected errors - - data class UserRejected(override val message: String) : PeerError() { - override val code: Int = 5000 - } - - data class UserRejectedChains(override val message: String) : PeerError() { - override val code: Int = 5001 - } - - data class UserRejectedMethods(override val message: String) : PeerError() { - override val code: Int = 5002 - } - - data class UserRejectedEvents(override val message: String) : PeerError() { - override val code: Int = 5003 - } - - //Uncategorized errors - - data class NoMatchingTopic(val sequence: String, val topic: String) : PeerError() { - override val message: String = "No matching $sequence with topic: $topic" - override val code: Int = 1301 - } - - data class SessionSettlementFailed(val reason: String) : PeerError() { - override val message: String = "Invalid Session Settle Request: $reason" - override val code: Int = 7000 - } - - data class Error(val reason: String, val errorCode: Int) : PeerError() { - override val message: String = reason - override val code: Int = errorCode - } - - //Namespaces validation - - data class UnsupportedNamespaceKey(override val message: String) : PeerError() { - override val code: Int = 5104 - } - - data class UnsupportedChains(override val message: String) : PeerError() { - override val code: Int = 5100 - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerReason.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerReason.kt deleted file mode 100644 index 1908d65030..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/peer/PeerReason.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.exceptions.peer - -import com.walletconnect.chat.copiedFromSign.core.exceptions.DISCONNECT_MESSAGE - -internal sealed class PeerReason { - abstract val message: String - abstract val code: Int - - - object UserDisconnected : PeerError() { - override val message: String = DISCONNECT_MESSAGE - override val code: Int = 6000 - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/client/Relay.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/client/Relay.kt deleted file mode 100644 index b35de8790e..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/client/Relay.kt +++ /dev/null @@ -1,162 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.client - -import com.walletconnect.chat.copiedFromSign.network.model.IRN_PUBLISH -import com.walletconnect.chat.copiedFromSign.network.model.IRN_SUBSCRIBE -import com.walletconnect.chat.copiedFromSign.network.model.IRN_SUBSCRIPTION -import com.walletconnect.chat.copiedFromSign.network.model.IRN_UNSUBSCRIBE - - -object Relay { - sealed class Model { - sealed class Call : Relay.Model() { - abstract val id: Long - abstract val jsonrpc: String - - sealed class Publish : Call() { - - data class Request( - override val id: Long, - override val jsonrpc: String = "2.0", - val method: String = IRN_PUBLISH, - val params: Params, - ) : Publish() { - - data class Params( - val topic: String, - val message: String, - val ttl: Long, - val tag: Int, - val prompt: Boolean?, - ) - } - - data class Acknowledgement( - override val id: Long, - override val jsonrpc: String = "2.0", - val result: Boolean, - ) : Publish() - - data class JsonRpcError( - override val jsonrpc: String = "2.0", - val error: Error, - override val id: Long, - ) : Publish() - } - - sealed class Subscribe : Call() { - - data class Request( - override val id: Long, - override val jsonrpc: String = "2.0", - val method: String = IRN_SUBSCRIBE, - val params: Params, - ) : Subscribe() { - - data class Params( - val topic: String, - ) - } - - data class Acknowledgement( - override val id: Long, - override val jsonrpc: String = "2.0", - val result: String, - ) : Subscribe() - - data class JsonRpcError( - override val jsonrpc: String = "2.0", - val error: Error, - override val id: Long, - ) : Subscribe() - } - - sealed class Subscription : Call() { - - data class Request( - override val id: Long, - override val jsonrpc: String = "2.0", - val method: String = IRN_SUBSCRIPTION, - val params: Params, - ) : Subscription() { - - val subscriptionTopic: String = params.subscriptionData.topic - val message: String = params.subscriptionData.message - - data class Params( - val subscriptionId: String, - val subscriptionData: SubscriptionData, - ) { - - data class SubscriptionData( - val topic: String, - val message: String, - ) - } - } - - data class Acknowledgement( - override val id: Long, - override val jsonrpc: String = "2.0", - val result: Boolean, - ) : Subscription() - - data class JsonRpcError( - override val jsonrpc: String = "2.0", - val error: Error, - override val id: Long, - ) : Subscription() - } - - sealed class Unsubscribe : Call() { - - data class Request( - override val id: Long, - override val jsonrpc: String = "2.0", - val method: String = IRN_UNSUBSCRIBE, - val params: Params, - ) : Unsubscribe() { - - data class Params( - val topic: String, - val subscriptionId: String, - ) - } - - data class Acknowledgement( - override val id: Long, - override val jsonrpc: String = "2.0", - val result: Boolean, - ) : Unsubscribe() - - data class JsonRpcError( - override val jsonrpc: String = "2.0", - val error: Error, - override val id: Long, - ) : Unsubscribe() - } - } - - data class Error( - val code: Long, - val message: String, - ) : Relay.Model() { - val errorMessage: String = "Error code: $code; Error message: $message" - } - - sealed class Event : Relay.Model() { - data class OnConnectionOpened(val webSocket: WEB_SOCKET) : Event() - data class OnMessageReceived(val message: Message) : Event() - data class OnConnectionClosing(val shutdownReason: ShutdownReason) : Event() - data class OnConnectionClosed(val shutdownReason: ShutdownReason) : Event() - data class OnConnectionFailed(val throwable: Throwable) : Event() - } - - sealed class Message : Relay.Model() { - data class Text(val value: String) : Message() - class Bytes(val value: ByteArray) : Message() - } - - data class ShutdownReason(val code: Int, val reason: String) : Relay.Model() - data class IrnParams(val tag: Int, val ttl: Long, val prompt: Boolean = false) : Relay.Model() - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/ClientParams.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/ClientParams.kt deleted file mode 100644 index 5676645811..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/ClientParams.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.type - -internal interface ClientParams : SerializableJsonRpc \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/JsonRpcClientSync.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/JsonRpcClientSync.kt deleted file mode 100644 index 4e86d20713..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/JsonRpcClientSync.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.type - -internal interface JsonRpcClientSync : SerializableJsonRpc { - val id: Long - val method: String - val jsonrpc: String - val params: T -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/SerializableJsonRpc.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/SerializableJsonRpc.kt deleted file mode 100644 index 078da6e104..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/SerializableJsonRpc.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.type - -internal interface SerializableJsonRpc \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/enums/EnvelopeType.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/enums/EnvelopeType.kt deleted file mode 100644 index 53ac3cb11a..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/type/enums/EnvelopeType.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.type.enums - -internal enum class EnvelopeType(val id: Byte) { - ZERO(0), ONE(1) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/CommonObjects.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/CommonObjects.kt deleted file mode 100644 index 4f221f2c34..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/CommonObjects.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.vo - -// TODO: Look into finding a way to convert these into value classes and still have Moshi deserialize them without adding property inside JSON object -internal data class TopicVO(val value: String) - -internal data class TtlVO(val seconds: Long) - -internal data class ExpiryVO(val seconds: Long) - -internal data class SubscriptionIdVO(val id: String) - -@JvmInline -internal value class SymmetricKey(override val keyAsHex: String) : Key - -@JvmInline -internal value class PublicKey(override val keyAsHex: String) : Key - -@JvmInline -internal value class PrivateKey(override val keyAsHex: String) : Key - -internal interface Key { - val keyAsHex: String -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/IriudiumParamsVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/IriudiumParamsVO.kt deleted file mode 100644 index 7d4ff8a388..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/IriudiumParamsVO.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.vo - -import com.walletconnect.chat.core.model.vo.Tags - -internal data class IrnParamsVO(val tag: Tags, val ttl: TtlVO, val prompt: Boolean = false) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcHistoryVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcHistoryVO.kt deleted file mode 100644 index d5b7aa20a3..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcHistoryVO.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc - -data class JsonRpcHistoryVO( - val requestId: Long, - val topic: String, - val method: String, - val body: String, - val response: String?, -) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcResponseVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcResponseVO.kt deleted file mode 100644 index c8fe7c3603..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/jsonRpc/JsonRpcResponseVO.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc - -import com.squareup.moshi.JsonClass - -internal sealed class JsonRpcResponseVO { - abstract val id: Long - - @JsonClass(generateAdapter = true) - internal data class JsonRpcResult( - override val id: Long, - val jsonrpc: String = "2.0", - val result: Any, - ) : JsonRpcResponseVO() - - @JsonClass(generateAdapter = true) - internal data class JsonRpcError( - override val id: Long, - val jsonrpc: String = "2.0", - val error: Error, - ) : JsonRpcResponseVO() { - val errorMessage: String = "${error.message} : code: ${error.code}" - } - - internal data class Error( - val code: Int, - val message: String, - ) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/ParticipantsVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/ParticipantsVO.kt deleted file mode 100644 index 1d1a3a45aa..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/ParticipantsVO.kt +++ /dev/null @@ -1,10 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.core.model.vo.sync - -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey - -internal data class ParticipantsVO( - val senderPublicKey: PublicKey, - val receiverPublicKey: PublicKey, -) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/PendingRequestVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/PendingRequestVO.kt deleted file mode 100644 index 8341461b81..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/PendingRequestVO.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.vo.sync - -data class PendingRequestVO( - val requestId: Long, - val topic: String, - val method: String, - val chainId: String?, - val params: String -) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCRequestVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCRequestVO.kt deleted file mode 100644 index 8e699c3a89..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCRequestVO.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.vo.sync - -import com.walletconnect.chat.copiedFromSign.core.model.type.ClientParams -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO - -internal data class WCRequestVO( - val topic: TopicVO, - val id: Long, - val method: String, - val params: ClientParams -) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCResponseVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCResponseVO.kt deleted file mode 100644 index 389fd48b94..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/model/vo/sync/WCResponseVO.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.core.model.vo.sync - -import com.walletconnect.chat.copiedFromSign.core.model.type.ClientParams -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc.JsonRpcResponseVO - -internal data class WCResponseVO( - val topic: TopicVO, - val method: String, - val response: JsonRpcResponseVO, - val params: ClientParams, -) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/scope/WalletConnectScope.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/scope/WalletConnectScope.kt deleted file mode 100644 index c03c83dde4..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/scope/WalletConnectScope.kt +++ /dev/null @@ -1,15 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.core.scope - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob - -// TODO: This should be extracted to core - -private val job = SupervisorJob() - -@get:JvmSynthetic -internal var scope = CoroutineScope(job + Dispatchers.IO) - diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/utils/Time.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/utils/Time.kt deleted file mode 100644 index ba7062466d..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/utils/Time.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.walletconnect.sign.core.model.utils - -import java.util.concurrent.TimeUnit - -object Time { - val currentTimeInSeconds: Long = System.currentTimeMillis() / 1000 - val thirtySeconds: Long = TimeUnit.SECONDS.convert(30, TimeUnit.SECONDS) - val fiveMinutesInSeconds: Long = TimeUnit.SECONDS.convert(5, TimeUnit.MINUTES) - val dayInSeconds: Long = TimeUnit.SECONDS.convert(1, TimeUnit.DAYS) - val weekInSeconds: Long = TimeUnit.SECONDS.convert(7, TimeUnit.DAYS) - val monthInSeconds: Long = TimeUnit.SECONDS.convert(30, TimeUnit.DAYS) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/Codec.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/Codec.kt deleted file mode 100644 index 8af8969013..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/Codec.kt +++ /dev/null @@ -1,12 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.crypto - -import com.walletconnect.chat.copiedFromSign.core.model.type.enums.EnvelopeType -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.ParticipantsVO - -internal interface Codec { - fun encrypt(topic: TopicVO, payload: String, envelopeType: EnvelopeType, participants: ParticipantsVO? = null): String - fun decrypt(topic: TopicVO, cipherText: String): String -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyManagementRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyManagementRepository.kt deleted file mode 100644 index 4c5efc75e5..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyManagementRepository.kt +++ /dev/null @@ -1,29 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.crypto - -import com.walletconnect.chat.copiedFromSign.core.model.vo.PrivateKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.SymmetricKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO - -internal interface KeyManagementRepository { - fun generateSymmetricKey(topic: TopicVO): SymmetricKey - fun setSymmetricKey(topic: TopicVO, symmetricKey: SymmetricKey) - fun getSymmetricKey(topic: TopicVO): SymmetricKey - - fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey - fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): TopicVO - fun getKeyAgreement(topic: TopicVO): Pair - fun generateKeyPair(): PublicKey - - fun removeKeys(tag: String) - - //Added with Chat SDK - fun generateInviteSelfKeyPair(): Pair - fun getInviteSelfPublicKey(): PublicKey - fun setInviteSelfPublicKey(topic: TopicVO, publicKey: PublicKey) - fun getHash(string: String): String - fun getInvitePublicKey(topic: TopicVO): PublicKey - fun setKeyAgreement(topic: TopicVO, self: PublicKey, peer: PublicKey) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/codec/ChaChaPolyCodec.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/codec/ChaChaPolyCodec.kt deleted file mode 100644 index fecec83e32..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/data/codec/ChaChaPolyCodec.kt +++ /dev/null @@ -1,161 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.crypto.data.codec - -import com.walletconnect.android.impl.common.MissingParticipantsException -import com.walletconnect.android.impl.common.MissingReceiverPublicKeyException -import com.walletconnect.android.impl.common.UnknownEnvelopeTypeException -import com.walletconnect.chat.copiedFromSign.core.model.type.enums.EnvelopeType -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.SymmetricKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.ParticipantsVO -import com.walletconnect.chat.copiedFromSign.crypto.Codec -import com.walletconnect.chat.copiedFromSign.crypto.KeyManagementRepository -import com.walletconnect.chat.copiedFromSign.util.bytesToHex -import com.walletconnect.chat.copiedFromSign.util.hexToBytes -import com.walletconnect.chat.copiedFromSign.util.randomBytes -import org.bouncycastle.crypto.modes.ChaCha20Poly1305 -import org.bouncycastle.crypto.params.KeyParameter -import org.bouncycastle.crypto.params.ParametersWithIV -import org.bouncycastle.util.encoders.Base64 -import java.nio.ByteBuffer - -/* Note: -* The cha20Poly1305.init() throws InvalidArgumentException in the debugging mode code but it doesn't affects the final method execution -* EnvelopeType.ZERO -> tp + iv + sb -* EnvelopeType.ONE -> tp + pk + iv + sb - */ - -internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagementRepository) : Codec { - - private val cha20Poly1305 = ChaCha20Poly1305() - - @Throws( - UnknownEnvelopeTypeException::class, - MissingParticipantsException::class - ) - override fun encrypt(topic: TopicVO, jsonRpcPayload: String, envelopeType: EnvelopeType, participants: ParticipantsVO?): String { - val input = jsonRpcPayload.toByteArray(Charsets.UTF_8) - val nonceBytes = randomBytes(NONCE_SIZE) - - return when (envelopeType.id) { - EnvelopeType.ZERO.id -> encryptEnvelopeType0(topic, nonceBytes, input, envelopeType) - EnvelopeType.ONE.id -> encryptEnvelopeType1(participants, nonceBytes, input, envelopeType) - else -> throw UnknownEnvelopeTypeException("Unknown envelope type: ${envelopeType.id}") - } - } - - @Throws( - UnknownEnvelopeTypeException::class, - MissingReceiverPublicKeyException::class - ) - override fun decrypt(topic: TopicVO, encryptedPayload: String): String { - val encryptedPayloadBytes = Base64.decode(encryptedPayload) - - return when (val envelopeType = encryptedPayloadBytes.envelopeType) { - EnvelopeType.ZERO.id -> decryptType0(topic, encryptedPayloadBytes) - EnvelopeType.ONE.id -> decryptType1(encryptedPayloadBytes, keyManagementRepository.getInvitePublicKey(topic)) - else -> throw UnknownEnvelopeTypeException("Unknown envelope type: $envelopeType") - } - } - - private fun decryptType0(topic: TopicVO, encryptedPayloadBytes: ByteArray): String { - val envelopeType = ByteArray(ENVELOPE_TYPE_SIZE) - val nonce = ByteArray(NONCE_SIZE) - val encryptedMessageBytes = ByteArray(encryptedPayloadBytes.size - NONCE_SIZE - ENVELOPE_TYPE_SIZE) - - //tp + iv + sb - val byteBuffer: ByteBuffer = ByteBuffer.wrap(encryptedPayloadBytes) - byteBuffer.get(envelopeType) - byteBuffer.get(nonce) - byteBuffer.get(encryptedMessageBytes) - - val symmetricKey = keyManagementRepository.getSymmetricKey(topic) - val decryptedTextBytes = decryptPayload(symmetricKey, nonce, encryptedMessageBytes) - - return String(decryptedTextBytes, Charsets.UTF_8) - } - - private fun decryptType1(encryptedPayloadBytes: ByteArray, receiverPublicKey: PublicKey?): String { - if (receiverPublicKey == null) throw MissingReceiverPublicKeyException("Missing receiver public key") - - val envelopeType = ByteArray(ENVELOPE_TYPE_SIZE) - val nonce = ByteArray(NONCE_SIZE) - val publicKey = ByteArray(KEY_SIZE) - val encryptedMessageBytes = ByteArray(encryptedPayloadBytes.size - NONCE_SIZE - KEY_SIZE - ENVELOPE_TYPE_SIZE) - - //tp + pk + iv + sb - val byteBuffer: ByteBuffer = ByteBuffer.wrap(encryptedPayloadBytes) - byteBuffer.get(envelopeType) - byteBuffer.get(publicKey) - byteBuffer.get(nonce) - byteBuffer.get(encryptedMessageBytes) - - val peer = PublicKey(publicKey.bytesToHex()) // PubKey Y - val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(receiverPublicKey, peer) - keyManagementRepository.setSymmetricKey(TopicVO(keyManagementRepository.getHash(receiverPublicKey.keyAsHex)), symmetricKey) - val decryptedTextBytes = decryptPayload(symmetricKey, nonce, encryptedMessageBytes) - - return String(decryptedTextBytes, Charsets.UTF_8) - } - - private fun encryptEnvelopeType0(topic: TopicVO, nonceBytes: ByteArray, input: ByteArray, envelopeType: EnvelopeType): String { - val symmetricKey = keyManagementRepository.getSymmetricKey(topic) - val cipherBytes = encryptPayload(symmetricKey, nonceBytes, input) - val payloadSize = cipherBytes.size + NONCE_SIZE + ENVELOPE_TYPE_SIZE - - //tp + iv + sb - val encryptedPayloadBytes = ByteBuffer.allocate(payloadSize) - .put(envelopeType.id).put(nonceBytes).put(cipherBytes) - .array() - - return Base64.toBase64String(encryptedPayloadBytes) - } - - private fun encryptEnvelopeType1( - participants: ParticipantsVO?, - nonceBytes: ByteArray, - input: ByteArray, - envelopeType: EnvelopeType, - ): String { - if (participants == null) throw MissingParticipantsException("Missing participants when encrypting envelope type 1") - val self = participants.senderPublicKey - val selfBytes = self.keyAsHex.hexToBytes() - val peer = participants.receiverPublicKey - val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(self, peer) - val cipherBytes = encryptPayload(symmetricKey, nonceBytes, input) - val payloadSize = cipherBytes.size + NONCE_SIZE + ENVELOPE_TYPE_SIZE + selfBytes.size - //tp + pk + iv + sb - val encryptedPayloadBytes = ByteBuffer.allocate(payloadSize) - .put(envelopeType.id).put(selfBytes).put(nonceBytes).put(cipherBytes) - .array() - - return Base64.toBase64String(encryptedPayloadBytes) - } - - private fun encryptPayload(key: SymmetricKey, nonce: ByteArray, input: ByteArray): ByteArray { - val params = ParametersWithIV(KeyParameter(key.keyAsHex.hexToBytes()), nonce) - cha20Poly1305.init(true, params) - val cipherBytes = ByteArray(cha20Poly1305.getOutputSize(input.size)) - val outputSize = cha20Poly1305.processBytes(input, 0, input.size, cipherBytes, 0) - cha20Poly1305.doFinal(cipherBytes, outputSize) - return cipherBytes - } - - private fun decryptPayload(key: SymmetricKey, nonce: ByteArray, input: ByteArray): ByteArray { - val params = ParametersWithIV(KeyParameter(key.keyAsHex.hexToBytes()), nonce) - cha20Poly1305.init(false, params) - val decryptedTextBytes = ByteArray(cha20Poly1305.getOutputSize(input.size)) - val outputSize = cha20Poly1305.processBytes(input, 0, input.size, decryptedTextBytes, 0) - cha20Poly1305.doFinal(decryptedTextBytes, outputSize) - return decryptedTextBytes - } - - private companion object { - const val NONCE_SIZE = 12 - const val KEY_SIZE = 32 - const val ENVELOPE_TYPE_SIZE = 1 - val ByteArray.envelopeType: Byte get() = this[0] - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CommonModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CommonModule.kt deleted file mode 100644 index 526bc14176..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CommonModule.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.di - -import com.squareup.moshi.Moshi -import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import com.tinder.scarlet.utils.getRawType -import com.walletconnect.chat.copiedFromSign.core.adapters.* -import com.walletconnect.chat.copiedFromSign.core.model.vo.SubscriptionIdVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TtlVO -import com.walletconnect.chat.copiedFromSign.json_rpc.model.RelayerDO -import org.json.JSONObject -import org.koin.dsl.module -import kotlin.reflect.jvm.jvmName - -@JvmSynthetic -internal fun commonModule() = module { - - single> { - PolymorphicJsonAdapterFactory.of(RelayerDO.JsonRpcResponse::class.java, "type") - .withSubtype(RelayerDO.JsonRpcResponse.JsonRpcResult::class.java, "result") - .withSubtype(RelayerDO.JsonRpcResponse.JsonRpcError::class.java, "error") - } - - single { - KotlinJsonAdapterFactory() - } - - single { - Moshi.Builder() - .addLast { type, _, moshi -> - when (type.getRawType().name) { -// ExpiryVO::class.jvmName -> ExpiryAdapter - JSONObject::class.jvmName -> JSONObjectAdapter - SubscriptionIdVO::class.jvmName -> SubscriptionIdAdapter - TopicVO::class.jvmName -> TopicAdapter - TtlVO::class.jvmName -> TtlAdapter -// SessionRequestVO::class.jvmName -> SessionRequestVOJsonAdapter(moshi) - RelayerDO.JsonRpcResponse.JsonRpcResult::class.jvmName -> RelayDOJsonRpcResultJsonAdapter(moshi) - else -> null - } - } - .addLast(get()) - .add(get>()) - .build() - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CryptoModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CryptoModule.kt deleted file mode 100644 index d5e7c96d8a..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/CryptoModule.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.di - -import androidx.security.crypto.EncryptedSharedPreferences -import androidx.security.crypto.MasterKeys -import com.walletconnect.chat.copiedFromSign.crypto.KeyManagementRepository -import com.walletconnect.chat.copiedFromSign.crypto.KeyStore -import com.walletconnect.chat.copiedFromSign.crypto.data.keystore.KeyChain -import com.walletconnect.chat.copiedFromSign.crypto.data.repository.BouncyCastleKeyManagementRepository -import org.koin.android.ext.koin.androidContext -import org.koin.core.qualifier.named -import org.koin.dsl.module - -@JvmSynthetic -internal fun cryptoModule() = module { - val sharedPrefsFile = "wc_key_store" - val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC - val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) - - single(named(DITags.KEY_STORE)) { - EncryptedSharedPreferences.create( - sharedPrefsFile, - mainKeyAlias, - androidContext(), - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM - ) - } - - single { KeyChain(get(named(DITags.KEY_STORE))) } - - single { BouncyCastleKeyManagementRepository(get()) } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/DITags.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/DITags.kt deleted file mode 100644 index b2201be5b8..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/DITags.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.di - -internal enum class DITags { - @JvmSynthetic KEY_STORE, - @JvmSynthetic RPC_STORE, - @JvmSynthetic RPC_STORE_ALIAS, - @JvmSynthetic DB_ALIAS, - @JvmSynthetic DB_KEY_STORAGE, - @JvmSynthetic DB_SECRET_KEY, - @JvmSynthetic DB_PASSPHRASE -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/NetworkModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/NetworkModule.kt deleted file mode 100644 index aa9169ed20..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/NetworkModule.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.di - -import com.tinder.scarlet.Scarlet -import com.tinder.scarlet.lifecycle.LifecycleRegistry -import com.tinder.scarlet.lifecycle.android.AndroidLifecycle -import com.tinder.scarlet.messageadapter.moshi.MoshiMessageAdapter -import com.tinder.scarlet.retry.LinearBackoffStrategy -import com.tinder.scarlet.websocket.okhttp.newWebSocketFactory -import com.walletconnect.chat.copiedFromSign.network.RelayInterface -import com.walletconnect.chat.copiedFromSign.network.adapter.FlowStreamAdapter -import com.walletconnect.chat.copiedFromSign.network.connection.ConnectionType -import com.walletconnect.chat.copiedFromSign.network.connection.controller.ConnectionController -import com.walletconnect.chat.copiedFromSign.network.connection.lifecycle.ManualConnectionLifecycle -import com.walletconnect.chat.copiedFromSign.network.domain.RelayClient -import com.walletconnect.chat.copiedFromSign.network.service.RelayService -import okhttp3.OkHttpClient -import org.koin.android.ext.koin.androidApplication -import org.koin.dsl.module -import java.util.concurrent.TimeUnit - -@JvmSynthetic -internal fun networkModule(serverUrl: String, connectionType: ConnectionType = ConnectionType.AUTOMATIC) = module { - val TIMEOUT_TIME = 5000L - val DEFAULT_BACKOFF_MINUTES = 5L - - single { MoshiMessageAdapter.Factory(get()) } - - single { FlowStreamAdapter.Factory() } - - single { - OkHttpClient.Builder() - .writeTimeout(TIMEOUT_TIME, TimeUnit.MILLISECONDS) - .readTimeout(TIMEOUT_TIME, TimeUnit.MILLISECONDS) - .callTimeout(TIMEOUT_TIME, TimeUnit.MILLISECONDS) - .connectTimeout(TIMEOUT_TIME, TimeUnit.MILLISECONDS) - .build() - } - - single { - if (connectionType == ConnectionType.MANUAL) { - ConnectionController.Manual() - } else { - ConnectionController.Automatic - } - } - - single { - if (connectionType == ConnectionType.MANUAL) { - ManualConnectionLifecycle(get(), LifecycleRegistry()) - } else { - AndroidLifecycle.ofApplicationForeground(androidApplication()) - } - } - - single { - Scarlet.Builder() - .backoffStrategy(LinearBackoffStrategy(TimeUnit.MINUTES.toMillis(DEFAULT_BACKOFF_MINUTES))) - .webSocketFactory(get().newWebSocketFactory(serverUrl)) - .lifecycle(get()) - .addMessageAdapterFactory(get()) - .addStreamAdapterFactory(get()) - .build() - } - - single { - get().create(RelayService::class.java) - } - -// single { relay ?: RelayClient(get(), get()) } -// TODO: Figure out how to get relay as in Sign in here - single { RelayClient(get(), get()) } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/RelayerModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/RelayerModule.kt deleted file mode 100644 index d959197e6f..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/RelayerModule.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.di - -import com.walletconnect.chat.copiedFromSign.crypto.Codec -import com.walletconnect.chat.copiedFromSign.crypto.data.codec.ChaChaPolyCodec -import com.walletconnect.chat.copiedFromSign.json_rpc.data.JsonRpcSerializer -import com.walletconnect.chat.copiedFromSign.json_rpc.domain.RelayerInteractor -import com.walletconnect.chat.copiedFromSign.util.NetworkState -import org.koin.dsl.module - -@JvmSynthetic -internal fun relayerModule() = module { - - single { - ChaChaPolyCodec(get()) - } - - single { - JsonRpcSerializer(get()) - } - - single { - NetworkState(get()) - } - - single { - RelayerInteractor(get(), get(), get(), get(), get()) - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/StorageModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/StorageModule.kt deleted file mode 100644 index 66f3f110bd..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/StorageModule.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.di - -import android.annotation.SuppressLint -import android.content.Context -import android.content.SharedPreferences -import com.squareup.sqldelight.ColumnAdapter -import com.squareup.sqldelight.android.AndroidSqliteDriver -import com.squareup.sqldelight.db.SqlDriver -import com.walletconnect.chat.Database -import com.walletconnect.chat.copiedFromSign.storage.JsonRpcHistory -import org.koin.android.ext.koin.androidContext -import org.koin.core.module.Module -import org.koin.core.qualifier.named -import org.koin.dsl.module - -@SuppressLint("HardwareIds") -@JvmSynthetic -internal fun storageModule(): Module = module { - - single(named(DITags.RPC_STORE)) { - val sharedPrefsFile = "wc_rpc_store" - - androidContext().getSharedPreferences(sharedPrefsFile, Context.MODE_PRIVATE) - } - - single, String>> { - object : ColumnAdapter, String> { - - override fun decode(databaseValue: String) = - if (databaseValue.isBlank()) { - listOf() - } else { - databaseValue.split(",") - } - - override fun encode(value: List) = value.joinToString(separator = ",") - } - } - - single { - AndroidSqliteDriver( - schema = Database.Schema, - context = androidContext(), - name = "WalletConnectV2.db" - ) - } - - single { - Database(get()) - } - - - single { - get().jsonRpcHistoryQueries - } - - single { - JsonRpcHistory(get(named(DITags.RPC_STORE)), get()) - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/domain/RelayerInteractor.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/domain/RelayerInteractor.kt deleted file mode 100644 index a85f63a078..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/domain/RelayerInteractor.kt +++ /dev/null @@ -1,282 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.json_rpc.domain - -import com.walletconnect.android.exception.GenericException -import com.walletconnect.android.exception.NoRelayConnectionException -import com.walletconnect.android.exception.WalletConnectException -import com.walletconnect.android.impl.utils.Logger -import com.walletconnect.chat.copiedFromSign.core.exceptions.client.InvalidProjectIdException -import com.walletconnect.chat.copiedFromSign.core.exceptions.client.ProjectIdDoesNotExistException -import com.walletconnect.chat.copiedFromSign.core.exceptions.peer.PeerError -import com.walletconnect.chat.copiedFromSign.core.model.client.Relay -import com.walletconnect.chat.copiedFromSign.core.model.type.ClientParams -import com.walletconnect.chat.copiedFromSign.core.model.type.JsonRpcClientSync -import com.walletconnect.chat.copiedFromSign.core.model.type.enums.EnvelopeType -import com.walletconnect.chat.copiedFromSign.core.model.vo.IrnParamsVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.SubscriptionIdVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc.JsonRpcResponseVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.ParticipantsVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.WCRequestVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.WCResponseVO -import com.walletconnect.chat.copiedFromSign.core.scope.scope -import com.walletconnect.chat.copiedFromSign.crypto.Codec -import com.walletconnect.chat.copiedFromSign.json_rpc.data.JsonRpcSerializer -import com.walletconnect.chat.copiedFromSign.json_rpc.model.* -import com.walletconnect.chat.copiedFromSign.network.RelayInterface -import com.walletconnect.chat.copiedFromSign.util.Empty -import com.walletconnect.chat.copiedFromSign.util.NetworkState -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import java.net.HttpURLConnection - -//todo: extract Relay to core module. Consider what is the best place for RelayerInteractor (sdk or core module)? -internal class RelayerInteractor( - private val relay: RelayInterface, - private val serializer: JsonRpcSerializer, - private val chaChaPolyCodec: Codec, - private val jsonRpcHistory: com.walletconnect.chat.copiedFromSign.storage.JsonRpcHistory, - networkState: NetworkState, //todo: move to the RelayClient? -) { - private val _clientSyncJsonRpc: MutableSharedFlow = MutableSharedFlow() - val clientSyncJsonRpc: SharedFlow = _clientSyncJsonRpc.asSharedFlow() - - private val _peerResponse: MutableSharedFlow = MutableSharedFlow() - val peerResponse: SharedFlow = _peerResponse.asSharedFlow() - - private val _internalErrors = MutableSharedFlow() - val internalErrors: SharedFlow = _internalErrors.asSharedFlow() - - private val _isNetworkAvailable: StateFlow = networkState.isAvailable - private val _isWSSConnectionOpened: MutableStateFlow = MutableStateFlow(false) - - val isConnectionAvailable: StateFlow = - combine(_isWSSConnectionOpened, _isNetworkAvailable) { wss, internet -> wss && internet } - .stateIn(scope, SharingStarted.Eagerly, false) - - private val subscriptions: MutableMap = mutableMapOf() - private val exceptionHandler = CoroutineExceptionHandler { _, exception -> handleError(exception.message ?: String.Empty) } - - init { - manageSubscriptions() - } - - @get:JvmSynthetic - private val Throwable.toWalletConnectException: WalletConnectException - get() = - when { - this.message?.contains(HttpURLConnection.HTTP_UNAUTHORIZED.toString()) == true -> - ProjectIdDoesNotExistException(this.message) - this.message?.contains(HttpURLConnection.HTTP_FORBIDDEN.toString()) == true -> - InvalidProjectIdException(this.message) - else -> GenericException(this.message) - } - - - val initializationErrorsFlow: Flow - get() = relay.eventsFlow - .onEach { event: Relay.Model.Event -> - setIsWSSConnectionOpened(event) - } - .filterIsInstance() - .map { error -> error.throwable.toWalletConnectException } - - init { - manageSubscriptions() - } - - internal fun checkConnectionWorking() { - if (!isConnectionAvailable.value) { - throw NoRelayConnectionException("No connection available") - } - } - - internal fun publishJsonRpcRequests( - topic: TopicVO, - params: IrnParamsVO, - payload: JsonRpcClientSync<*>, - envelopeType: EnvelopeType, - onSuccess: () -> Unit = {}, - onFailure: (Throwable) -> Unit = {}, - participantsVO: ParticipantsVO? = null, - ) { - val requestJson = serializer.serialize(payload) - - if (jsonRpcHistory.setRequest(payload.id, topic, payload.method, requestJson)) { - val encryptedRequest = chaChaPolyCodec.encrypt(topic, requestJson, envelopeType, participantsVO) - - relay.publish(topic.value, encryptedRequest, params.toRelay()) { result -> - result.fold( - onSuccess = { onSuccess() }, - onFailure = { error -> onFailure(error) } - ) - } - } - } - - internal fun publishJsonRpcResponse( - topic: TopicVO, - params: IrnParamsVO, - response: JsonRpcResponseVO, - envelopeType: EnvelopeType, - onSuccess: () -> Unit = {}, - onFailure: (Throwable) -> Unit = {}, - ) { - val jsonResponseDO = response.toRelayerDOJsonRpcResponse() - val responseJson = serializer.serialize(jsonResponseDO) - val encryptedResponse = chaChaPolyCodec.encrypt(topic, responseJson, envelopeType) - - relay.publish(topic.value, encryptedResponse, params.toRelay()) { result -> - result.fold( - onSuccess = { - jsonRpcHistory.updateRequestWithResponse(response.id, responseJson) - onSuccess() - }, - onFailure = { error -> onFailure(error) } - ) - } - } - - internal fun respondWithParams( - request: WCRequestVO, - clientParams: ClientParams, - irnParams: IrnParamsVO, - envelopeType: EnvelopeType, - ) { - val result = JsonRpcResponseVO.JsonRpcResult(id = request.id, result = clientParams) - - publishJsonRpcResponse(request.topic, irnParams, result, envelopeType, - onFailure = { error -> Logger.error("Cannot send the response, error: $error") }) - } - - internal fun respondWithSuccess(request: WCRequestVO, irnParams: IrnParamsVO, envelopeType: EnvelopeType) { - val result = JsonRpcResponseVO.JsonRpcResult(id = request.id, result = true) - try { - publishJsonRpcResponse(request.topic, irnParams, result, envelopeType, - onFailure = { error -> Logger.error("Cannot send the response, error: $error") }) - } catch (e: Exception) { - handleError(e.message ?: String.Empty) - } - } - - internal fun respondWithError( - request: WCRequestVO, - error: PeerError, - irnParams: IrnParamsVO, - envelopeType: EnvelopeType, - onFailure: (Throwable) -> Unit = {}, - ) { - Logger.error("Responding with error: ${error.message}: ${error.code}") - val jsonRpcError = JsonRpcResponseVO.JsonRpcError(id = request.id, error = JsonRpcResponseVO.Error(error.code, error.message)) - - try { - publishJsonRpcResponse(request.topic, irnParams, jsonRpcError, envelopeType, - onFailure = { failure -> - Logger.error("Cannot respond with error: $failure") - onFailure(failure) - }) - } catch (e: Exception) { - handleError(e.message ?: String.Empty) - } - } - - internal fun subscribe(topic: TopicVO) { - relay.subscribe(topic.value) { result -> - result.fold( - onSuccess = { acknowledgement -> subscriptions[topic.value] = acknowledgement.result }, - onFailure = { error -> Logger.error("Subscribe to topic: $topic error: $error") } - ) - } - } - - internal fun unsubscribe(topic: TopicVO) { - if (subscriptions.contains(topic.value)) { - val subscriptionId = SubscriptionIdVO(subscriptions[topic.value].toString()) - relay.unsubscribe(topic.value, subscriptionId.id) { result -> - result.fold( - onSuccess = { - jsonRpcHistory.deleteRequests(topic) - subscriptions.remove(topic.value) - }, - onFailure = { error -> Logger.error("Unsubscribe to topic: $topic error: $error") } - ) - } - } - } - -// internal fun getMessages(topic: TopicVO): List = -// jsonRpcHistory.getRequests(topic) -// .filter { entry -> entry.response != null && entry.method == JsonRpcMethod.WC_CHAT_MESSAGE } -//// .filter { entry -> serializer.tryDeserialize(entry.body) != null } -//// .map { entry -> serializer.tryDeserialize(entry.body)!!.toPendingRequestVO(entry) } - - private fun manageSubscriptions() { - scope.launch(exceptionHandler) { - relay.subscriptionRequest - .map { relayRequest -> - val topic = TopicVO(relayRequest.subscriptionTopic) - val message = chaChaPolyCodec.decrypt(topic, relayRequest.message) - Logger.log("manageSubscriptions($message)") - - Pair(message, topic) - } - .collect { (decryptedMessage, topic) -> manageSubscriptions(decryptedMessage, topic) } - } - } - - private suspend fun manageSubscriptions(decryptedMessage: String, topic: TopicVO) { - serializer.tryDeserialize(decryptedMessage)?.let { clientJsonRpc -> - handleRequest(clientJsonRpc, topic, decryptedMessage) - } ?: serializer.tryDeserialize(decryptedMessage)?.let { result -> - handleJsonRpcResult(result) - } ?: serializer.tryDeserialize(decryptedMessage)?.let { error -> - handleJsonRpcError(error) - } ?: handleError("RelayerInteractor: Received unknown object type") - } - - private suspend fun handleRequest(clientJsonRpc: RelayerDO.ClientJsonRpc, topic: TopicVO, decryptedMessage: String) { - if (jsonRpcHistory.setRequest(clientJsonRpc.id, topic, clientJsonRpc.method, decryptedMessage)) { - serializer.deserialize(clientJsonRpc.method, decryptedMessage)?.let { params -> - _clientSyncJsonRpc.emit(WCRequestVO(topic, clientJsonRpc.id, clientJsonRpc.method, params)) - } ?: handleError("RelayerInteractor: Unknown request params") - } - } - - private suspend fun handleJsonRpcResult(jsonRpcResult: RelayerDO.JsonRpcResponse.JsonRpcResult) { - val jsonRpcRecord = jsonRpcHistory.updateRequestWithResponse(jsonRpcResult.id, serializer.serialize(jsonRpcResult)) - - if (jsonRpcRecord != null) { - serializer.deserialize(jsonRpcRecord.method, jsonRpcRecord.body)?.let { params -> - val responseVO = JsonRpcResponseVO.JsonRpcResult(jsonRpcResult.id, result = jsonRpcResult.result) - _peerResponse.emit(jsonRpcRecord.toWCResponse(responseVO, params)) - } ?: handleError("RelayerInteractor: Unknown result params") - } - } - - private suspend fun handleJsonRpcError(jsonRpcError: RelayerDO.JsonRpcResponse.JsonRpcError) { - val jsonRpcRecord = jsonRpcHistory.updateRequestWithResponse(jsonRpcError.id, serializer.serialize(jsonRpcError)) - - if (jsonRpcRecord != null) { - serializer.deserialize(jsonRpcRecord.method, jsonRpcRecord.body)?.let { params -> - _peerResponse.emit(jsonRpcRecord.toWCResponse(jsonRpcError.toJsonRpcErrorVO(), params)) - } ?: handleError("RelayerInteractor: Unknown error params") - } - } - - private fun setIsWSSConnectionOpened(event: Relay.Model.Event) { - if (event is Relay.Model.Event.OnConnectionOpened<*>) { - _isWSSConnectionOpened.compareAndSet(expect = false, update = true) - } else if (event is Relay.Model.Event.OnConnectionClosed || event is Relay.Model.Event.OnConnectionFailed) { - _isWSSConnectionOpened.compareAndSet(expect = true, update = false) - } - } - - private fun handleError(errorMessage: String) { - Logger.error(errorMessage) - scope.launch { - _internalErrors.emit(InternalError(errorMessage)) - } - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerDO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerDO.kt deleted file mode 100644 index f61d8bcf63..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerDO.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.json_rpc.model - -import com.squareup.moshi.JsonClass -import com.walletconnect.chat.copiedFromSign.core.model.type.SerializableJsonRpc - -internal sealed class RelayerDO { - - internal sealed class JsonRpcResponse : RelayerDO(), SerializableJsonRpc { - abstract val id: Long - - @JsonClass(generateAdapter = false) - internal data class JsonRpcResult( - override val id: Long, - val jsonrpc: String = "2.0", - val result: Any, - ) : JsonRpcResponse() - - @JsonClass(generateAdapter = true) - internal data class JsonRpcError( - override val id: Long, - val jsonrpc: String = "2.0", - val error: Error, - ) : JsonRpcResponse() - - internal data class Error( - val code: Int, - val message: String, - ) - } - - internal data class ClientJsonRpc( - val id: Long, - val jsonrpc: String, - val method: String - ) : RelayerDO() -} diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerMapper.kt deleted file mode 100644 index e2e7a18749..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/model/RelayerMapper.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.json_rpc.model - -import com.walletconnect.chat.copiedFromSign.core.model.client.Relay -import com.walletconnect.chat.copiedFromSign.core.model.type.ClientParams -import com.walletconnect.chat.copiedFromSign.core.model.vo.IrnParamsVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc.JsonRpcHistoryVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc.JsonRpcResponseVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.WCResponseVO - -@JvmSynthetic -internal fun JsonRpcResponseVO.toRelayerDOJsonRpcResponse(): RelayerDO.JsonRpcResponse = - when (this) { - is JsonRpcResponseVO.JsonRpcResult -> toRelayerDOJsonRpcResult() - is JsonRpcResponseVO.JsonRpcError -> toRelayerDORpcError() - } - -@JvmSynthetic -internal fun JsonRpcResponseVO.JsonRpcResult.toRelayerDOJsonRpcResult(): RelayerDO.JsonRpcResponse.JsonRpcResult = - RelayerDO.JsonRpcResponse.JsonRpcResult(id, result = result) - -@JvmSynthetic -internal fun JsonRpcResponseVO.JsonRpcError.toRelayerDORpcError(): RelayerDO.JsonRpcResponse.JsonRpcError = - RelayerDO.JsonRpcResponse.JsonRpcError(id, error = RelayerDO.JsonRpcResponse.Error(error.code, error.message)) - -@JvmSynthetic -internal fun RelayerDO.JsonRpcResponse.JsonRpcError.toJsonRpcErrorVO(): JsonRpcResponseVO.JsonRpcError = - JsonRpcResponseVO.JsonRpcError(id, error = JsonRpcResponseVO.Error(error.code, error.message)) - -@JvmSynthetic -internal fun JsonRpcHistoryVO.toWCResponse(result: JsonRpcResponseVO, params: ClientParams): WCResponseVO = - WCResponseVO(TopicVO(topic), method, result, params) - -//@JvmSynthetic -//internal fun SessionSettlementVO.SessionRequest.toPendingRequestVO(entry: JsonRpcHistoryVO): PendingRequestVO = -// PendingRequestVO( -// entry.requestId, -// entry.topic, -// params.request.method, -// params.chainId, -// params.request.params.toString(), -// ) - -@JvmSynthetic -internal fun IrnParamsVO.toRelay(): Relay.Model.IrnParams = - Relay.Model.IrnParams(tag.id, ttl.seconds, prompt) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/RelayInterface.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/RelayInterface.kt deleted file mode 100644 index 1196256206..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/RelayInterface.kt +++ /dev/null @@ -1,32 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.network - -import com.walletconnect.chat.copiedFromSign.core.model.client.Relay -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharedFlow - -interface RelayInterface { - val eventsFlow: SharedFlow - - val subscriptionRequest: Flow - - fun connect(onError: (String) -> Unit) - - fun disconnect(onError: (String) -> Unit) - - fun publish( - topic: String, - message: String, - params: Relay.Model.IrnParams, - onResult: (Result) -> Unit = {}, - ) - - fun subscribe(topic: String, onResult: (Result) -> Unit) - - fun unsubscribe( - topic: String, - subscriptionId: String, - onResult: (Result) -> Unit, - ) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/adapter/FlowStreamAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/adapter/FlowStreamAdapter.kt deleted file mode 100644 index bd5c16dfcf..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/adapter/FlowStreamAdapter.kt +++ /dev/null @@ -1,30 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.network.adapter - -import com.tinder.scarlet.Stream -import com.tinder.scarlet.StreamAdapter -import com.tinder.scarlet.utils.getRawType -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.reactive.collect -import java.lang.reflect.Type - -internal class FlowStreamAdapter : StreamAdapter> { - - override fun adapt(stream: Stream) = flow { - stream.collect { - emit(it) - } - } - - internal class Factory : StreamAdapter.Factory { - - override fun create(type: Type): StreamAdapter { - return when (type.getRawType()) { - Flow::class.java -> FlowStreamAdapter() - else -> throw IllegalArgumentException() - } - } - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionEvent.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionEvent.kt deleted file mode 100644 index 6791800b25..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionEvent.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.network.connection - -internal enum class ConnectionEvent { - CONNECT, DISCONNECT -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionType.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionType.kt deleted file mode 100644 index ef35c05b8b..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/ConnectionType.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.network.connection - -internal enum class ConnectionType { - AUTOMATIC, MANUAL -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/controller/ConnectionController.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/controller/ConnectionController.kt deleted file mode 100644 index 1adedba820..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/controller/ConnectionController.kt +++ /dev/null @@ -1,26 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.network.connection.controller - -import com.walletconnect.chat.copiedFromSign.network.connection.ConnectionEvent -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow - -internal sealed class ConnectionController { - - internal class Manual : ConnectionController() { - private val _connectionEvent: MutableStateFlow = MutableStateFlow(ConnectionEvent.DISCONNECT) - val connectionEventFlow: StateFlow = _connectionEvent.asStateFlow() - - fun connect() { - _connectionEvent.value = ConnectionEvent.CONNECT - } - - fun disconnect() { - _connectionEvent.value = ConnectionEvent.DISCONNECT - } - } - - internal object Automatic : ConnectionController() -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/lifecycle/ManualConnectionLifecycle.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/lifecycle/ManualConnectionLifecycle.kt deleted file mode 100644 index 07c6a80b72..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/lifecycle/ManualConnectionLifecycle.kt +++ /dev/null @@ -1,30 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.network.connection.lifecycle - -import com.tinder.scarlet.Lifecycle -import com.tinder.scarlet.lifecycle.LifecycleRegistry -import com.walletconnect.chat.copiedFromSign.core.scope.scope -import com.walletconnect.chat.copiedFromSign.network.connection.ConnectionEvent -import com.walletconnect.chat.copiedFromSign.network.connection.controller.ConnectionController -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach - -internal class ManualConnectionLifecycle( - connectionController: ConnectionController, - private val lifecycleRegistry: LifecycleRegistry, -) : Lifecycle by lifecycleRegistry { - - init { - if (connectionController is ConnectionController.Manual) { - connectionController.connectionEventFlow - .onEach { event -> - when (event) { - ConnectionEvent.CONNECT -> lifecycleRegistry.onNext(Lifecycle.State.Started) - ConnectionEvent.DISCONNECT -> lifecycleRegistry.onNext(Lifecycle.State.Stopped.WithReason()) - } - } - .launchIn(scope) - } - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/domain/RelayClient.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/domain/RelayClient.kt deleted file mode 100644 index a80af36e6b..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/domain/RelayClient.kt +++ /dev/null @@ -1,181 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.network.domain - -import com.walletconnect.chat.copiedFromSign.core.exceptions.WRONG_CONNECTION_TYPE -import com.walletconnect.chat.copiedFromSign.core.model.client.Relay -import com.walletconnect.chat.copiedFromSign.core.model.vo.SubscriptionIdVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TtlVO -import com.walletconnect.chat.copiedFromSign.core.scope.scope -import com.walletconnect.chat.copiedFromSign.network.RelayInterface -import com.walletconnect.chat.copiedFromSign.network.connection.controller.ConnectionController -import com.walletconnect.chat.copiedFromSign.network.model.RelayDTO -import com.walletconnect.chat.copiedFromSign.network.model.toRelayAcknowledgment -import com.walletconnect.chat.copiedFromSign.network.model.toRelayEvent -import com.walletconnect.chat.copiedFromSign.network.model.toRelayRequest -import com.walletconnect.chat.copiedFromSign.network.service.RelayService -import com.walletconnect.chat.copiedFromSign.util.Logger -import com.walletconnect.chat.copiedFromSign.util.generateId -import kotlinx.coroutines.cancel -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import kotlinx.coroutines.supervisorScope - -internal class RelayClient internal constructor( - private val connectionController: ConnectionController, - private val relay: RelayService, -) : RelayInterface { - - override val eventsFlow: SharedFlow = relay - .observeWebSocketEvent() - .map { event -> event.toRelayEvent() } - .shareIn(scope, SharingStarted.Lazily, REPLAY) - - - override fun connect(onError: (String) -> Unit) { - when (connectionController) { - is ConnectionController.Automatic -> onError(WRONG_CONNECTION_TYPE) - is ConnectionController.Manual -> connectionController.connect() - } - } - - override fun disconnect(onError: (String) -> Unit) { - when (connectionController) { - is ConnectionController.Automatic -> onError(WRONG_CONNECTION_TYPE) - is ConnectionController.Manual -> connectionController.disconnect() - } - } - - override val subscriptionRequest: Flow = - relay.observeSubscriptionRequest() - .map { request -> request.toRelayRequest() } - .onEach { relayRequest -> supervisorScope { publishSubscriptionAcknowledgement(relayRequest.id) } } - - override fun publish( - topic: String, - message: String, - params: Relay.Model.IrnParams, - onResult: (Result) -> Unit, - ) { - val (tag, ttl, prompt) = params - val publishParams = RelayDTO.Publish.Request.Params(TopicVO(topic), message, TtlVO(ttl), tag, prompt) - val request = RelayDTO.Publish.Request(generateId(), params = publishParams) - - observePublishAcknowledgement { acknowledgement -> onResult(Result.success(acknowledgement)) } - observePublishError { error -> onResult(Result.failure(error)) } - relay.publishRequest(request) - } - - override fun subscribe(topic: String, onResult: (Result) -> Unit) { - val subscribeRequest = RelayDTO.Subscribe.Request(id = generateId(), params = RelayDTO.Subscribe.Request.Params(TopicVO(topic))) - observeSubscribeAcknowledgement { acknowledgement -> onResult(Result.success(acknowledgement)) } - observeSubscribeError { error -> onResult(Result.failure(error)) } - relay.subscribeRequest(subscribeRequest) - } - - override fun unsubscribe( - topic: String, - subscriptionId: String, - onResult: (Result) -> Unit, - ) { - val unsubscribeRequest = RelayDTO.Unsubscribe.Request(id = generateId(), - params = RelayDTO.Unsubscribe.Request.Params(TopicVO(topic), SubscriptionIdVO(subscriptionId))) - observeUnSubscribeAcknowledgement { acknowledgement -> onResult(Result.success(acknowledgement)) } - observeUnSubscribeError { error -> onResult(Result.failure(error)) } - relay.unsubscribeRequest(unsubscribeRequest) - } - - private fun publishSubscriptionAcknowledgement(id: Long) { - val publishRequest = RelayDTO.Subscription.Acknowledgement(id = id, result = true) - relay.publishSubscriptionAcknowledgement(publishRequest) - } - - private fun observePublishAcknowledgement(onResult: (Relay.Model.Call.Publish.Acknowledgement) -> Unit) { - scope.launch { - relay.observePublishAcknowledgement() - .map { ack -> ack.toRelayAcknowledgment() } - .catch { exception -> Logger.error(exception) } - .collect { acknowledgement -> - supervisorScope { - onResult(acknowledgement) - cancel() - } - } - } - } - - private fun observePublishError(onFailure: (Throwable) -> Unit) { - scope.launch { - relay.observePublishError() - .onEach { jsonRpcError -> Logger.error(Throwable(jsonRpcError.error.errorMessage)) } - .catch { exception -> Logger.error(exception) } - .collect { errorResponse -> - supervisorScope { - onFailure(Throwable(errorResponse.error.errorMessage)) - cancel() - } - } - } - } - - private fun observeSubscribeAcknowledgement(onResult: (Relay.Model.Call.Subscribe.Acknowledgement) -> Unit) { - scope.launch { - relay.observeSubscribeAcknowledgement() - .map { ack -> ack.toRelayAcknowledgment() } - .catch { exception -> Logger.error(exception) } - .collect { acknowledgement -> - supervisorScope { - onResult(acknowledgement) - cancel() - } - } - } - } - - private fun observeSubscribeError(onFailure: (Throwable) -> Unit) { - scope.launch { - relay.observeSubscribeError() - .onEach { jsonRpcError -> Logger.error(Throwable(jsonRpcError.error.errorMessage)) } - .catch { exception -> Logger.error(exception) } - .collect { errorResponse -> - supervisorScope { - onFailure(Throwable(errorResponse.error.errorMessage)) - cancel() - } - } - } - } - - private fun observeUnSubscribeAcknowledgement(onSuccess: (Relay.Model.Call.Unsubscribe.Acknowledgement) -> Unit) { - scope.launch { - relay.observeUnsubscribeAcknowledgement() - .map { ack -> ack.toRelayAcknowledgment() } - .catch { exception -> Logger.error(exception) } - .collect { acknowledgement -> - supervisorScope { - onSuccess(acknowledgement) - cancel() - } - } - } - } - - private fun observeUnSubscribeError(onFailure: (Throwable) -> Unit) { - scope.launch { - relay.observeUnsubscribeError() - .onEach { jsonRpcError -> Logger.error(Throwable(jsonRpcError.error.errorMessage)) } - .catch { exception -> Logger.error(exception) } - .collect { errorResponse -> - supervisorScope { - onFailure(Throwable(errorResponse.error.errorMessage)) - cancel() - } - } - } - } - - private companion object { - private const val REPLAY: Int = 1 - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/JsonRpcRelay.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/JsonRpcRelay.kt deleted file mode 100644 index 5e55ce6041..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/JsonRpcRelay.kt +++ /dev/null @@ -1,9 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.network.model - -private const val SUFFIX = "irn" -internal const val IRN_PUBLISH: String = "${SUFFIX}_publish" -internal const val IRN_SUBSCRIPTION: String = "${SUFFIX}_subscription" -internal const val IRN_SUBSCRIBE: String = "${SUFFIX}_subscribe" -internal const val IRN_UNSUBSCRIBE: String = "${SUFFIX}_unsubscribe" \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayDTO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayDTO.kt deleted file mode 100644 index 3950274b1b..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayDTO.kt +++ /dev/null @@ -1,214 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.network.model - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass -import com.walletconnect.chat.copiedFromSign.core.adapters.SubscriptionIdAdapter -import com.walletconnect.chat.copiedFromSign.core.adapters.TopicAdapter -import com.walletconnect.chat.copiedFromSign.core.adapters.TtlAdapter -import com.walletconnect.chat.copiedFromSign.core.model.vo.SubscriptionIdVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TtlVO - -internal sealed class RelayDTO { - abstract val id: Long - abstract val jsonrpc: String - - internal sealed class Publish : RelayDTO() { - - @JsonClass(generateAdapter = true) - internal data class Request( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "method") - val method: String = IRN_PUBLISH, - @Json(name = "params") - val params: Params - ) : Publish() { - - @JsonClass(generateAdapter = true) - internal data class Params( - @Json(name = "topic") - @field:TopicAdapter.Qualifier - val topic: TopicVO, - @Json(name = "message") - val message: String, - @Json(name = "ttl") - @field:TtlAdapter.Qualifier - val ttl: TtlVO, - @Json(name = "tag") - val tag: Int, - @Json(name = "prompt") - val prompt: Boolean?, - ) - } - - internal data class Acknowledgement( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "result") - val result: Boolean - ) : Publish() - - internal data class JsonRpcError( - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "error") - val error: Error, - @Json(name = "id") - override val id: Long - ) : Publish() - } - - internal sealed class Subscribe : RelayDTO() { - - @JsonClass(generateAdapter = true) - internal data class Request( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "method") - val method: String = IRN_SUBSCRIBE, - @Json(name = "params") - val params: Params - ) : Subscribe() { - - @JsonClass(generateAdapter = true) - internal data class Params( - @Json(name = "topic") - @field:TopicAdapter.Qualifier - val topic: TopicVO - ) - } - - internal data class Acknowledgement( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "result") - @field:SubscriptionIdAdapter.Qualifier - val result: SubscriptionIdVO - ) : Subscribe() - - internal data class JsonRpcError( - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "error") - val error: Error, - @Json(name = "id") - override val id: Long - ) : Subscribe() - } - - internal sealed class Subscription : RelayDTO() { - - @JsonClass(generateAdapter = true) - internal data class Request( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "method") - val method: String = IRN_SUBSCRIPTION, - @Json(name = "params") - val params: Params - ) : Subscription() { - - val subscriptionTopic: TopicVO = params.subscriptionData.topic - val message: String = params.subscriptionData.message - - @JsonClass(generateAdapter = true) - internal data class Params( - @Json(name = "id") - @field:SubscriptionIdAdapter.Qualifier - val subscriptionId: SubscriptionIdVO, - @Json(name = "data") - val subscriptionData: SubscriptionData - ) { - - @JsonClass(generateAdapter = true) - internal data class SubscriptionData( - @Json(name = "topic") - @field:TopicAdapter.Qualifier - val topic: TopicVO, - @Json(name = "message") - val message: String //ack, jsonrpc error, eth_sign - ) - } - } - - internal data class Acknowledgement( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "result") - val result: Boolean - ) : Subscription() - - internal data class JsonRpcError( - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "error") - val error: Error, - @Json(name = "id") - override val id: Long - ) : Subscription() - } - - internal sealed class Unsubscribe : RelayDTO() { - - internal data class Request( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "method") - val method: String = IRN_UNSUBSCRIBE, - @Json(name = "params") - val params: Params - ) : Unsubscribe() { - - internal data class Params( - @Json(name = "topic") - @field:TopicAdapter.Qualifier - val topic: TopicVO, - @Json(name = "id") - @field:SubscriptionIdAdapter.Qualifier - val subscriptionId: SubscriptionIdVO - ) - } - - internal data class Acknowledgement( - @Json(name = "id") - override val id: Long, - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "result") - val result: Boolean - ) : Unsubscribe() - - internal data class JsonRpcError( - @Json(name = "jsonrpc") - override val jsonrpc: String = "2.0", - @Json(name = "error") - val error: Error, - @Json(name = "id") - override val id: Long - ) : Unsubscribe() - } - - internal data class Error( - @Json(name = "code") - val code: Long, - @Json(name = "message") - val message: String, - ) { - val errorMessage: String = "Error code: $code; Error message: $message" - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayMapper.kt deleted file mode 100644 index a95c734f59..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/model/RelayMapper.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.network.model - -import com.tinder.scarlet.Message -import com.tinder.scarlet.ShutdownReason -import com.tinder.scarlet.WebSocket -import com.walletconnect.chat.copiedFromSign.core.model.client.Relay - -@JvmSynthetic -internal fun WebSocket.Event.toRelayEvent() = when (this) { - is WebSocket.Event.OnConnectionOpened<*> -> - Relay.Model.Event.OnConnectionOpened(webSocket) - is WebSocket.Event.OnMessageReceived -> - Relay.Model.Event.OnMessageReceived(message.toRelayMessage()) - is WebSocket.Event.OnConnectionClosing -> - Relay.Model.Event.OnConnectionClosing(shutdownReason.toRelayShutdownReason()) - is WebSocket.Event.OnConnectionClosed -> - Relay.Model.Event.OnConnectionClosed(shutdownReason.toRelayShutdownReason()) - is WebSocket.Event.OnConnectionFailed -> - Relay.Model.Event.OnConnectionFailed(throwable) -} - -@JvmSynthetic -internal fun Message.toRelayMessage() = when (this) { - is Message.Text -> Relay.Model.Message.Text(value) - is Message.Bytes -> Relay.Model.Message.Bytes(value) -} - -@JvmSynthetic -internal fun ShutdownReason.toRelayShutdownReason() = - Relay.Model.ShutdownReason(code, reason) - -@JvmSynthetic -internal fun RelayDTO.Subscription.Request.Params.SubscriptionData.toRelaySubscriptionData() = - Relay.Model.Call.Subscription.Request.Params.SubscriptionData(topic.value, message) - -@JvmSynthetic -internal fun RelayDTO.Subscription.Request.Params.toRelayParams() = - Relay.Model.Call.Subscription.Request.Params(subscriptionId.id, subscriptionData.toRelaySubscriptionData()) - -@JvmSynthetic -internal fun RelayDTO.Subscription.Request.toRelayRequest() = - Relay.Model.Call.Subscription.Request(id, jsonrpc, method, params.toRelayParams()) - -@JvmSynthetic -internal fun RelayDTO.Publish.Acknowledgement.toRelayAcknowledgment() = - Relay.Model.Call.Publish.Acknowledgement(id, jsonrpc, result) - -@JvmSynthetic -internal fun RelayDTO.Subscribe.Acknowledgement.toRelayAcknowledgment() = - Relay.Model.Call.Subscribe.Acknowledgement(id, jsonrpc, result.id) - -@JvmSynthetic -internal fun RelayDTO.Unsubscribe.Acknowledgement.toRelayAcknowledgment() = - Relay.Model.Call.Unsubscribe.Acknowledgement(id, jsonrpc, result) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/service/RelayService.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/service/RelayService.kt deleted file mode 100644 index 42ba2a0c37..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/service/RelayService.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.network.service - -import com.tinder.scarlet.WebSocket -import com.tinder.scarlet.ws.Receive -import com.tinder.scarlet.ws.Send -import com.walletconnect.chat.copiedFromSign.network.model.RelayDTO -import kotlinx.coroutines.flow.Flow - -internal interface RelayService { - - @Receive - fun observeWebSocketEvent(): Flow - - @Send - fun publishRequest(publishRequest: RelayDTO.Publish.Request) - - @Receive - fun observePublishAcknowledgement(): Flow - - @Receive - fun observePublishError(): Flow - - @Send - fun subscribeRequest(subscribeRequest: RelayDTO.Subscribe.Request) - - @Receive - fun observeSubscribeAcknowledgement(): Flow - - @Receive - fun observeSubscribeError(): Flow - - @Receive - fun observeSubscriptionRequest(): Flow - - @Send - fun publishSubscriptionAcknowledgement(publishRequest: RelayDTO.Subscription.Acknowledgement) - - @Send - fun unsubscribeRequest(unsubscribeRequest: RelayDTO.Unsubscribe.Request) - - @Receive - fun observeUnsubscribeAcknowledgement(): Flow - - @Receive - fun observeUnsubscribeError(): Flow -} diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/storage/JsonRpcHistory.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/storage/JsonRpcHistory.kt deleted file mode 100644 index fb51c9ac86..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/storage/JsonRpcHistory.kt +++ /dev/null @@ -1,60 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.storage - -import android.content.SharedPreferences -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc.JsonRpcHistoryVO -import com.walletconnect.chat.copiedFromSign.util.Logger -import com.walletconnect.chat.storage.data.dao.JsonRpcHistoryQueries - -internal class JsonRpcHistory(private val sharedPreferences: SharedPreferences, private val jsonRpcHistoryQueries: JsonRpcHistoryQueries) { - - fun setRequest(requestId: Long, topic: TopicVO, method: String, payload: String): Boolean { - return try { - if (jsonRpcHistoryQueries.doesJsonRpcNotExist(requestId).executeAsOne()) { - jsonRpcHistoryQueries.insertOrAbortJsonRpcHistory(requestId, topic.value, method, payload) - jsonRpcHistoryQueries.selectLastInsertedRowId().executeAsOne() > 0L - } else { - Logger.error("Duplicated JsonRpc RequestId: $requestId") - false - } - } catch (e: Exception) { - Logger.error(e) - false - } - } - - fun updateRequestWithResponse(requestId: Long, response: String): JsonRpcHistoryVO? { - val record = jsonRpcHistoryQueries.getJsonRpcHistoryRecord(requestId, mapper = ::mapToJsonRpc).executeAsOneOrNull() - return if (record != null) { - updateRecord(record, requestId, response) - } else { - Logger.log("No JsonRpcRequest matching response") - null - } - } - - private fun updateRecord(record: JsonRpcHistoryVO, requestId: Long, response: String): JsonRpcHistoryVO? = - if (record.response != null) { - Logger.log("Duplicated JsonRpc RequestId: $requestId") - null - } else { - jsonRpcHistoryQueries.updateJsonRpcHistory(response = response, request_id = requestId) - record - } - - fun deleteRequests(topic: TopicVO) { - sharedPreferences.all.entries - .filter { entry -> entry.value == topic.value } - .forEach { entry -> sharedPreferences.edit().remove(entry.key).apply() } - - jsonRpcHistoryQueries.deleteJsonRpcHistory(topic.value) - } - - internal fun getRequests(topic: TopicVO): List = - jsonRpcHistoryQueries.getJsonRpcRequestsDaos(topic.value, mapper = ::mapToJsonRpc).executeAsList() - - private fun mapToJsonRpc(requestId: Long, topic: String, method: String, body: String, response: String?): JsonRpcHistoryVO = - JsonRpcHistoryVO(requestId, topic, method, body, response) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/KotlinExtensions.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/KotlinExtensions.kt deleted file mode 100644 index ce98963390..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/KotlinExtensions.kt +++ /dev/null @@ -1,9 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.util - -@get:JvmSynthetic -internal val String.Companion.Empty get() = "" - -@get:JvmSynthetic -internal val Int.Companion.DefaultId get() = -1 \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Logger.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Logger.kt deleted file mode 100644 index 5c2c77b251..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Logger.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.util - -import com.walletconnect.chat.BuildConfig -import timber.log.Timber - -internal object Logger { - const val TAG = "WalletConnectV2" - - init { - if (BuildConfig.DEBUG) { - // Source: https://medium.com/androiddevnotes/customize-your-android-timber-logger-setup-to-add-a-global-tag-and-a-method-name-to-the-logs-for-e7f23acd844f - Timber.plant( - object : Timber.DebugTree() { - /** - * Override [log] to modify the tag and add a "global tag" prefix to it. You can rename the String "global_tag_" as you see fit. - */ - override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { - super.log(priority, TAG, message, t) - } - }) - } - } - - fun log(logMsg: String?) { - Timber.d(logMsg) - } - - fun log(throwable: Throwable?) { - Timber.d(throwable) - } - - fun error(errorMsg: String?) { - Timber.e(errorMsg) - } - - fun error(throwable: Throwable?) { - Timber.e(throwable) - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/NetworkState.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/NetworkState.kt deleted file mode 100644 index 1085d9033e..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/NetworkState.kt +++ /dev/null @@ -1,26 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign.util - -import android.content.Context -import android.net.ConnectivityManager -import android.net.Network -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow - -internal class NetworkState(context: Context) { - - private val _isAvailable = MutableStateFlow(false) - val isAvailable: StateFlow = _isAvailable.asStateFlow() - - private val callback = object : ConnectivityManager.NetworkCallback() { - override fun onAvailable(network: Network) { _isAvailable.compareAndSet(expect = false, update = true) } - override fun onLost(network: Network) { _isAvailable.compareAndSet(expect = true, update = false) } - } - - init { - (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).registerDefaultNetworkCallback(callback) - } -} - diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Time.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Time.kt deleted file mode 100644 index 9690a84934..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/Time.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.walletconnect.chat.copiedFromSign.util - -import com.walletconnect.sign.core.model.utils.Time - -object Expiration { - val inactivePairing: Long = Time.currentTimeInSeconds + Time.fiveMinutesInSeconds - val activePairing: Long = Time.currentTimeInSeconds + Time.monthInSeconds - val activeSession: Long = Time.currentTimeInSeconds + Time.weekInSeconds -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/UtilFunctions.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/UtilFunctions.kt deleted file mode 100644 index 49bce67feb..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/util/UtilFunctions.kt +++ /dev/null @@ -1,57 +0,0 @@ -@file:JvmName("Utils") - -package com.walletconnect.chat.copiedFromSign.util - -import java.lang.System.currentTimeMillis -import java.security.SecureRandom - -// Commented because ExpiryVO should not be in core module but somewhere in android_core -//@JvmSynthetic -//internal fun ExpiryVO.isSequenceValid(): Boolean = seconds > Time.currentTimeInSeconds - -@JvmSynthetic -internal fun randomBytes(size: Int): ByteArray = - ByteArray(size).apply { - SecureRandom().nextBytes(this) - } - -@JvmSynthetic -internal fun generateId(): Long = (currentTimeMillis() + (100..999).random()) - -@JvmSynthetic -internal fun ByteArray.bytesToHex(): String { - val hexString = StringBuilder(2 * this.size) - for (i in this.indices) { - val hex = Integer.toHexString(0xff and this[i].toInt()) - if (hex.length == 1) { - hexString.append('0') - } - hexString.append(hex) - } - return hexString.toString() -} - -@JvmSynthetic -internal fun String.hexToBytes(): ByteArray { - val len = this.length - val data = ByteArray(len / 2) - var i = 0 - while (i < len) { - data[i / 2] = ((Character.digit(this[i], 16) shl 4) - + Character.digit(this[i + 1], 16)).toByte() - i += 2 - } - return data -} - -private fun getHexPrefix(input: String): String = - if (containsHexPrefix(input)) { - input.substring(2) - } else { - input - } - -private fun containsHexPrefix(input: String): Boolean = input.startsWith("0x") - -@JvmSynthetic -internal fun Long.extractTimestamp() = this / 1000 \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt index 2ca190f0c3..d78f96ca86 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt @@ -2,8 +2,8 @@ package com.walletconnect.chat.core.model.vo -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey import com.walletconnect.chat.engine.domain.Validator +import com.walletconnect.foundation.common.model.PublicKey @JvmInline internal value class AccountIdVO(val value: String) { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/ChatRpcVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/ChatRpcVO.kt index 75dd6fe65c..b3df54a36e 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/ChatRpcVO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/ChatRpcVO.kt @@ -2,8 +2,8 @@ package com.walletconnect.chat.core.model.vo.clientsync import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import com.walletconnect.chat.copiedFromSign.core.model.type.JsonRpcClientSync -import com.walletconnect.chat.copiedFromSign.json_rpc.model.JsonRpcMethod +import com.walletconnect.android.impl.common.model.type.JsonRpcClientSync +import com.walletconnect.chat.copiedFromSign.JsonRpcMethod import com.walletconnect.chat.core.model.vo.clientsync.params.ChatParamsVO internal sealed class ChatRpcVO : JsonRpcClientSync { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/params/ChatParamsVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/params/ChatParamsVO.kt index 67d1f9895c..fcc4d4f22f 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/params/ChatParamsVO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/params/ChatParamsVO.kt @@ -2,7 +2,7 @@ package com.walletconnect.chat.core.model.vo.clientsync.params import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import com.walletconnect.chat.copiedFromSign.core.model.type.ClientParams +import com.walletconnect.android.impl.common.model.type.ClientParams import com.walletconnect.chat.core.model.vo.MediaVO internal sealed class ChatParamsVO : ClientParams { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt index 7f19b9b35c..af14b48903 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt @@ -2,12 +2,12 @@ package com.walletconnect.chat.discovery.keyserver.model -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey import com.walletconnect.chat.core.model.vo.AccountIdVO import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO +import com.walletconnect.foundation.common.model.PublicKey @JvmSynthetic internal fun KeyServerDTO.Account.toVOAccount(): AccountIdWithPublicKeyVO = AccountIdWithPublicKeyVO(AccountIdVO(account), PublicKey(publicKey)) @JvmSynthetic -internal fun AccountIdWithPublicKeyVO.toDTOAccount(): KeyServerDTO.Account = KeyServerDTO.Account(accountId.value, publicKey.keyAsHex) +internal fun AccountIdWithPublicKeyVO.toDTOAccount(): KeyServerDTO.Account = KeyServerDTO.Account(accountId.value, publicKey.keyAsHex) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index e4997cd2f4..7d0edcf136 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -2,21 +2,16 @@ package com.walletconnect.chat.engine.domain +import com.walletconnect.android.common.JsonRpcResponse +import com.walletconnect.android.common.scope import com.walletconnect.android.exception.GenericException -import com.walletconnect.chat.copiedFromSign.core.model.type.enums.EnvelopeType -import com.walletconnect.chat.copiedFromSign.core.model.vo.IrnParamsVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey -import com.walletconnect.chat.copiedFromSign.core.model.vo.TopicVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.TtlVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.jsonRpc.JsonRpcResponseVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.ParticipantsVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.WCRequestVO -import com.walletconnect.chat.copiedFromSign.core.model.vo.sync.WCResponseVO -import com.walletconnect.chat.copiedFromSign.core.scope.scope -import com.walletconnect.chat.copiedFromSign.crypto.KeyManagementRepository -import com.walletconnect.chat.copiedFromSign.json_rpc.domain.RelayerInteractor -import com.walletconnect.chat.copiedFromSign.util.Logger -import com.walletconnect.chat.copiedFromSign.util.generateId +import com.walletconnect.android.impl.common.model.IrnParams +import com.walletconnect.android.impl.common.model.Participants +import com.walletconnect.android.impl.common.model.sync.WCRequest +import com.walletconnect.android.impl.common.model.sync.WCResponse +import com.walletconnect.android.impl.common.model.type.enums.EnvelopeType +import com.walletconnect.android.impl.utils.Logger +import com.walletconnect.chat.copiedFromSign.KeyManagementRepository import com.walletconnect.chat.core.model.vo.AccountIdVO import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO import com.walletconnect.chat.core.model.vo.Tags @@ -26,7 +21,10 @@ import com.walletconnect.chat.discovery.keyserver.domain.use_case.RegisterAccoun import com.walletconnect.chat.discovery.keyserver.domain.use_case.ResolveAccountUseCase import com.walletconnect.chat.engine.model.EngineDO import com.walletconnect.chat.storage.ChatStorageRepository -import com.walletconnect.sign.core.model.utils.Time +import com.walletconnect.foundation.common.model.PublicKey +import com.walletconnect.foundation.common.model.Topic +import com.walletconnect.foundation.common.model.Ttl +import com.walletconnect.util.generateId import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.* @@ -37,18 +35,18 @@ internal class ChatEngine( private val registerAccountUseCase: RegisterAccountUseCase, private val resolveAccountUseCase: ResolveAccountUseCase, private val keyManagementRepository: KeyManagementRepository, - private val relayer: RelayerInteractor, + private val jsonRpcInteractor: JsonRpcInteractor, private val chatStorage: ChatStorageRepository, ) { private val _events: MutableSharedFlow = MutableSharedFlow() val events: SharedFlow = _events.asSharedFlow() - private val inviteRequestMap: MutableMap = mutableMapOf() + private val inviteRequestMap: MutableMap = mutableMapOf() init { collectJsonRpcRequests() collectPeerResponses() - relayer.initializationErrorsFlow.onEach { error -> Logger.error(error) }.launchIn(scope) - relayer.isConnectionAvailable + jsonRpcInteractor.initializationErrorsFlow.onEach { error -> Logger.error(error) }.launchIn(scope) + jsonRpcInteractor.isConnectionAvailable .onEach { isAvailable -> // _events.emit(EngineDO.ConnectionState(isAvailable)) todo add connection state callbacks } @@ -80,7 +78,7 @@ internal class ChatEngine( private: Boolean, ) { fun _onSuccess(publicKey: PublicKey) { - val topic = TopicVO(keyManagementRepository.getHash(publicKey.keyAsHex)) + val topic = Topic(keyManagementRepository.getHash(publicKey.keyAsHex)) keyManagementRepository.setInviteSelfPublicKey(topic, publicKey) trySubscribeToInviteTopic() onSuccess(publicKey.keyAsHex) @@ -105,8 +103,8 @@ internal class ChatEngine( private fun trySubscribeToInviteTopic() { try { val publicKey = keyManagementRepository.getInviteSelfPublicKey() - val topic = TopicVO(keyManagementRepository.getHash(publicKey.keyAsHex)) - relayer.subscribe(topic) + val topic = Topic(keyManagementRepository.getHash(publicKey.keyAsHex)) + jsonRpcInteractor.subscribe(topic) Logger.log("Listening for invite on: $topic, pubKey X:$publicKey") } catch (error: Exception) { Logger.log(error) // It will log if run before registerAccount() @@ -122,26 +120,26 @@ internal class ChatEngine( val receiverPublicKey = PublicKey(publicKeyString) // KeyPair X val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(senderPublicKey, receiverPublicKey) // SymKey I - val inviteTopic = TopicVO(keyManagementRepository.getHash(publicKeyString)) // Topic I + val inviteTopic = Topic(keyManagementRepository.getHash(publicKeyString)) // Topic I keyManagementRepository.setKeyAgreement(inviteTopic, senderPublicKey, receiverPublicKey) - val participantsVO = ParticipantsVO(senderPublicKey = senderPublicKey, receiverPublicKey = receiverPublicKey) + val participantsVO = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = receiverPublicKey) val inviteParams = ChatParamsVO.InviteParams(invite.message, invite.accountId.value, senderPublicKey.keyAsHex, invite.signature) val payload = ChatRpcVO.ChatInvite(id = generateId(), params = inviteParams) - val acceptTopic = TopicVO(keyManagementRepository.getHash(symmetricKey.keyAsHex)) + val acceptTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) keyManagementRepository.setSymmetricKey(acceptTopic, symmetricKey) - relayer.subscribe(acceptTopic) - val irnParams = IrnParamsVO(Tags.CHAT_INVITE, TtlVO(Time.dayInSeconds), true) + jsonRpcInteractor.subscribe(acceptTopic) + val irnParams = IrnParams(Tags.CHAT_INVITE, Ttl(Time.dayInSeconds), true) - relayer.publishJsonRpcRequests(inviteTopic, irnParams, payload, EnvelopeType.ONE, + jsonRpcInteractor.publishJsonRpcRequests(inviteTopic, irnParams, payload, EnvelopeType.ONE, { Logger.log("Chat invite sent successfully") }, { throwable -> Logger.log("Chat invite error: $throwable") - relayer.unsubscribe(acceptTopic) + jsonRpcInteractor.unsubscribe(acceptTopic) onFailure(throwable) }, participantsVO) @@ -149,20 +147,20 @@ internal class ChatEngine( onFailure(error) } - private fun onInviteResponse(wcResponse: WCResponseVO) { + private fun onInviteResponse(wcResponse: WCResponse) { when (val response = wcResponse.response) { - is JsonRpcResponseVO.JsonRpcError -> { + is JsonRpcResponse.JsonRpcError -> { Logger.log("Chat invite was rejected") } - is JsonRpcResponseVO.JsonRpcResult -> { + is JsonRpcResponse.JsonRpcResult -> { Logger.log("Chat invite was accepted") val acceptParams = response.result as ChatParamsVO.AcceptanceParams val pubKeyZ = PublicKey(acceptParams.publicKey) // PubKey Z val (selfPubKey, _) = keyManagementRepository.getKeyAgreement(wcResponse.topic) val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(selfPubKey, pubKeyZ) // SymKey T - val threadTopic = TopicVO(keyManagementRepository.getHash(symmetricKey.keyAsHex)) + val threadTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) keyManagementRepository.setSymmetricKey(threadTopic, symmetricKey) - relayer.subscribe(threadTopic) + jsonRpcInteractor.subscribe(threadTopic) scope.launch { _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) } @@ -170,7 +168,7 @@ internal class ChatEngine( } } - private fun onInviteRequest(wcRequest: WCRequestVO, params: ChatParamsVO.InviteParams) { + private fun onInviteRequest(wcRequest: WCRequest, params: ChatParamsVO.InviteParams) { inviteRequestMap[wcRequest.id] = wcRequest // todo when to remove it? scope.launch { @@ -189,21 +187,21 @@ internal class ChatEngine( val invitePublicKey = keyManagementRepository.getInviteSelfPublicKey() // PubKey X val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) // SymKey I - val acceptTopic = TopicVO(keyManagementRepository.getHash(symmetricKey.keyAsHex)) // Topic T + val acceptTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) // Topic T keyManagementRepository.setSymmetricKey(acceptTopic, symmetricKey) val publicKey = keyManagementRepository.generateKeyPair() // KeyPair Z val acceptanceParams = ChatParamsVO.AcceptanceParams(publicKey.keyAsHex) - val irnParams = IrnParamsVO(Tags.CHAT_INVITE_RESPONSE, TtlVO(Time.dayInSeconds)) + val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(Time.dayInSeconds)) - relayer.respondWithParams(request.copy(topic = acceptTopic), acceptanceParams, irnParams, EnvelopeType.ZERO) + jsonRpcInteractor.respondWithParams(request.copy(topic = acceptTopic), acceptanceParams, irnParams, EnvelopeType.ZERO) val threadSymmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(publicKey, senderPublicKey) // SymKey T - val threadTopic = TopicVO(keyManagementRepository.getHash(threadSymmetricKey.keyAsHex)) // Topic T + val threadTopic = Topic(keyManagementRepository.getHash(threadSymmetricKey.keyAsHex)) // Topic T keyManagementRepository.setSymmetricKey(threadTopic, threadSymmetricKey) - relayer.subscribe(threadTopic) + jsonRpcInteractor.subscribe(threadTopic) scope.launch { _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) @@ -215,10 +213,10 @@ internal class ChatEngine( internal fun reject(inviteId: String, onFailure: (Throwable) -> Unit) { // //todo: correct define params -// val request = WCRequestVO() +// val request = WCRequest() // val error = PeerError.Error("reason", 1) // -// relayer.respondWithError(request, error, EnvelopeType.ZERO) { throwable -> onFailure(throwable) } +// jsonRpcInteractor.respondWithError(request, error, EnvelopeType.ZERO) { throwable -> onFailure(throwable) } } internal fun message(topic: String, sendMessage: EngineDO.SendMessage, onFailure: (Throwable) -> Unit) { @@ -226,9 +224,9 @@ internal class ChatEngine( val messageParams = ChatParamsVO.MessageParams(sendMessage.message, sendMessage.author.value, System.currentTimeMillis(), sendMessage.media) val payload = ChatRpcVO.ChatMessage(id = generateId(), params = messageParams) - val irnParams = IrnParamsVO(Tags.CHAT_MESSAGE, TtlVO(Time.dayInSeconds), true) + val irnParams = IrnParams(Tags.CHAT_MESSAGE, Ttl(Time.dayInSeconds), true) - relayer.publishJsonRpcRequests(TopicVO(topic), irnParams, payload, EnvelopeType.ZERO, + jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, payload, EnvelopeType.ZERO, { Logger.log("Chat message sent successfully") }, { throwable -> Logger.log("Chat message error: $throwable") @@ -236,7 +234,7 @@ internal class ChatEngine( }) } - private fun onMessage(wcRequest: WCRequestVO, params: ChatParamsVO.MessageParams) { + private fun onMessage(wcRequest: WCRequest, params: ChatParamsVO.MessageParams) { scope.launch { _events.emit(EngineDO.Events.OnMessage(wcRequest.topic.value, EngineDO.Message(params.message, AccountIdVO(params.authorAccount), params.timestamp, params.media))) @@ -249,9 +247,9 @@ internal class ChatEngine( //todo: correct define params val leaveParams = ChatParamsVO.LeaveParams() val payload = ChatRpcVO.ChatLeave(id = generateId(), params = leaveParams) - val irnParams = IrnParamsVO(Tags.CHAT_LEAVE, TtlVO(Time.dayInSeconds), true) + val irnParams = IrnParams(Tags.CHAT_LEAVE, Ttl(Time.dayInSeconds), true) - relayer.publishJsonRpcRequests(TopicVO(topic), irnParams, payload, EnvelopeType.ZERO, + jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, payload, EnvelopeType.ZERO, { Logger.log("Chat message sent successfully") }, { throwable -> Logger.log("Chat message error: $throwable") @@ -265,7 +263,7 @@ internal class ChatEngine( private fun collectJsonRpcRequests() { scope.launch { - relayer.clientSyncJsonRpc.collect { request -> + jsonRpcInteractor.clientSyncJsonRpc.collect { request -> when (val params = request.params) { is ChatParamsVO.InviteParams -> onInviteRequest(request, params) is ChatParamsVO.MessageParams -> onMessage(request, params) @@ -276,7 +274,7 @@ internal class ChatEngine( private fun collectPeerResponses() { scope.launch { - relayer.peerResponse.collect { response -> + jsonRpcInteractor.peerResponse.collect { response -> when (val params = response.params) { is ChatParamsVO.InviteParams -> onInviteResponse(response) } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt index 1fd681d0fc..df1284e6f6 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt @@ -2,11 +2,11 @@ package com.walletconnect.chat.storage -import com.walletconnect.chat.copiedFromSign.core.model.vo.PublicKey import com.walletconnect.chat.core.model.vo.AccountIdVO import com.walletconnect.chat.engine.model.EngineDO import com.walletconnect.chat.storage.data.dao.Contacts import com.walletconnect.chat.storage.data.dao.ContactsQueries +import com.walletconnect.foundation.common.model.PublicKey internal class ChatStorageRepository( private val contactsQueries: ContactsQueries, diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index 5a1e9918da..2c51579ea4 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -48,7 +48,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.flow.* internal class SignEngine( - private val relayer: JsonRpcInteractor, + private val jsonRpcInteractor: JsonRpcInteractor, private val crypto: KeyManagementRepository, private val sequenceStorageRepository: SequenceStorageRepository, private val metaData: EngineDO.AppMetaData, @@ -66,11 +66,11 @@ internal class SignEngine( } fun handleInitializationErrors(onError: (WalletConnectException) -> Unit) { - relayer.initializationErrorsFlow.onEach { walletConnectException -> onError(walletConnectException) }.launchIn(scope) + jsonRpcInteractor.initializationErrorsFlow.onEach { walletConnectException -> onError(walletConnectException) }.launchIn(scope) } private fun resubscribeToSequences() { - relayer.isConnectionAvailable + jsonRpcInteractor.isConnectionAvailable .onEach { isAvailable -> _engineEvent.emit(ConnectionState(isAvailable)) } .filter { isAvailable: Boolean -> isAvailable } .onEach { @@ -103,10 +103,10 @@ internal class SignEngine( val request = PairingRpcVO.SessionPropose(id = generateId(), params = sessionProposal) sessionProposalRequest[selfPublicKey.keyAsHex] = WCRequest(pairingTopic, request.id, request.method, sessionProposal) val irnParams = IrnParams(Tags.SESSION_PROPOSE, Ttl(FIVE_MINUTES_IN_SECONDS), true) - relayer.subscribe(pairingTopic) + jsonRpcInteractor.subscribe(pairingTopic) onProposedSequence(proposedSequence) - relayer.publishJsonRpcRequests(pairingTopic, irnParams, request, + jsonRpcInteractor.publishJsonRpcRequests(pairingTopic, irnParams, request, onSuccess = { Logger.log("Session proposal sent successfully") }, @@ -142,12 +142,12 @@ internal class SignEngine( try { sequenceStorageRepository.insertPairing(inactivePairing) - relayer.subscribe(pairingTopic) + jsonRpcInteractor.subscribe(pairingTopic) proposedSession(pairingTopic, null, EngineDO.ProposedSequence.Pairing(walletConnectUri.toAbsoluteString())) } catch (e: SQLiteException) { crypto.removeKeys(pairingTopic.value) - relayer.unsubscribe(pairingTopic) + jsonRpcInteractor.unsubscribe(pairingTopic) sequenceStorageRepository.deletePairing(pairingTopic) onFailure(e) @@ -168,10 +168,10 @@ internal class SignEngine( try { sequenceStorageRepository.insertPairing(activePairing) - relayer.subscribe(activePairing.topic) + jsonRpcInteractor.subscribe(activePairing.topic) } catch (e: SQLiteException) { crypto.removeKeys(walletConnectUri.topic.value) - relayer.unsubscribe(activePairing.topic) + jsonRpcInteractor.unsubscribe(activePairing.topic) } } @@ -181,7 +181,7 @@ internal class SignEngine( sessionProposalRequest.remove(proposerPublicKey) val irnParams = IrnParams(Tags.SESSION_PROPOSE_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) - relayer.respondWithError(request, PeerError.EIP1193.UserRejectedRequest(reason), irnParams, onFailure = { error -> onFailure(error) }) + jsonRpcInteractor.respondWithError(request, PeerError.EIP1193.UserRejectedRequest(reason), irnParams, onFailure = { error -> onFailure(error) }) } internal fun approve( @@ -205,7 +205,7 @@ internal class SignEngine( val sessionSettle = SessionRpcVO.SessionSettle(id = generateId(), params = params) val irnParams = IrnParams(Tags.SESSION_SETTLE, Ttl(FIVE_MINUTES_IN_SECONDS)) - relayer.publishJsonRpcRequests(sessionTopic, irnParams, sessionSettle, onFailure = { error -> onFailure(error) }) + jsonRpcInteractor.publishJsonRpcRequests(sessionTopic, irnParams, sessionSettle, onFailure = { error -> onFailure(error) }) } catch (e: SQLiteException) { onFailure(e) } @@ -223,12 +223,12 @@ internal class SignEngine( val selfPublicKey: PublicKey = crypto.generateKeyPair() val sessionTopic = crypto.generateTopicFromKeyAgreement(selfPublicKey, PublicKey(proposerPublicKey)) - relayer.subscribe(sessionTopic) + jsonRpcInteractor.subscribe(sessionTopic) val approvalParams = proposal.toSessionApproveParams(selfPublicKey) val irnParams = IrnParams(Tags.SESSION_PROPOSE_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) - relayer.respondWithParams(request, approvalParams, irnParams) + jsonRpcInteractor.respondWithParams(request, approvalParams, irnParams) sessionSettle(request.id, proposal, sessionTopic) } @@ -261,7 +261,7 @@ internal class SignEngine( val irnParams = IrnParams(com.walletconnect.android.common.model.Tags.SESSION_UPDATE, Ttl(DAY_IN_SECONDS)) sequenceStorageRepository.insertTempNamespaces(topic, namespaces.toMapOfNamespacesVOSession(), sessionUpdate.id, onSuccess = { - relayer.publishJsonRpcRequests(Topic(topic), irnParams, sessionUpdate, + jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionUpdate, onSuccess = { Logger.log("Update sent successfully") }, onFailure = { error -> Logger.error("Sending session update error: $error") @@ -292,7 +292,7 @@ internal class SignEngine( val sessionPayload = SessionRpcVO.SessionRequest(id = generateId(), params = params) val irnParams = IrnParams(Tags.SESSION_REQUEST, Ttl(FIVE_MINUTES_IN_SECONDS), true) - relayer.publishJsonRpcRequests( + jsonRpcInteractor.publishJsonRpcRequests( Topic(request.topic), irnParams, sessionPayload, @@ -325,7 +325,7 @@ internal class SignEngine( } val irnParams = IrnParams(Tags.SESSION_REQUEST_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) - relayer.publishJsonRpcResponse(Topic(topic), irnParams, jsonRpcResponse, + jsonRpcInteractor.publishJsonRpcResponse(Topic(topic), irnParams, jsonRpcResponse, { Logger.log("Session payload sent successfully") }, { error -> Logger.error("Sending session payload response error: $error") @@ -348,7 +348,7 @@ internal class SignEngine( else -> throw CannotFindSequenceForTopic("$NO_SEQUENCE_FOR_TOPIC_MESSAGE$topic") } - relayer.publishJsonRpcRequests(Topic(topic), irnParams, pingPayload, + jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, pingPayload, onSuccess = { Logger.log("Ping sent successfully") @@ -407,7 +407,7 @@ internal class SignEngine( val sessionEvent = SessionRpcVO.SessionEvent(id = generateId(), params = eventParams) val irnParams = IrnParams(Tags.SESSION_EVENT, Ttl(FIVE_MINUTES_IN_SECONDS), true) - relayer.publishJsonRpcRequests(Topic(topic), irnParams, sessionEvent, + jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionEvent, onSuccess = { Logger.log("Event sent successfully") }, onFailure = { error -> Logger.error("Sending event error: $error") @@ -434,7 +434,7 @@ internal class SignEngine( val sessionExtend = SessionRpcVO.SessionExtend(id = generateId(), params = SessionParamsVO.ExtendParams(newExpiration)) val irnParams = IrnParams(Tags.SESSION_EXTEND, Ttl(DAY_IN_SECONDS)) - relayer.publishJsonRpcRequests(Topic(topic), irnParams, sessionExtend, + jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionExtend, onSuccess = { Logger.log("Session extend sent successfully") }, onFailure = { error -> Logger.error("Sending session extend error: $error") @@ -450,10 +450,10 @@ internal class SignEngine( val deleteParams = SessionParamsVO.DeleteParams(PeerError.Reason.UserDisconnected.code, PeerError.Reason.UserDisconnected.message) val sessionDelete = SessionRpcVO.SessionDelete(id = generateId(), params = deleteParams) sequenceStorageRepository.deleteSession(Topic(topic)) - relayer.unsubscribe(Topic(topic)) + jsonRpcInteractor.unsubscribe(Topic(topic)) val irnParams = IrnParams(Tags.SESSION_DELETE, Ttl(DAY_IN_SECONDS)) - relayer.publishJsonRpcRequests(Topic(topic), irnParams, sessionDelete, + jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionDelete, onSuccess = { Logger.error("Disconnect sent successfully") }, onFailure = { error -> Logger.error("Sending session disconnect error: $error") }) } @@ -470,10 +470,10 @@ internal class SignEngine( .map { pairing -> pairing.toEngineDOSettledPairing() } } - internal fun getPendingRequests(topic: Topic): List = relayer.getPendingRequests(topic) + internal fun getPendingRequests(topic: Topic): List = jsonRpcInteractor.getPendingRequests(topic) private suspend fun collectResponse(id: Long, onResponse: (Result) -> Unit = {}) { - relayer.peerResponse + jsonRpcInteractor.peerResponse .filter { response -> response.response.id == id } .collect { response -> when (val result = response.response) { @@ -485,7 +485,7 @@ internal class SignEngine( private fun collectJsonRpcRequests() { scope.launch { - relayer.clientSyncJsonRpc.collect { request -> + jsonRpcInteractor.clientSyncJsonRpc.collect { request -> when (val requestParams = request.params) { is PairingParamsVO.SessionProposeParams -> onSessionPropose(request, requestParams) is PairingParamsVO.DeleteParams -> onPairingDelete(request, requestParams) @@ -502,14 +502,14 @@ internal class SignEngine( } private fun collectInternalErrors() { - relayer.internalErrors + jsonRpcInteractor.internalErrors .onEach { exception -> _engineEvent.emit(SDKError(exception)) } .launchIn(scope) } private fun collectJsonRpcResponses() { scope.launch { - relayer.peerResponse.collect { response -> + jsonRpcInteractor.peerResponse.collect { response -> when (val params = response.params) { is PairingParamsVO.SessionProposeParams -> onSessionProposalResponse(response, params) is SessionParamsVO.SessionSettleParams -> onSessionSettleResponse(response) @@ -524,7 +524,7 @@ internal class SignEngine( private fun onSessionPropose(request: WCRequest, payloadParams: PairingParamsVO.SessionProposeParams) { Validator.validateProposalNamespace(payloadParams.namespaces) { error -> val irnParams = IrnParams(Tags.SESSION_PROPOSE_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) - relayer.respondWithError(request, error.toPeerError(), irnParams) + jsonRpcInteractor.respondWithError(request, error.toPeerError(), irnParams) return } @@ -541,14 +541,14 @@ internal class SignEngine( val irnParams = IrnParams(Tags.SESSION_SETTLE, Ttl(FIVE_MINUTES_IN_SECONDS)) if (proposal.params !is PairingParamsVO.SessionProposeParams) { - relayer.respondWithError(request, PeerError.Failure.SessionSettlementFailed(NAMESPACE_MISSING_PROPOSAL_MESSAGE), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Failure.SessionSettlementFailed(NAMESPACE_MISSING_PROPOSAL_MESSAGE), irnParams) return } val proposalNamespaces = (proposal.params as PairingParamsVO.SessionProposeParams).namespaces Validator.validateSessionNamespace(settleParams.namespaces, proposalNamespaces) { error -> - relayer.respondWithError(request, error.toPeerError(), irnParams) + jsonRpcInteractor.respondWithError(request, error.toPeerError(), irnParams) return } @@ -562,12 +562,12 @@ internal class SignEngine( sessionProposalRequest.remove(selfPublicKey.keyAsHex) sequenceStorageRepository.insertSession(session, request.id) - relayer.respondWithSuccess(request, IrnParams(Tags.SESSION_SETTLE, Ttl(FIVE_MINUTES_IN_SECONDS))) + jsonRpcInteractor.respondWithSuccess(request, IrnParams(Tags.SESSION_SETTLE, Ttl(FIVE_MINUTES_IN_SECONDS))) scope.launch { _engineEvent.emit(session.toSessionApproved()) } } catch (e: SQLiteException) { sessionProposalRequest[selfPublicKey.keyAsHex] = tempProposalRequest sequenceStorageRepository.deleteSession(sessionTopic) - relayer.respondWithError(request, PeerError.Failure.SessionSettlementFailed(e.message ?: String.Empty), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Failure.SessionSettlementFailed(e.message ?: String.Empty), irnParams) return } } @@ -576,12 +576,12 @@ internal class SignEngine( private fun onPairingDelete(request: WCRequest, params: PairingParamsVO.DeleteParams) { if (!sequenceStorageRepository.isPairingValid(request.topic)) { val irnParams = IrnParams(Tags.PAIRING_DELETE_RESPONSE, Ttl(DAY_IN_SECONDS)) - relayer.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.PAIRING.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.PAIRING.name, request.topic.value), irnParams) return } crypto.removeKeys(request.topic.value) - relayer.unsubscribe(request.topic) + jsonRpcInteractor.unsubscribe(request.topic) sequenceStorageRepository.deletePairing(request.topic) scope.launch { _engineEvent.emit(EngineDO.DeletedPairing(request.topic.value, params.message)) } @@ -591,13 +591,13 @@ internal class SignEngine( private fun onSessionDelete(request: WCRequest, params: SessionParamsVO.DeleteParams) { if (!sequenceStorageRepository.isSessionValid(request.topic)) { val irnParams = IrnParams(Tags.SESSION_DELETE_RESPONSE, Ttl(DAY_IN_SECONDS)) - relayer.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) return } crypto.removeKeys(request.topic.value) sequenceStorageRepository.deleteSession(request.topic) - relayer.unsubscribe(request.topic) + jsonRpcInteractor.unsubscribe(request.topic) scope.launch { _engineEvent.emit(params.toEngineDO(request.topic)) } } @@ -606,12 +606,12 @@ internal class SignEngine( private fun onSessionRequest(request: WCRequest, params: SessionParamsVO.SessionRequestParams) { val irnParams = IrnParams(Tags.SESSION_REQUEST_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) Validator.validateSessionRequest(params.toEngineDO(request.topic)) { error -> - relayer.respondWithError(request, error.toPeerError(), irnParams) + jsonRpcInteractor.respondWithError(request, error.toPeerError(), irnParams) return } if (!sequenceStorageRepository.isSessionValid(request.topic)) { - relayer.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) return } @@ -620,7 +620,7 @@ internal class SignEngine( val method = params.request.method Validator.validateChainIdWithMethodAuthorisation(params.chainId, method, sessionNamespaces) { error -> - relayer.respondWithError(request, error.toPeerError(), irnParams) + jsonRpcInteractor.respondWithError(request, error.toPeerError(), irnParams) return } @@ -631,32 +631,32 @@ internal class SignEngine( private fun onSessionEvent(request: WCRequest, params: SessionParamsVO.EventParams) { val irnParams = IrnParams(Tags.SESSION_EVENT_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) Validator.validateEvent(params.toEngineDOEvent()) { error -> - relayer.respondWithError(request, error.toPeerError(), irnParams) + jsonRpcInteractor.respondWithError(request, error.toPeerError(), irnParams) return } if (!sequenceStorageRepository.isSessionValid(request.topic)) { - relayer.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) return } val session = sequenceStorageRepository.getSessionByTopic(request.topic) if (!session.isPeerController) { - relayer.respondWithError(request, PeerError.Unauthorized.Event(Sequences.SESSION.name), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Unauthorized.Event(Sequences.SESSION.name), irnParams) return } if (!session.isAcknowledged) { - relayer.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) return } val event = params.event Validator.validateChainIdWithEventAuthorisation(params.chainId, event.name, session.namespaces) { error -> - relayer.respondWithError(request, error.toPeerError(), irnParams) + jsonRpcInteractor.respondWithError(request, error.toPeerError(), irnParams) return } - relayer.respondWithSuccess(request, irnParams) + jsonRpcInteractor.respondWithSuccess(request, irnParams) scope.launch { _engineEvent.emit(params.toEngineDO(request.topic)) } } @@ -664,34 +664,34 @@ internal class SignEngine( private fun onSessionUpdate(request: WCRequest, params: SessionParamsVO.UpdateNamespacesParams) { val irnParams = IrnParams(Tags.SESSION_UPDATE_RESPONSE, Ttl(DAY_IN_SECONDS)) if (!sequenceStorageRepository.isSessionValid(request.topic)) { - relayer.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) return } val session: SessionVO = sequenceStorageRepository.getSessionByTopic(request.topic) if (!session.isPeerController) { - relayer.respondWithError(request, PeerError.Unauthorized.UpdateRequest(Sequences.SESSION.name), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Unauthorized.UpdateRequest(Sequences.SESSION.name), irnParams) return } Validator.validateSessionNamespace(params.namespaces, session.proposalNamespaces) { error -> - relayer.respondWithError(request, PeerError.Invalid.UpdateRequest(error.message), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Invalid.UpdateRequest(error.message), irnParams) return } if (!sequenceStorageRepository.isUpdatedNamespaceValid(session.topic.value, request.id.extractTimestamp())) { - relayer.respondWithError(request, PeerError.Invalid.UpdateRequest("Update Namespace Request ID too old"), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Invalid.UpdateRequest("Update Namespace Request ID too old"), irnParams) return } sequenceStorageRepository.deleteNamespaceAndInsertNewNamespace(session.topic.value, params.namespaces, request.id, onSuccess = { - relayer.respondWithSuccess(request, irnParams) + jsonRpcInteractor.respondWithSuccess(request, irnParams) scope.launch { _engineEvent.emit(EngineDO.SessionUpdateNamespaces(request.topic, params.namespaces.toMapOfEngineNamespacesSession())) } }, onFailure = { - relayer.respondWithError( + jsonRpcInteractor.respondWithError( request, PeerError.Invalid.UpdateRequest("Updating Namespace Failed. Review Namespace structure"), irnParams @@ -703,30 +703,30 @@ internal class SignEngine( private fun onSessionExtend(request: WCRequest, requestParams: SessionParamsVO.ExtendParams) { val irnParams = IrnParams(Tags.SESSION_EXTEND_RESPONSE, Ttl(DAY_IN_SECONDS)) if (!sequenceStorageRepository.isSessionValid(request.topic)) { - relayer.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) return } val session = sequenceStorageRepository.getSessionByTopic(request.topic) if (!session.isPeerController) { - relayer.respondWithError(request, PeerError.Unauthorized.ExtendRequest(Sequences.SESSION.name), irnParams) + jsonRpcInteractor.respondWithError(request, PeerError.Unauthorized.ExtendRequest(Sequences.SESSION.name), irnParams) return } val newExpiry = requestParams.expiry Validator.validateSessionExtend(newExpiry, session.expiry.seconds) { error -> - relayer.respondWithError(request, error.toPeerError(), irnParams) + jsonRpcInteractor.respondWithError(request, error.toPeerError(), irnParams) return } sequenceStorageRepository.extendSession(request.topic, newExpiry) - relayer.respondWithSuccess(request, irnParams) + jsonRpcInteractor.respondWithSuccess(request, irnParams) scope.launch { _engineEvent.emit(session.toEngineDOSessionExtend(com.walletconnect.android.common.model.Expiry(newExpiry))) } } private fun onPing(request: WCRequest) { val irnParams = IrnParams(Tags.SESSION_PING_RESPONSE, Ttl(THIRTY_SECONDS)) - relayer.respondWithSuccess(request, irnParams) + jsonRpcInteractor.respondWithSuccess(request, irnParams) } // listened by DappDelegate @@ -745,7 +745,7 @@ internal class SignEngine( val approveParams = response.result as SessionParamsVO.ApprovalParams val responderPublicKey = PublicKey(approveParams.responderPublicKey) val sessionTopic = crypto.generateTopicFromKeyAgreement(selfPublicKey, responderPublicKey) - relayer.subscribe(sessionTopic) + jsonRpcInteractor.subscribe(sessionTopic) } is JsonRpcResponse.JsonRpcError -> { if (!pairing.isActive) sequenceStorageRepository.deletePairing(pairingTopic) @@ -769,7 +769,7 @@ internal class SignEngine( } is JsonRpcResponse.JsonRpcError -> { Logger.error("Peer failed to settle session: ${(wcResponse.response as JsonRpcResponse.JsonRpcError).errorMessage}") - relayer.unsubscribe(sessionTopic) + jsonRpcInteractor.unsubscribe(sessionTopic) sequenceStorageRepository.deleteSession(sessionTopic) crypto.removeKeys(sessionTopic.value) } @@ -831,14 +831,14 @@ internal class SignEngine( listOfExpiredPairing .map { pairing -> pairing.topic } .onEach { pairingTopic -> - relayer.unsubscribe(pairingTopic) + jsonRpcInteractor.unsubscribe(pairingTopic) crypto.removeKeys(pairingTopic.value) sequenceStorageRepository.deletePairing(pairingTopic) } listOfValidPairing .map { pairing -> pairing.topic } - .onEach { pairingTopic -> relayer.subscribe(pairingTopic) } + .onEach { pairingTopic -> jsonRpcInteractor.subscribe(pairingTopic) } } private fun resubscribeToSession() { @@ -848,18 +848,18 @@ internal class SignEngine( listOfExpiredSession .map { session -> session.topic } .onEach { sessionTopic -> - relayer.unsubscribe(sessionTopic) + jsonRpcInteractor.unsubscribe(sessionTopic) crypto.removeKeys(sessionTopic.value) sequenceStorageRepository.deleteSession(sessionTopic) } listOfValidSessions - .onEach { session -> relayer.subscribe(session.topic) } + .onEach { session -> jsonRpcInteractor.subscribe(session.topic) } } private fun setupSequenceExpiration() { sequenceStorageRepository.onSequenceExpired = { topic -> - relayer.unsubscribe(topic) + jsonRpcInteractor.unsubscribe(topic) crypto.removeKeys(topic.value) } } From 5295f1ddf6454537e4e819347162d6751678a77a Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 20 Oct 2022 16:36:33 +0200 Subject: [PATCH 02/30] Create a common dir in chat module --- .../android/common/model/Tags.kt | 13 +- .../android/common/storage/KeyChain.kt | 21 ++ .../android/common/storage/KeyStore.kt | 7 + .../impl/crypto/KeyManagementRepository.kt | 12 +- .../BouncyCastleKeyManagementRepository.kt | 60 +++++- .../impl/BouncyCastleCryptoRepositoryTest.kt | 2 +- .../com/walletconnect/chat/client/Chat.kt | 3 +- .../walletconnect/chat/client/ChatProtocol.kt | 10 +- .../chat/client/mapper/ClientMapper.kt | 16 +- .../adapter/JsonRpcResultAdapter.kt} | 43 +++-- .../json_rpc/ChatParams.kt} | 18 +- .../json_rpc/ChatRpc.kt} | 25 ++- .../chat/common/model/AccountId.kt | 10 + .../common/model/AccountIdWithPublicKey.kt | 10 + .../walletconnect/chat/common/model/Events.kt | 13 ++ .../walletconnect/chat/common/model/Invite.kt | 9 + .../walletconnect/chat/common/model/Media.kt | 8 + .../chat/common/model/Message.kt | 10 + .../walletconnect/chat/common/model/Thread.kt | 9 + .../BouncyCastleKeyManagementRepository.kt | 182 ------------------ .../chat/copiedFromSign/KeyChain.kt | 66 ------- .../copiedFromSign/KeyManagementRepository.kt | 29 --- .../chat/copiedFromSign/KeyStore.kt | 22 --- .../chat/core/model/vo/Common.kt | 40 ---- .../chat/core/model/vo/EventsVO.kt | 13 -- .../walletconnect/chat/core/model/vo/Tags.kt | 15 -- .../domain/use_case/RegisterAccountUseCase.kt | 4 +- .../domain/use_case/ResolveAccountUseCase.kt | 6 +- .../keyserver/model/KeyserverMapper.kt | 8 +- .../chat/engine/domain/ChatEngine.kt | 51 +++-- .../chat/engine/model/EngineDO.kt | 22 +-- .../data}/JsonRpcSerializer.kt | 21 +- .../chat/json_rpc/domain/JsonRpcInteractor.kt | 4 + .../model}/JsonRpcMethod.kt | 2 +- .../chat/storage/ChatStorageRepository.kt | 8 +- .../common/adapters/JsonRpcResultAdapter.kt | 14 +- .../sign/engine/domain/SignEngine.kt | 4 +- 37 files changed, 312 insertions(+), 498 deletions(-) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/{copiedFromSign/RelayDOJsonRpcResultJsonAdapter.kt => common/adapter/JsonRpcResultAdapter.kt} (72%) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/{core/model/vo/clientsync/params/ChatParamsVO.kt => common/json_rpc/ChatParams.kt} (73%) rename chat/sdk/src/main/kotlin/com/walletconnect/chat/{core/model/vo/clientsync/ChatRpcVO.kt => common/json_rpc/ChatRpc.kt} (72%) create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountId.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountIdWithPublicKey.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Events.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Invite.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Media.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Message.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Thread.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/BouncyCastleKeyManagementRepository.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyChain.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyStore.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/EventsVO.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Tags.kt rename chat/sdk/src/main/kotlin/com/walletconnect/chat/{copiedFromSign => json_rpc/data}/JsonRpcSerializer.kt (71%) create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt rename chat/sdk/src/main/kotlin/com/walletconnect/chat/{copiedFromSign => json_rpc/model}/JsonRpcMethod.kt (90%) diff --git a/androidCore/common/src/main/kotlin/com/walletconnect/android/common/model/Tags.kt b/androidCore/common/src/main/kotlin/com/walletconnect/android/common/model/Tags.kt index a00405aae2..afde764c2b 100644 --- a/androidCore/common/src/main/kotlin/com/walletconnect/android/common/model/Tags.kt +++ b/androidCore/common/src/main/kotlin/com/walletconnect/android/common/model/Tags.kt @@ -31,7 +31,18 @@ enum class Tags(val id: Int) { SESSION_PING(1114), SESSION_PING_RESPONSE(1115), + CHAT_INVITE(2000), + CHAT_INVITE_RESPONSE(2001), + + CHAT_MESSAGE(2002), + CHAT_MESSAGE_RESPONSE(2003), + + CHAT_LEAVE(2004), + CHAT_LEAVE_RESPONSE(2005), + + CHAT_PING(2006), + CHAT_PING_RESPONSE(2007), + AUTH_REQUEST(3000), AUTH_REQUEST_RESPONSE(3001) - //todo: Discuss: Should Tags be in specific SDKs? } \ No newline at end of file diff --git a/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyChain.kt b/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyChain.kt index cfd174bcc8..db59ebd773 100644 --- a/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyChain.kt +++ b/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyChain.kt @@ -4,6 +4,7 @@ package com.walletconnect.android.common.storage import android.content.SharedPreferences import com.walletconnect.foundation.common.model.Key +import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.util.Empty import com.walletconnect.util.bytesToHex import com.walletconnect.util.hexToBytes @@ -46,4 +47,24 @@ internal class KeyChain(private val sharedPreferences: SharedPreferences) : KeyS return keyA.bytesToHex() to keyB.bytesToHex() } + + // Added With Chat SDK + override fun getInviteSelfPublicKey(tag: String): String? { + return sharedPreferences.getString(tag, null) + } + + // Added With Chat SDK + override fun setInviteSelfPublicKey(tag: String, key: Key) { + sharedPreferences.edit().putString(tag, key.keyAsHex).apply() + } + + // Added With Chat SDK + override fun getPublicKey(tag: String): String { + return sharedPreferences.getString(tag, String.Empty) ?: String.Empty + } + + // Added With Chat SDK + override fun setPublicKey(tag: String, publicKey: PublicKey) { + sharedPreferences.edit().putString(tag, publicKey.keyAsHex).apply() + } } \ No newline at end of file diff --git a/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyStore.kt b/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyStore.kt index 8300202ab5..efb1ec8453 100644 --- a/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyStore.kt +++ b/androidCore/common/src/main/kotlin/com/walletconnect/android/common/storage/KeyStore.kt @@ -3,6 +3,7 @@ package com.walletconnect.android.common.storage import com.walletconnect.foundation.common.model.Key +import com.walletconnect.foundation.common.model.PublicKey interface KeyStore { fun getKey(tag: String): String @@ -14,4 +15,10 @@ interface KeyStore { fun deleteKeys(tag: String) fun checkKeys(tag: String): Boolean + + // Added With Chat SDK + fun getInviteSelfPublicKey(tag: String): String? + fun setInviteSelfPublicKey(tag: String, key: Key) + fun getPublicKey(tag: String): String + fun setPublicKey(tag: String, publicKey: PublicKey) } \ No newline at end of file diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/crypto/KeyManagementRepository.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/crypto/KeyManagementRepository.kt index 9e4eaedb77..32cccca80d 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/crypto/KeyManagementRepository.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/crypto/KeyManagementRepository.kt @@ -2,6 +2,7 @@ package com.walletconnect.android.impl.crypto import com.walletconnect.android.impl.common.model.SymmetricKey import com.walletconnect.foundation.common.model.Key +import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic @@ -12,7 +13,7 @@ interface KeyManagementRepository { fun getSymmetricKey(topic: Topic): SymmetricKey fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey - fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic + fun generateTopicFromKeyAgreementAndSafeSymKey(self: PublicKey, peer: PublicKey): Topic fun getTopicFromKey(key: Key): Topic fun getKeyAgreement(topic: Topic): Pair fun generateKeyPair(): PublicKey @@ -20,4 +21,13 @@ interface KeyManagementRepository { fun removeKeys(tag: String) fun setSelfParticipant(key: PublicKey, topic: Topic) fun getSelfParticipant(topic: Topic): PublicKey? + + //Added with Chat SDK + fun generateInviteSelfKeyPair(): Pair + fun getInviteSelfPublicKey(): PublicKey + fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) + fun getHash(string: String): String + fun getInvitePublicKey(topic: Topic): PublicKey + fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) + fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic } \ No newline at end of file diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt index 7994ed83d8..180aeb051f 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt @@ -50,7 +50,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor return PublicKey(publicKey.bytesToHex().lowercase()) } - override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic { + override fun generateTopicFromKeyAgreementAndSafeSymKey(self: PublicKey, peer: PublicKey): Topic { val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer) val topic = Topic(sha256(symmetricKey.keyAsHex)) keyChain.setKey(topic.value.lowercase(), symmetricKey) @@ -96,7 +96,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor return Pair(PublicKey(selfPublic), PublicKey(peerPublic)) } - private fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) { + override fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) { val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" keyChain.setKeys(tag, self, peer) } @@ -146,5 +146,61 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor const val KEY_AGREEMENT_CONTEXT = "key_agreement/" const val SELF_PARTICIPANT_CONTEXT = "self_participant/" + const val INVITE_CONTEXT = "invite/" + const val SELF_INVITE_PUBLIC_KEY = "selfInviteKey/" + } + + + // Added with Chat SDK + override fun generateInviteSelfKeyPair(): Pair { + val keyPair: Pair = generateWithoutSavingKeyPair() // TODO: Refactor on extracting core. + // Note: This could be cleaner with refactor of such method as generateKeyPair so it wont save keys + // Note: I wont do it here because I don't want two versions of this file + setKeyPair(keyPair.first, keyPair.second) + return keyPair + } + + // Added with Chat SDK + override fun getInviteSelfPublicKey(): PublicKey { + val publicKey = keyChain.getInviteSelfPublicKey(SELF_INVITE_PUBLIC_KEY) ?: throw Exception("TODO: Name me / Create exception") + return PublicKey(publicKey) + } + + // Added with Chat SDK + override fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) { + keyChain.setInviteSelfPublicKey(SELF_INVITE_PUBLIC_KEY, publicKey) + keyChain.setPublicKey("$INVITE_CONTEXT${topic.value}", publicKey) + } + + // Added with Chat SDK. TODO: This could be removed after proper refactor + private fun generateWithoutSavingKeyPair(): Pair { + val publicKey = ByteArray(KEY_SIZE) + val privateKey = ByteArray(KEY_SIZE) + X25519.generatePrivateKey(SecureRandom(ByteArray(KEY_SIZE)), privateKey) + X25519.generatePublicKey(privateKey, 0, publicKey, 0) + + return PublicKey(publicKey.bytesToHex().lowercase()) to PrivateKey(privateKey.bytesToHex().lowercase()) } + + // Added with Chat SDK + override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic { + val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer) + val topic = generateTopicFromSymmetricKey(symmetricKey) + setKeyAgreement(topic, self, peer) + return topic + } + + // Added with Chat SDK + private fun generateTopicFromSymmetricKey(symmetricKey: SymmetricKey): Topic { + val topic = Topic(sha256(symmetricKey.keyAsHex)) + keyChain.setKey(topic.value.lowercase(), symmetricKey) + return topic + } + + // Added with Chat SDK + override fun getHash(string: String): String = sha256(string) + + + // Added with Chat SDK + override fun getInvitePublicKey(topic: Topic): PublicKey = PublicKey(keyChain.getPublicKey("$INVITE_CONTEXT${topic.value}")) } \ No newline at end of file diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt index 4adffed8f1..5b5a926b32 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt @@ -52,7 +52,7 @@ internal class BouncyCastleCryptoRepositoryTest { @Test fun `Generate a shared key and return a Topic object`() { val peerKey = PublicKey("ff7a7d5767c362b0a17ad92299ebdb7831dcbd9a56959c01368c7404543b3342") - val topic = sut.generateTopicFromKeyAgreement(publicKey, peerKey) + val topic = sut.generateTopicFromKeyAgreementAndSafeSymKey(publicKey, peerKey) assert(topic.value.isNotBlank()) assert(topic.value.length == 64) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt index d55b9a7f53..133cb3e943 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt @@ -1,7 +1,6 @@ package com.walletconnect.chat.client import android.app.Application -import com.walletconnect.chat.core.model.vo.AccountIdVO object Chat { @@ -22,7 +21,7 @@ object Chat { @JvmInline value class AccountId(val value: String) { - fun isValid() = AccountIdVO(value).isValid() + fun isValid() = com.walletconnect.chat.common.model.AccountId(value).isValid() } data class Invite( diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index b5f43a5480..9d97c302d4 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -7,8 +7,8 @@ import com.walletconnect.android.impl.di.networkModule import com.walletconnect.chat.client.mapper.toClient import com.walletconnect.chat.client.mapper.toEngineDO import com.walletconnect.chat.client.mapper.toVO -import com.walletconnect.chat.core.model.vo.AccountIdVO -import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO +import com.walletconnect.chat.common.model.AccountId +import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.di.engineModule import com.walletconnect.chat.di.keyServerModule import com.walletconnect.chat.engine.domain.ChatEngine @@ -70,7 +70,7 @@ internal class ChatProtocol : ChatInterface { checkEngineInitialization() chatEngine.registerAccount( - AccountIdVO(register.account.value), + AccountId(register.account.value), { publicKey -> listener.onSuccess(publicKey) }, { throwable -> listener.onError(Chat.Model.Error(throwable)) }, register.private ?: false @@ -82,7 +82,7 @@ internal class ChatProtocol : ChatInterface { checkEngineInitialization() chatEngine.resolveAccount( - AccountIdVO(resolve.account.value), + AccountId(resolve.account.value), { publicKey -> listener.onSuccess(publicKey) }, { throwable -> listener.onError(Chat.Model.Error(throwable)) } ) @@ -133,7 +133,7 @@ internal class ChatProtocol : ChatInterface { @Throws(IllegalStateException::class) override fun addContact(addContact: Chat.Params.AddContact, onError: (Chat.Model.Error) -> Unit) { checkEngineInitialization() - chatEngine.addContact(AccountIdWithPublicKeyVO(addContact.account.toVO(), PublicKey(addContact.publicKey))) { error -> + chatEngine.addContact(AccountIdWithPublicKey(addContact.account.toVO(), PublicKey(addContact.publicKey))) { error -> onError(Chat.Model.Error(error)) } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt index e620108666..365508ff22 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt @@ -3,8 +3,8 @@ package com.walletconnect.chat.client.mapper import com.walletconnect.chat.client.Chat -import com.walletconnect.chat.core.model.vo.AccountIdVO -import com.walletconnect.chat.core.model.vo.MediaVO +import com.walletconnect.chat.common.model.AccountId +import com.walletconnect.chat.common.model.Media import com.walletconnect.chat.engine.model.EngineDO //TODO: Figure out what to do with models separation @@ -19,13 +19,13 @@ internal fun Chat.Params.Message.toEngineDO(): EngineDO.SendMessage { } @JvmSynthetic -private fun Chat.Model.Media.toVO(): MediaVO { - return MediaVO(type, data) +private fun Chat.Model.Media.toVO(): Media { + return Media(type, data) } @JvmSynthetic -internal fun Chat.Model.AccountId.toVO(): AccountIdVO { - return AccountIdVO(value) +internal fun Chat.Model.AccountId.toVO(): AccountId { + return AccountId(value) } @JvmSynthetic @@ -39,12 +39,12 @@ internal fun EngineDO.Invite.toClient(): Chat.Model.Invite { } @JvmSynthetic -internal fun AccountIdVO.toClient(): Chat.Model.AccountId { +internal fun AccountId.toClient(): Chat.Model.AccountId { return Chat.Model.AccountId(value) } @JvmSynthetic -internal fun MediaVO.toClient(): Chat.Model.Media { +internal fun Media.toClient(): Chat.Model.Media { return Chat.Model.Media(type, data) } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/RelayDOJsonRpcResultJsonAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/adapter/JsonRpcResultAdapter.kt similarity index 72% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/RelayDOJsonRpcResultJsonAdapter.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/common/adapter/JsonRpcResultAdapter.kt index a8cbea6c9c..e68fa1c8f4 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/RelayDOJsonRpcResultJsonAdapter.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/adapter/JsonRpcResultAdapter.kt @@ -1,13 +1,14 @@ @file:JvmSynthetic -package com.walletconnect.chat.copiedFromSign +package com.walletconnect.chat.common.adapter import com.squareup.moshi.JsonAdapter import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import com.squareup.moshi.Moshi import com.squareup.moshi.internal.Util -import com.walletconnect.chat.core.model.vo.clientsync.params.ChatParamsVO +import com.walletconnect.android.common.JsonRpcResponse +import com.walletconnect.chat.common.json_rpc.ChatParams import org.json.JSONArray import org.json.JSONObject import java.lang.reflect.Constructor @@ -16,23 +17,23 @@ import kotlin.Long import kotlin.String //todo: when extracted to core code for serialising both SessionParamsVO.ApprovalParams and ChatParamsVO.ApprovalParams -internal class RelayDOJsonRpcResultJsonAdapter(moshi: Moshi) : JsonAdapter() { +internal class JsonRpcResultAdapter(moshi: Moshi) : JsonAdapter() { private val options: JsonReader.Options = JsonReader.Options.of("id", "jsonrpc", "result") private val longAdapter: JsonAdapter = moshi.adapter(Long::class.java, emptySet(), "id") private val stringAdapter: JsonAdapter = moshi.adapter(String::class.java, emptySet(), "jsonrpc") private val booleanAdapter: JsonAdapter = moshi.adapter(Boolean::class.java, emptySet(), "result") private val anyAdapter: JsonAdapter = moshi.adapter(Any::class.java, emptySet(), "result") - private val acceptanceParamsAdapter: JsonAdapter = - moshi.adapter(ChatParamsVO.AcceptanceParams::class.java) + private val acceptanceParamsAdapter: JsonAdapter = + moshi.adapter(ChatParams.AcceptanceParams::class.java) @Volatile - private var constructorRef: Constructor? = null + private var constructorRef: Constructor? = null override fun toString(): String = buildString(59) { append("GeneratedJsonAdapter(").append("RelayDO.JsonRpcResponse.JsonRpcResult").append(')') } - override fun fromJson(reader: JsonReader): RelayerDO.JsonRpcResponse.JsonRpcResult { + override fun fromJson(reader: JsonReader): JsonRpcResponse.JsonRpcResult { var id: Long? = null var jsonrpc: String? = null var result: Any? = null @@ -42,8 +43,10 @@ internal class RelayDOJsonRpcResultJsonAdapter(moshi: Moshi) : JsonAdapter id = longAdapter.fromJson(reader) ?: throw Util.unexpectedNull("id", "id", reader) 1 -> { - jsonrpc = stringAdapter.fromJson(reader) ?: throw Util.unexpectedNull("jsonrpc", - "jsonrpc", reader) + jsonrpc = stringAdapter.fromJson(reader) ?: throw Util.unexpectedNull( + "jsonrpc", + "jsonrpc", reader + ) // $mask = $mask and (1 shl 1).inv() mask0 = mask0 and 0xfffffffd.toInt() } @@ -64,7 +67,7 @@ internal class RelayDOJsonRpcResultJsonAdapter(moshi: Moshi) : JsonAdapter = + val localConstructor: Constructor = this.constructorRef - ?: RelayerDO.JsonRpcResponse.JsonRpcResult::class.java.getDeclaredConstructor(Long::class.javaPrimitiveType, + ?: JsonRpcResponse.JsonRpcResult::class.java.getDeclaredConstructor( + Long::class.javaPrimitiveType, String::class.java, Any::class.java, Int::class.javaPrimitiveType, - Util.DEFAULT_CONSTRUCTOR_MARKER).also { this.constructorRef = it } + Util.DEFAULT_CONSTRUCTOR_MARKER + ).also { this.constructorRef = it } return localConstructor.newInstance( id ?: throw Util.missingProperty("id", "id", reader), jsonrpc, @@ -87,7 +92,7 @@ internal class RelayDOJsonRpcResultJsonAdapter(moshi: Moshi) : JsonAdapter { - val approvalParamsString = acceptanceParamsAdapter.toJson(value_.result) + (value_.result as? ChatParams.AcceptanceParams) != null -> { + val approvalParamsString = acceptanceParamsAdapter.toJson(value_.result as ChatParams.AcceptanceParams) writer.valueSink().use { it.writeUtf8(approvalParamsString) } } - value_.result is String && value_.result.startsWith("{") -> { + value_.result is String && (value_.result as String).startsWith("{") -> { writer.valueSink().use { - it.writeUtf8(JSONObject(value_.result).toString()) + it.writeUtf8(JSONObject(value_.result as String).toString()) } } - value_.result is String && value_.result.startsWith("[") -> { + value_.result is String && (value_.result as String).startsWith("[") -> { writer.valueSink().use { it.writeUtf8(JSONArray(value_.result).toString()) } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/params/ChatParamsVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatParams.kt similarity index 73% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/params/ChatParamsVO.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatParams.kt index fcc4d4f22f..9d1ba58b42 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/params/ChatParamsVO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatParams.kt @@ -1,11 +1,11 @@ -package com.walletconnect.chat.core.model.vo.clientsync.params +package com.walletconnect.chat.common.json_rpc import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import com.walletconnect.android.impl.common.model.type.ClientParams -import com.walletconnect.chat.core.model.vo.MediaVO +import com.walletconnect.chat.common.model.Media -internal sealed class ChatParamsVO : ClientParams { +internal sealed class ChatParams : ClientParams { @JsonClass(generateAdapter = true) internal data class InviteParams( @@ -17,13 +17,13 @@ internal sealed class ChatParamsVO : ClientParams { val publicKey: String, @Json(name = "signature") val signature: String?, - ) : ChatParamsVO() + ) : ChatParams() @JsonClass(generateAdapter = true) internal data class AcceptanceParams( @Json(name = "publicKey") val publicKey: String, - ) : ChatParamsVO() + ) : ChatParams() @JsonClass(generateAdapter = true) internal data class MessageParams( @@ -34,12 +34,12 @@ internal sealed class ChatParamsVO : ClientParams { @Json(name = "timestamp") val timestamp: Long, @Json(name = "media") - val media: MediaVO?, - ) : ChatParamsVO() + val media: Media?, + ) : ChatParams() @Suppress("CanSealedSubClassBeObject") - internal class PingParams : ChatParamsVO() + internal class PingParams : ChatParams() @Suppress("CanSealedSubClassBeObject") - internal class LeaveParams : ChatParamsVO() + internal class LeaveParams : ChatParams() } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/ChatRpcVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt similarity index 72% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/ChatRpcVO.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt index b3df54a36e..3385157134 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/clientsync/ChatRpcVO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt @@ -1,16 +1,15 @@ -package com.walletconnect.chat.core.model.vo.clientsync +package com.walletconnect.chat.common.json_rpc import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import com.walletconnect.android.impl.common.model.type.JsonRpcClientSync -import com.walletconnect.chat.copiedFromSign.JsonRpcMethod -import com.walletconnect.chat.core.model.vo.clientsync.params.ChatParamsVO +import com.walletconnect.chat.json_rpc.model.JsonRpcMethod -internal sealed class ChatRpcVO : JsonRpcClientSync { +internal sealed class ChatRpc : JsonRpcClientSync { abstract override val id: Long abstract override val method: String abstract override val jsonrpc: String - abstract override val params: ChatParamsVO + abstract override val params: ChatParams @JsonClass(generateAdapter = true) internal data class ChatInvite( @@ -21,8 +20,8 @@ internal sealed class ChatRpcVO : JsonRpcClientSync { @Json(name = "method") override val method: String = JsonRpcMethod.WC_CHAT_INVITE, @Json(name = "params") - override val params: ChatParamsVO.InviteParams, - ) : ChatRpcVO() + override val params: ChatParams.InviteParams, + ) : ChatRpc() @JsonClass(generateAdapter = true) internal data class ChatMessage( @@ -33,8 +32,8 @@ internal sealed class ChatRpcVO : JsonRpcClientSync { @Json(name = "method") override val method: String = JsonRpcMethod.WC_CHAT_MESSAGE, @Json(name = "params") - override val params: ChatParamsVO.MessageParams, - ) : ChatRpcVO() + override val params: ChatParams.MessageParams, + ) : ChatRpc() @JsonClass(generateAdapter = true) internal data class ChatPing( @@ -45,8 +44,8 @@ internal sealed class ChatRpcVO : JsonRpcClientSync { @Json(name = "method") override val method: String = JsonRpcMethod.WC_CHAT_PING, @Json(name = "params") - override val params: ChatParamsVO.PingParams, - ) : ChatRpcVO() + override val params: ChatParams.PingParams, + ) : ChatRpc() @JsonClass(generateAdapter = true) internal data class ChatLeave( @@ -57,6 +56,6 @@ internal sealed class ChatRpcVO : JsonRpcClientSync { @Json(name = "method") override val method: String = JsonRpcMethod.WC_CHAT_LEAVE, @Json(name = "params") - override val params: ChatParamsVO.LeaveParams, - ) : ChatRpcVO() + override val params: ChatParams.LeaveParams, + ) : ChatRpc() } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountId.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountId.kt new file mode 100644 index 0000000000..07c60c4837 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountId.kt @@ -0,0 +1,10 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.common.model + +import com.walletconnect.chat.engine.domain.Validator + +@JvmInline +internal value class AccountId(val value: String) { + fun isValid(): Boolean = Validator.isAccountIdCAIP10Compliant(value) +} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountIdWithPublicKey.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountIdWithPublicKey.kt new file mode 100644 index 0000000000..48df20cf0e --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/AccountIdWithPublicKey.kt @@ -0,0 +1,10 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.common.model + +import com.walletconnect.foundation.common.model.PublicKey + +internal data class AccountIdWithPublicKey( + val accountId: AccountId, + val publicKey: PublicKey, +) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Events.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Events.kt new file mode 100644 index 0000000000..7771114d53 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Events.kt @@ -0,0 +1,13 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.common.model + +internal sealed class Events { + data class OnInvite(val id: Int, val invite: Invite) : Events() + + data class OnJoined(val topic: String) : Events() + + data class OnMessage(val topic: String, val message: Message) : Events() + + data class OnLeft(val topic: String) : Events() +} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Invite.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Invite.kt new file mode 100644 index 0000000000..55cf5456b4 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Invite.kt @@ -0,0 +1,9 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.common.model + +internal data class Invite( + val account: String, + val message: String, + val signature: String? = null +) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Media.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Media.kt new file mode 100644 index 0000000000..9d0685fb39 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Media.kt @@ -0,0 +1,8 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.common.model + +internal data class Media( + val type: String, + val data: String, +) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Message.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Message.kt new file mode 100644 index 0000000000..c6683f2718 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Message.kt @@ -0,0 +1,10 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.common.model + +internal data class Message( + val message: String, + val authorAccount: String, + val timestamp: Long, + val media: Media +) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Thread.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Thread.kt new file mode 100644 index 0000000000..b2f4e9a0b4 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Thread.kt @@ -0,0 +1,9 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.common.model + +internal data class Thread( + val topic: String, + val selfAccount: String, + val peerAccount: String, +) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/BouncyCastleKeyManagementRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/BouncyCastleKeyManagementRepository.kt deleted file mode 100644 index 695f4527a4..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/BouncyCastleKeyManagementRepository.kt +++ /dev/null @@ -1,182 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign - -import com.walletconnect.android.impl.common.model.SymmetricKey -import com.walletconnect.foundation.common.model.Key -import com.walletconnect.foundation.common.model.PrivateKey -import com.walletconnect.foundation.common.model.PublicKey -import com.walletconnect.foundation.common.model.Topic -import com.walletconnect.util.bytesToHex -import com.walletconnect.util.hexToBytes -import org.bouncycastle.crypto.digests.SHA256Digest -import org.bouncycastle.crypto.generators.HKDFBytesGenerator -import org.bouncycastle.crypto.params.HKDFParameters -import org.bouncycastle.math.ec.rfc7748.X25519 -import java.security.MessageDigest -import java.security.SecureRandom -import javax.crypto.KeyGenerator - -//todo: use KeyChain from android_common -internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStore) : KeyManagementRepository { - - override fun generateSymmetricKey(topic: Topic): SymmetricKey { - val symmetricKey = createSymmetricKey().bytesToHex() - keyChain.setSymmetricKey(topic.value, SymmetricKey(symmetricKey)) - - return SymmetricKey(symmetricKey) - } - - override fun setSymmetricKey(topic: Topic, symmetricKey: SymmetricKey) { - keyChain.setSymmetricKey(topic.value, symmetricKey) - } - - override fun getSymmetricKey(topic: Topic): SymmetricKey { - val symmetricKey = keyChain.getSymmetricKey(topic.value) - - return SymmetricKey(symmetricKey) - } - - override fun generateKeyPair(): PublicKey { - val publicKey = ByteArray(KEY_SIZE) - val privateKey = ByteArray(KEY_SIZE) - X25519.generatePrivateKey(SecureRandom(ByteArray(KEY_SIZE)), privateKey) - X25519.generatePublicKey(privateKey, 0, publicKey, 0) - setKeyPair(PublicKey(publicKey.bytesToHex().lowercase()), PrivateKey(privateKey.bytesToHex().lowercase())) - - return PublicKey(publicKey.bytesToHex().lowercase()) - } - - - override fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey { - val (_, privateKey) = getKeyPair(self) - val sharedSecretBytes = ByteArray(KEY_SIZE) - X25519.scalarMult(privateKey.keyAsHex.hexToBytes(), 0, peer.keyAsHex.hexToBytes(), 0, sharedSecretBytes, 0) - val sharedSecret = sharedSecretBytes.bytesToHex() - val symmetricKeyBytes = deriveHKDFKey(sharedSecret) - - return SymmetricKey(symmetricKeyBytes.bytesToHex()) - } - - override fun removeKeys(tag: String) { - val (_, publicKey) = keyChain.getKeys(tag) - with(keyChain) { - deleteKeys(publicKey.lowercase()) - deleteKeys(tag) - } - } - - override fun getKeyAgreement(topic: Topic): Pair { - val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" - val (selfPublic, peerPublic) = keyChain.getKeys(tag) - - return Pair(PublicKey(selfPublic), PublicKey(peerPublic)) - } - - // Added with Chat SDK - override fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) { - val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" - keyChain.setKeys(tag, self, peer) - } - - internal fun setKeyPair(publicKey: PublicKey, privateKey: PrivateKey) { - keyChain.setKeys(publicKey.keyAsHex, publicKey, privateKey) - } - - internal fun getKeyPair(key: Key): Pair { - val (publicKeyHex, privateKeyHex) = keyChain.getKeys(key.keyAsHex) - - return Pair(PublicKey(publicKeyHex), PrivateKey(privateKeyHex)) - } - - private fun createSymmetricKey(): ByteArray { - val keyGenerator: KeyGenerator = KeyGenerator.getInstance(AES) - keyGenerator.init(SYM_KEY_SIZE) - - return keyGenerator.generateKey().encoded - } - - private fun sha256(key: String): String { - val messageDigest: MessageDigest = MessageDigest.getInstance(SHA_256) - val hashedBytes: ByteArray = messageDigest.digest(key.hexToBytes()) - - return hashedBytes.bytesToHex() - } - - private fun deriveHKDFKey(sharedSecret: String): ByteArray { - val hkdf = HKDFBytesGenerator(SHA256Digest()) - val inputKeyMaterial = sharedSecret.hexToBytes() - val salt = ByteArray(0) - val info = ByteArray(0) - val hkdfParameters = HKDFParameters(inputKeyMaterial, salt, info) - val derivedKey = ByteArray(KEY_SIZE) - hkdf.init(hkdfParameters) - hkdf.generateBytes(derivedKey, 0, KEY_SIZE) - - return derivedKey - } - - private companion object { - const val KEY_SIZE: Int = 32 - const val SYM_KEY_SIZE: Int = 256 - const val SHA_256: String = "SHA-256" - const val AES: String = "AES" - - const val KEY_AGREEMENT_CONTEXT = "key_agreement/" - const val INVITE_CONTEXT = "invite/" - const val SELF_INVITE_PUBLIC_KEY = "selfInviteKey" - } - - // Added with Chat SDK - override fun generateInviteSelfKeyPair(): Pair { - val keyPair: Pair = generateWithoutSavingKeyPair() // TODO: Refactor on extracting core. - // Note: This could be cleaner with refactor of such method as generateKeyPair so it wont save keys - // Note: I wont do it here because I don't want two versions of this file - setKeyPair(keyPair.first, keyPair.second) - return keyPair - } - - // Added with Chat SDK - override fun getInviteSelfPublicKey(): PublicKey { - val publicKey = keyChain.getInviteSelfPublicKey(SELF_INVITE_PUBLIC_KEY) ?: throw Exception("TODO: Name me / Create exception") - return PublicKey(publicKey) - } - - // Added with Chat SDK - override fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) { - keyChain.setInviteSelfPublicKey(SELF_INVITE_PUBLIC_KEY, publicKey) - keyChain.setPublicKey("$INVITE_CONTEXT${topic.value}", publicKey) - } - - // Added with Chat SDK. TODO: This could be removed after proper refactor - private fun generateWithoutSavingKeyPair(): Pair { - val publicKey = ByteArray(KEY_SIZE) - val privateKey = ByteArray(KEY_SIZE) - X25519.generatePrivateKey(SecureRandom(ByteArray(KEY_SIZE)), privateKey) - X25519.generatePublicKey(privateKey, 0, publicKey, 0) - - return PublicKey(publicKey.bytesToHex().lowercase()) to PrivateKey(privateKey.bytesToHex().lowercase()) - } - - // Added with Chat SDK - override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic { - val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer) - val topic = generateTopicFromSymmetricKey(symmetricKey) - setKeyAgreement(topic, self, peer) - return topic - } - - // Added with Chat SDK - private fun generateTopicFromSymmetricKey(symmetricKey: SymmetricKey): Topic { - val topic = Topic(sha256(symmetricKey.keyAsHex)) - keyChain.setSymmetricKey(topic.value.lowercase(), symmetricKey) - return topic - } - - // Added with Chat SDK - override fun getHash(string: String): String = sha256(string) - - - // Added with Chat SDK - override fun getInvitePublicKey(topic: Topic): PublicKey = PublicKey(keyChain.getPublicKey("$INVITE_CONTEXT${topic.value}")) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyChain.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyChain.kt deleted file mode 100644 index c12a919d73..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyChain.kt +++ /dev/null @@ -1,66 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign - -import android.content.SharedPreferences -import com.walletconnect.foundation.common.model.Key -import com.walletconnect.util.Empty -import com.walletconnect.util.bytesToHex -import com.walletconnect.util.hexToBytes - -//todo: use KeyChain from android_common -internal class KeyChain(private val sharedPreferences: SharedPreferences) : KeyStore { - - override fun setSymmetricKey(tag: String, key: Key) { - sharedPreferences.edit().putString(tag, key.keyAsHex).apply() - } - - override fun getSymmetricKey(tag: String): String { - return sharedPreferences.getString(tag, String.Empty) ?: String.Empty - } - - override fun setKeys(tag: String, key1: Key, key2: Key) { - val keys = concatKeys(key1, key2) - sharedPreferences.edit().putString(tag, keys).apply() - } - - - override fun getKeys(tag: String): Pair { - val concatKeys = sharedPreferences.getString(tag, String.Empty) ?: String.Empty - return splitKeys(concatKeys) - } - - override fun deleteKeys(tag: String) { - sharedPreferences.edit().remove(tag).apply() - } - - private fun concatKeys(keyA: Key, keyB: Key): String = (keyA.keyAsHex.hexToBytes() + keyB.keyAsHex.hexToBytes()).bytesToHex() - - private fun splitKeys(concatKeys: String): Pair { - val concatKeysByteArray = concatKeys.hexToBytes() - val privateKeyByteArray = concatKeysByteArray.sliceArray(0 until (concatKeysByteArray.size / 2)) - val publicKeyByteArray = concatKeysByteArray.sliceArray((concatKeysByteArray.size / 2) until concatKeysByteArray.size) - return privateKeyByteArray.bytesToHex() to publicKeyByteArray.bytesToHex() - } - - // Added With Chat SDK - override fun getInviteSelfPublicKey(tag: String): String? { - return sharedPreferences.getString(tag, null) - } - - // Added With Chat SDK - override fun setInviteSelfPublicKey(tag: String, key: Key) { - sharedPreferences.edit().putString(tag, key.keyAsHex).apply() - - } - - // Added With Chat SDK - override fun getPublicKey(tag: String): String { - return sharedPreferences.getString(tag, String.Empty) ?: String.Empty - } - - // Added With Chat SDK - override fun setPublicKey(tag: String, publicKey: PublicKey) { - sharedPreferences.edit().putString(tag, publicKey.keyAsHex).apply() - } -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt deleted file mode 100644 index fe344c7dee..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyManagementRepository.kt +++ /dev/null @@ -1,29 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign - -import com.walletconnect.android.impl.common.model.SymmetricKey -import com.walletconnect.foundation.common.model.PrivateKey -import com.walletconnect.foundation.common.model.PublicKey -import com.walletconnect.foundation.common.model.Topic - -internal interface KeyManagementRepository { - fun generateSymmetricKey(topic: Topic): SymmetricKey - fun setSymmetricKey(topic: Topic, symmetricKey: SymmetricKey) - fun getSymmetricKey(topic: Topic): SymmetricKey - - fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey - fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic - fun getKeyAgreement(topic: Topic): Pair - fun generateKeyPair(): PublicKey - - fun removeKeys(tag: String) - - //Added with Chat SDK - fun generateInviteSelfKeyPair(): Pair - fun getInviteSelfPublicKey(): PublicKey - fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) - fun getHash(string: String): String - fun getInvitePublicKey(topic: Topic): PublicKey - fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyStore.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyStore.kt deleted file mode 100644 index 8b1b13307a..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/KeyStore.kt +++ /dev/null @@ -1,22 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.copiedFromSign - -import com.walletconnect.foundation.common.model.Key -import com.walletconnect.foundation.common.model.PublicKey - -internal interface KeyStore { - fun setSymmetricKey(tag: String, key: Key) - fun getSymmetricKey(tag: String): String - - fun setKeys(tag: String, key1: Key, key2: Key) - fun getKeys(tag: String): Pair - - fun deleteKeys(tag: String) - - // Added With Chat SDK - fun getInviteSelfPublicKey(tag: String): String? - fun setInviteSelfPublicKey(tag: String, key: Key) - fun getPublicKey(tag: String): String - fun setPublicKey(tag: String, publicKey: PublicKey) -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt deleted file mode 100644 index d78f96ca86..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Common.kt +++ /dev/null @@ -1,40 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.core.model.vo - -import com.walletconnect.chat.engine.domain.Validator -import com.walletconnect.foundation.common.model.PublicKey - -@JvmInline -internal value class AccountIdVO(val value: String) { - fun isValid(): Boolean = Validator.isAccountIdCAIP10Compliant(value) -} - -internal data class AccountIdWithPublicKeyVO( - val accountId: AccountIdVO, - val publicKey: PublicKey, -) - -internal data class InviteVO( - val account: String, - val message: String, - val signature: String? = null -) - -internal data class MediaVO( - val type: String, - val data: String, -) - -internal data class ThreadVO( - val topic: String, - val selfAccount: String, - val peerAccount: String, -) - -internal data class MessageVO( - val message: String, - val authorAccount: String, - val timestamp: Long, - val media: MediaVO -) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/EventsVO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/EventsVO.kt deleted file mode 100644 index 36abf817b9..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/EventsVO.kt +++ /dev/null @@ -1,13 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.core.model.vo - -internal sealed class EventsVO { - data class OnInvite(val id: Int, val invite: InviteVO) : EventsVO() - - data class OnJoined(val topic: String) : EventsVO() - - data class OnMessage(val topic: String, val message: MessageVO) : EventsVO() - - data class OnLeft(val topic: String) : EventsVO() -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Tags.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Tags.kt deleted file mode 100644 index 8d83f294ad..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/core/model/vo/Tags.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.walletconnect.chat.core.model.vo - -enum class Tags(val id: Int) { - CHAT_INVITE(2000), - CHAT_INVITE_RESPONSE(2001), - - CHAT_MESSAGE(2002), - CHAT_MESSAGE_RESPONSE(2003), - - CHAT_LEAVE(2004), - CHAT_LEAVE_RESPONSE(2005), - - CHAT_PING(2006), - CHAT_PING_RESPONSE(2007), -} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/RegisterAccountUseCase.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/RegisterAccountUseCase.kt index 0d5aae3990..5b33f97cba 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/RegisterAccountUseCase.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/RegisterAccountUseCase.kt @@ -2,14 +2,14 @@ package com.walletconnect.chat.discovery.keyserver.domain.use_case -import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO +import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.discovery.keyserver.data.client.KeyServerClient import com.walletconnect.chat.discovery.keyserver.model.toDTOAccount internal class RegisterAccountUseCase( private val client: KeyServerClient, ) { - suspend operator fun invoke(accountIdWithPublicKeyVO: AccountIdWithPublicKeyVO): Result = try { + suspend operator fun invoke(accountIdWithPublicKeyVO: AccountIdWithPublicKey): Result = try { client.register(accountIdWithPublicKeyVO.toDTOAccount()) Result.success(Unit) } catch (e: Exception) { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/ResolveAccountUseCase.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/ResolveAccountUseCase.kt index 5603505f23..7e059544fd 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/ResolveAccountUseCase.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/domain/use_case/ResolveAccountUseCase.kt @@ -2,15 +2,15 @@ package com.walletconnect.chat.discovery.keyserver.domain.use_case -import com.walletconnect.chat.core.model.vo.AccountIdVO -import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO +import com.walletconnect.chat.common.model.AccountId +import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.discovery.keyserver.data.client.KeyServerClient import com.walletconnect.chat.discovery.keyserver.model.toVOAccount internal class ResolveAccountUseCase( private val client: KeyServerClient, ) { - suspend operator fun invoke(accountId: AccountIdVO): Result = try { + suspend operator fun invoke(accountId: AccountId): Result = try { val accountVO = client.resolve(accountId.value).toVOAccount() Result.success(accountVO) } catch (e: Exception) { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt index af14b48903..e1b0fc70b6 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/discovery/keyserver/model/KeyserverMapper.kt @@ -2,12 +2,12 @@ package com.walletconnect.chat.discovery.keyserver.model -import com.walletconnect.chat.core.model.vo.AccountIdVO -import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO +import com.walletconnect.chat.common.model.AccountId +import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.foundation.common.model.PublicKey @JvmSynthetic -internal fun KeyServerDTO.Account.toVOAccount(): AccountIdWithPublicKeyVO = AccountIdWithPublicKeyVO(AccountIdVO(account), PublicKey(publicKey)) +internal fun KeyServerDTO.Account.toVOAccount(): AccountIdWithPublicKey = AccountIdWithPublicKey(AccountId(account), PublicKey(publicKey)) @JvmSynthetic -internal fun AccountIdWithPublicKeyVO.toDTOAccount(): KeyServerDTO.Account = KeyServerDTO.Account(accountId.value, publicKey.keyAsHex) \ No newline at end of file +internal fun AccountIdWithPublicKey.toDTOAccount(): KeyServerDTO.Account = KeyServerDTO.Account(accountId.value, publicKey.keyAsHex) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 7d0edcf136..9693546f6d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -12,11 +12,10 @@ import com.walletconnect.android.impl.common.model.sync.WCResponse import com.walletconnect.android.impl.common.model.type.enums.EnvelopeType import com.walletconnect.android.impl.utils.Logger import com.walletconnect.chat.copiedFromSign.KeyManagementRepository -import com.walletconnect.chat.core.model.vo.AccountIdVO -import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO -import com.walletconnect.chat.core.model.vo.Tags -import com.walletconnect.chat.core.model.vo.clientsync.ChatRpcVO -import com.walletconnect.chat.core.model.vo.clientsync.params.ChatParamsVO +import com.walletconnect.chat.common.model.AccountId +import com.walletconnect.chat.common.model.AccountIdWithPublicKey +import com.walletconnect.chat.common.json_rpc.ChatRpc +import com.walletconnect.chat.common.json_rpc.ChatParams import com.walletconnect.chat.discovery.keyserver.domain.use_case.RegisterAccountUseCase import com.walletconnect.chat.discovery.keyserver.domain.use_case.ResolveAccountUseCase import com.walletconnect.chat.engine.model.EngineDO @@ -60,7 +59,7 @@ internal class ChatEngine( } - internal fun resolveAccount(accountId: AccountIdVO, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { + internal fun resolveAccount(accountId: AccountId, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { scope.launch { supervisorScope { resolveAccountUseCase(accountId).fold( @@ -72,7 +71,7 @@ internal class ChatEngine( } internal fun registerAccount( - accountId: AccountIdVO, + accountId: AccountId, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit, private: Boolean, @@ -89,7 +88,7 @@ internal class ChatEngine( if (!private) { scope.launch { supervisorScope { - registerAccountUseCase(AccountIdWithPublicKeyVO(accountId, publicKey)).fold( + registerAccountUseCase(AccountIdWithPublicKey(accountId, publicKey)).fold( onSuccess = { _onSuccess(publicKey) }, onFailure = { error -> onFailure(error) } ) @@ -112,7 +111,7 @@ internal class ChatEngine( } } - internal fun invite(peerAccount: AccountIdVO, invite: EngineDO.Invite, onFailure: (Throwable) -> Unit) = try { + internal fun invite(peerAccount: AccountId, invite: EngineDO.Invite, onFailure: (Throwable) -> Unit) = try { val senderPublicKey = keyManagementRepository.generateKeyPair() // KeyPair Y val contact = chatStorage.getContact(peerAccount) @@ -125,8 +124,8 @@ internal class ChatEngine( val participantsVO = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = receiverPublicKey) - val inviteParams = ChatParamsVO.InviteParams(invite.message, invite.accountId.value, senderPublicKey.keyAsHex, invite.signature) - val payload = ChatRpcVO.ChatInvite(id = generateId(), params = inviteParams) + val inviteParams = ChatParams.InviteParams(invite.message, invite.accountId.value, senderPublicKey.keyAsHex, invite.signature) + val payload = ChatRpc.ChatInvite(id = generateId(), params = inviteParams) val acceptTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) keyManagementRepository.setSymmetricKey(acceptTopic, symmetricKey) @@ -154,7 +153,7 @@ internal class ChatEngine( } is JsonRpcResponse.JsonRpcResult -> { Logger.log("Chat invite was accepted") - val acceptParams = response.result as ChatParamsVO.AcceptanceParams + val acceptParams = response.result as ChatParams.AcceptanceParams val pubKeyZ = PublicKey(acceptParams.publicKey) // PubKey Z val (selfPubKey, _) = keyManagementRepository.getKeyAgreement(wcResponse.topic) val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(selfPubKey, pubKeyZ) // SymKey T @@ -168,12 +167,12 @@ internal class ChatEngine( } } - private fun onInviteRequest(wcRequest: WCRequest, params: ChatParamsVO.InviteParams) { + private fun onInviteRequest(wcRequest: WCRequest, params: ChatParams.InviteParams) { inviteRequestMap[wcRequest.id] = wcRequest // todo when to remove it? scope.launch { _events.emit(EngineDO.Events.OnInvite(wcRequest.id, - EngineDO.Invite(AccountIdVO(params.account), params.message, params.signature))) + EngineDO.Invite(AccountId(params.account), params.message, params.signature))) } //TODO: Add adding invites to storage. For MVP we will use only emitted event. @@ -182,7 +181,7 @@ internal class ChatEngine( internal fun accept(inviteId: Long, onFailure: (Throwable) -> Unit) = try { val request = inviteRequestMap[inviteId] ?: throw GenericException("No request for inviteId") - val senderPublicKey = PublicKey((request.params as ChatParamsVO.InviteParams).publicKey) // PubKey Y + val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) // PubKey Y inviteRequestMap.remove(inviteId) val invitePublicKey = keyManagementRepository.getInviteSelfPublicKey() // PubKey X @@ -193,7 +192,7 @@ internal class ChatEngine( val publicKey = keyManagementRepository.generateKeyPair() // KeyPair Z - val acceptanceParams = ChatParamsVO.AcceptanceParams(publicKey.keyAsHex) + val acceptanceParams = ChatParams.AcceptanceParams(publicKey.keyAsHex) val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(Time.dayInSeconds)) jsonRpcInteractor.respondWithParams(request.copy(topic = acceptTopic), acceptanceParams, irnParams, EnvelopeType.ZERO) @@ -222,8 +221,8 @@ internal class ChatEngine( internal fun message(topic: String, sendMessage: EngineDO.SendMessage, onFailure: (Throwable) -> Unit) { //todo resolve AUTHOR_ACCOUNT from thread storage by topic val messageParams = - ChatParamsVO.MessageParams(sendMessage.message, sendMessage.author.value, System.currentTimeMillis(), sendMessage.media) - val payload = ChatRpcVO.ChatMessage(id = generateId(), params = messageParams) + ChatParams.MessageParams(sendMessage.message, sendMessage.author.value, System.currentTimeMillis(), sendMessage.media) + val payload = ChatRpc.ChatMessage(id = generateId(), params = messageParams) val irnParams = IrnParams(Tags.CHAT_MESSAGE, Ttl(Time.dayInSeconds), true) jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, payload, EnvelopeType.ZERO, @@ -234,10 +233,10 @@ internal class ChatEngine( }) } - private fun onMessage(wcRequest: WCRequest, params: ChatParamsVO.MessageParams) { + private fun onMessage(wcRequest: WCRequest, params: ChatParams.MessageParams) { scope.launch { _events.emit(EngineDO.Events.OnMessage(wcRequest.topic.value, - EngineDO.Message(params.message, AccountIdVO(params.authorAccount), params.timestamp, params.media))) + EngineDO.Message(params.message, AccountId(params.authorAccount), params.timestamp, params.media))) } //TODO: Add adding messages to storage. For MVP we will use only emitted event. @@ -245,8 +244,8 @@ internal class ChatEngine( internal fun leave(topic: String, onFailure: (Throwable) -> Unit) { //todo: correct define params - val leaveParams = ChatParamsVO.LeaveParams() - val payload = ChatRpcVO.ChatLeave(id = generateId(), params = leaveParams) + val leaveParams = ChatParams.LeaveParams() + val payload = ChatRpc.ChatLeave(id = generateId(), params = leaveParams) val irnParams = IrnParams(Tags.CHAT_LEAVE, Ttl(Time.dayInSeconds), true) jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, payload, EnvelopeType.ZERO, @@ -265,8 +264,8 @@ internal class ChatEngine( scope.launch { jsonRpcInteractor.clientSyncJsonRpc.collect { request -> when (val params = request.params) { - is ChatParamsVO.InviteParams -> onInviteRequest(request, params) - is ChatParamsVO.MessageParams -> onMessage(request, params) + is ChatParams.InviteParams -> onInviteRequest(request, params) + is ChatParams.MessageParams -> onMessage(request, params) } } } @@ -276,13 +275,13 @@ internal class ChatEngine( scope.launch { jsonRpcInteractor.peerResponse.collect { response -> when (val params = response.params) { - is ChatParamsVO.InviteParams -> onInviteResponse(response) + is ChatParams.InviteParams -> onInviteResponse(response) } } } } - internal fun addContact(accountIdWithPublicKeyVO: AccountIdWithPublicKeyVO, onFailure: (Throwable) -> Unit) = try { + internal fun addContact(accountIdWithPublicKeyVO: AccountIdWithPublicKey, onFailure: (Throwable) -> Unit) = try { if (chatStorage.doesContactNotExists(accountIdWithPublicKeyVO.accountId)) { chatStorage.createContact(EngineDO.Contact(accountIdWithPublicKeyVO, accountIdWithPublicKeyVO.accountId.value)) } else { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt index 484ff27ecd..097bb9aea5 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt @@ -2,41 +2,41 @@ package com.walletconnect.chat.engine.model -import com.walletconnect.chat.core.model.vo.AccountIdVO -import com.walletconnect.chat.core.model.vo.AccountIdWithPublicKeyVO -import com.walletconnect.chat.core.model.vo.MediaVO +import com.walletconnect.chat.common.model.AccountId +import com.walletconnect.chat.common.model.AccountIdWithPublicKey +import com.walletconnect.chat.common.model.Media internal sealed class EngineDO { data class Error(val throwable: Throwable) : EngineDO() // TODO: Should this be extracted to core for easier error handling? data class Invite( - val accountId: AccountIdVO, + val accountId: AccountId, val message: String, val signature: String? = null, ) : EngineDO() data class Thread( val topic: String, - val selfAccountId: AccountIdVO, - val peerAccountId: AccountIdVO, + val selfAccountId: AccountId, + val peerAccountId: AccountId, ) : EngineDO() data class Message( val message: String, - val authorAccountId: AccountIdVO, + val authorAccountId: AccountId, val timestamp: Long, - val media: MediaVO?, + val media: Media?, ) : EngineDO() data class Contact( - val accountIdWithPublicKeyVO: AccountIdWithPublicKeyVO, + val accountIdWithPublicKeyVO: AccountIdWithPublicKey, val displayName: String, ) : EngineDO() data class SendMessage( - val author: AccountIdVO, + val author: AccountId, val message: String, - val media: MediaVO?, + val media: Media?, ) : EngineDO() sealed class Events : EngineDO() { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcSerializer.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt similarity index 71% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcSerializer.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt index b259993bf2..233273b4b2 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcSerializer.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt @@ -1,30 +1,31 @@ @file:JvmSynthetic -package com.walletconnect.chat.copiedFromSign +package com.walletconnect.chat.json_rpc.data import com.squareup.moshi.Moshi import com.walletconnect.android.common.SerializableJsonRpc import com.walletconnect.android.impl.common.model.type.ClientParams -import com.walletconnect.chat.core.model.vo.clientsync.ChatRpcVO +import com.walletconnect.chat.common.json_rpc.ChatRpc +import com.walletconnect.chat.json_rpc.model.JsonRpcMethod //TODO: Should there be a copy for every SDK with specific methods or one file with all methods. internal class JsonRpcSerializer(private val moshi: Moshi) { internal fun deserialize(method: String, json: String): ClientParams? = when (method) { - JsonRpcMethod.WC_CHAT_MESSAGE -> tryDeserialize(json)?.params - JsonRpcMethod.WC_CHAT_INVITE -> tryDeserialize(json)?.params - JsonRpcMethod.WC_CHAT_LEAVE -> tryDeserialize(json)?.params - JsonRpcMethod.WC_CHAT_PING -> tryDeserialize(json)?.params + JsonRpcMethod.WC_CHAT_MESSAGE -> tryDeserialize(json)?.params + JsonRpcMethod.WC_CHAT_INVITE -> tryDeserialize(json)?.params + JsonRpcMethod.WC_CHAT_LEAVE -> tryDeserialize(json)?.params + JsonRpcMethod.WC_CHAT_PING -> tryDeserialize(json)?.params else -> null } fun serialize(payload: SerializableJsonRpc): String = when (payload) { - is ChatRpcVO.ChatMessage -> trySerialize(payload) - is ChatRpcVO.ChatInvite -> trySerialize(payload) - is ChatRpcVO.ChatLeave -> trySerialize(payload) - is ChatRpcVO.ChatPing -> trySerialize(payload) + is ChatRpc.ChatMessage -> trySerialize(payload) + is ChatRpc.ChatInvite -> trySerialize(payload) + is ChatRpc.ChatLeave -> trySerialize(payload) + is ChatRpc.ChatPing -> trySerialize(payload) is RelayerDO.JsonRpcResponse.JsonRpcResult -> trySerialize(payload) is RelayerDO.JsonRpcResponse.JsonRpcError -> trySerialize(payload) else -> String.Empty diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt new file mode 100644 index 0000000000..f48da0caeb --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt @@ -0,0 +1,4 @@ +package com.walletconnect.chat.json_rpc.domain + +class JsonRpcInteractor { +} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcMethod.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt similarity index 90% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcMethod.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt index 6d74c1039d..494f39dd80 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/JsonRpcMethod.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt @@ -1,4 +1,4 @@ -package com.walletconnect.chat.copiedFromSign +package com.walletconnect.chat.json_rpc.model //TODO: Should there be a copy for every SDK with specific methods or one file with all methods. internal object JsonRpcMethod { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt index df1284e6f6..0e46926f80 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt @@ -2,7 +2,7 @@ package com.walletconnect.chat.storage -import com.walletconnect.chat.core.model.vo.AccountIdVO +import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.engine.model.EngineDO import com.walletconnect.chat.storage.data.dao.Contacts import com.walletconnect.chat.storage.data.dao.ContactsQueries @@ -13,7 +13,7 @@ internal class ChatStorageRepository( ) { @JvmSynthetic - internal fun doesContactNotExists(accountIdVO: AccountIdVO): Boolean = + internal fun doesContactNotExists(accountIdVO: AccountId): Boolean = contactsQueries.doesContactNotExists(accountIdVO.value).executeAsOne() @JvmSynthetic @@ -24,10 +24,10 @@ internal class ChatStorageRepository( ) @JvmSynthetic - internal fun getContact(accountIdVO: AccountIdVO) : Contacts = contactsQueries.getContact(accountIdVO.value).executeAsOne() + internal fun getContact(accountIdVO: AccountId) : Contacts = contactsQueries.getContact(accountIdVO.value).executeAsOne() @JvmSynthetic - internal fun updateContact(accountIdVO: AccountIdVO, publicKey: PublicKey, displayName: String) { + internal fun updateContact(accountIdVO: AccountId, publicKey: PublicKey, displayName: String) { contactsQueries.updateContactPublicKey(publicKey.keyAsHex, accountIdVO.value) contactsQueries.updateContactDisplayName(displayName, accountIdVO.value) } diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/common/adapters/JsonRpcResultAdapter.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/common/adapters/JsonRpcResultAdapter.kt index 2b8569ee3f..33da45e5e8 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/common/adapters/JsonRpcResultAdapter.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/common/adapters/JsonRpcResultAdapter.kt @@ -19,7 +19,7 @@ import kotlin.Long import kotlin.String // TODO: figure out how to share this with other modules -internal class JsonRpcResultAdapter(moshi: Moshi) : JsonAdapter() { +internal class JsonRpcResultAdapter(moshi: Moshi) : JsonAdapter() { private val options: JsonReader.Options = JsonReader.Options.of("id", "jsonrpc", "result") private val longAdapter: JsonAdapter = moshi.adapter(Long::class.java, emptySet(), "id") private val stringAdapter: JsonAdapter = moshi.adapter(String::class.java, emptySet(), "jsonrpc") @@ -28,13 +28,13 @@ internal class JsonRpcResultAdapter(moshi: Moshi) : JsonAdapter = moshi.adapter(SessionParamsVO.ApprovalParams::class.java) @Volatile - private var constructorRef: Constructor? = null + private var constructorRef: Constructor? = null override fun toString(): String = buildString(59) { append("GeneratedJsonAdapter(").append("RelayDO.JsonRpcResponse.JsonRpcResult").append(')') } - override fun fromJson(reader: JsonReader): com.walletconnect.android.common.JsonRpcResponse.JsonRpcResult { + override fun fromJson(reader: JsonReader): JsonRpcResponse.JsonRpcResult { var id: Long? = null var jsonrpc: String? = null var result: Any? = null @@ -66,7 +66,7 @@ internal class JsonRpcResultAdapter(moshi: Moshi) : JsonAdapter = + val localConstructor: Constructor = this.constructorRef - ?: com.walletconnect.android.common.JsonRpcResponse.JsonRpcResult::class.java.getDeclaredConstructor(Long::class.javaPrimitiveType, + ?: JsonRpcResponse.JsonRpcResult::class.java.getDeclaredConstructor(Long::class.javaPrimitiveType, String::class.java, Any::class.java, Int::class.javaPrimitiveType, Util.DEFAULT_CONSTRUCTOR_MARKER).also { this.constructorRef = it } return localConstructor.newInstance( @@ -89,7 +89,7 @@ internal class JsonRpcResultAdapter(moshi: Moshi) : JsonAdapter { From 1c90e57058b2da0c2ae1c15bb566589a883066fe Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 20 Oct 2022 18:39:02 +0200 Subject: [PATCH 03/30] Integrate androidCore into chat sdk --- .../android/impl/di/StorageModule.kt | 4 -- .../json_rpc/domain/BaseJsonRpcInteractor.kt | 2 +- .../auth/engine/domain/AuthEngine.kt | 2 +- .../auth/json_rpc/data/JsonRpcSerializer.kt | 2 +- .../auth/json_rpc/domain/JsonRpcInteractor.kt | 9 +-- .../chatsample/ChatSampleApplication.kt | 14 ++-- chat/sdk/build.gradle.kts | 7 ++ .../com/walletconnect/chat/client/Chat.kt | 4 +- .../walletconnect/chat/client/ChatProtocol.kt | 28 ++++---- .../com/walletconnect/chat/di/CommonModule.kt | 30 ++++++++ .../walletconnect/chat/di/JsonRpcModule.kt | 19 ++++++ .../walletconnect/chat/di/StorageModule.kt | 9 ++- .../chat/engine/domain/ChatEngine.kt | 60 +++++++++------- .../chat/engine/domain/Validator.kt | 3 +- .../chat/json_rpc/data/JsonRpcSerializer.kt | 14 ++-- .../chat/json_rpc/domain/JsonRpcInteractor.kt | 14 +++- .../chat/json_rpc/model/JsonRpcMethod.kt | 1 - .../chat/storage/ChatStorageRepository.kt | 12 ++-- .../chat/storage/data/dao/JsonRpcHistory.sq | 42 ------------ .../com/walletconnect/sign/client/Sign.kt | 1 - .../sign/engine/domain/SignEngine.kt | 68 +++++++++++++------ .../sign/json_rpc/data/JsonRpcSerializer.kt | 2 +- .../json_rpc/domain/RelayerInteractorTest.kt | 3 +- 23 files changed, 203 insertions(+), 147 deletions(-) create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt delete mode 100644 chat/sdk/src/main/sqldelight/com/walletconnect/chat/storage/data/dao/JsonRpcHistory.sq diff --git a/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt b/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt index 8a555e133d..3554e5356f 100644 --- a/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt +++ b/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt @@ -1,13 +1,9 @@ package com.walletconnect.android.impl.di -import android.content.Context -import android.content.SharedPreferences -import com.squareup.sqldelight.ColumnAdapter import com.squareup.sqldelight.android.AndroidSqliteDriver import com.squareup.sqldelight.db.SqlDriver import com.walletconnect.android.impl.Database import org.koin.android.ext.koin.androidContext -import org.koin.core.qualifier.named import org.koin.dsl.module inline fun coreStorageModule(databaseSchema: SqlDriver.Schema, storageSuffix: String) = module { diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/BaseJsonRpcInteractor.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/BaseJsonRpcInteractor.kt index 2ebf0314d4..1380de9834 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/BaseJsonRpcInteractor.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/BaseJsonRpcInteractor.kt @@ -59,7 +59,7 @@ open class BaseJsonRpcInteractor( } } - fun publishJsonRpcRequests( + fun publishJsonRpcRequest( topic: Topic, params: IrnParams, payload: JsonRpcClientSync<*>, diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt index 85273a75d3..943a40cebb 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt @@ -93,7 +93,7 @@ internal class AuthEngine( val irnParams = IrnParams(Tags.AUTH_REQUEST, Ttl(DAY_IN_SECONDS), true) onPairing(walletConnectUri.toAbsoluteString()) - jsonRpcInteractor.publishJsonRpcRequests(pairingTopic, irnParams, authRequest, + jsonRpcInteractor.publishJsonRpcRequest(pairingTopic, irnParams, authRequest, onSuccess = { Logger.log("Auth request sent successfully on topic:$pairingTopic, awaiting response on topic:$responseTopic") // todo: Remove after Alpha jsonRpcInteractor.subscribe(responseTopic) diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt index d8ced0fc37..ee326ea812 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt @@ -17,7 +17,7 @@ internal class JsonRpcSerializer(override val moshi: Moshi) : JsonRpcSerializerA else -> null } - override fun sdkSpecificSerialize(payload: com.walletconnect.android.common.SerializableJsonRpc): String = when (payload) { + override fun sdkSpecificSerialize(payload: SerializableJsonRpc): String = when (payload) { is AuthRpc.AuthRequest -> trySerialize(payload) else -> String.Empty } diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/domain/JsonRpcInteractor.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/domain/JsonRpcInteractor.kt index 88cf58591f..a088c9a20f 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/domain/JsonRpcInteractor.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/domain/JsonRpcInteractor.kt @@ -5,6 +5,7 @@ package com.walletconnect.auth.json_rpc.domain import com.walletconnect.android.impl.crypto.Codec import com.walletconnect.android.impl.json_rpc.domain.BaseJsonRpcInteractor import com.walletconnect.android.RelayConnectionInterface +import com.walletconnect.android.common.JsonRpcResponse import com.walletconnect.android.impl.json_rpc.model.JsonRpcHistoryRecord import com.walletconnect.android.impl.storage.JsonRpcHistory import com.walletconnect.auth.common.json_rpc.AuthRpc @@ -40,15 +41,15 @@ internal class JsonRpcInteractor( return entry } - fun getResponseById(id: Long): com.walletconnect.android.common.JsonRpcResponse? { + fun getResponseById(id: Long): JsonRpcResponse? { val record: JsonRpcHistoryRecord? = jsonRpcHistory.getRecordById(id) - var jsonRpcResponse: com.walletconnect.android.common.JsonRpcResponse? = null + var jsonRpcResponse: JsonRpcResponse? = null if (record != null) { record.response?.let { responseJson -> - serializer.tryDeserialize(responseJson)?.let { jsonRpcResult -> + serializer.tryDeserialize(responseJson)?.let { jsonRpcResult -> jsonRpcResponse = jsonRpcResult - } ?: serializer.tryDeserialize(responseJson)?.let { jsonRpcError -> + } ?: serializer.tryDeserialize(responseJson)?.let { jsonRpcError -> jsonRpcResponse = jsonRpcError } } diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt index 45b4181b58..a123e2a48e 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt @@ -2,20 +2,22 @@ package com.walletconnect.chatsample import android.app.Application import android.util.Log +import com.walletconnect.android.RelayClient +import com.walletconnect.android.connection.ConnectionType import com.walletconnect.chat.client.Chat import com.walletconnect.chat.client.ChatClient import com.walletconnect.chatsample.utils.tag +const val WALLET_CONNECT_PROD_RELAY_URL = "relay.walletconnect.com" + class ChatSampleApplication : Application() { override fun onCreate() { super.onCreate() - ChatClient.initialize( - Chat.Params.Init( - this, - "https://keys.walletconnect.com" - ) - ) { error -> + val serverUri = "wss://$WALLET_CONNECT_PROD_RELAY_URL?projectId=${BuildConfig.PROJECT_ID}" + RelayClient.initialize(relayServerUrl = serverUri, connectionType = ConnectionType.AUTOMATIC, application = this) + + ChatClient.initialize(Chat.Params.Init(RelayClient, "https://keys.walletconnect.com")) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } } diff --git a/chat/sdk/build.gradle.kts b/chat/sdk/build.gradle.kts index f4b192ebc9..a17c7227c3 100644 --- a/chat/sdk/build.gradle.kts +++ b/chat/sdk/build.gradle.kts @@ -38,6 +38,13 @@ android { } } +sqldelight { + database("Database") { + packageName = "com.walletconnect.chat" + dependency(project(":androidCore:impl")) + } +} + dependencies { debugImplementation(project(":androidCore:impl")) releaseImplementation("com.walletconnect:android-core-impl:1.0.0") diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt index 133cb3e943..a395ebf50d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt @@ -1,6 +1,6 @@ package com.walletconnect.chat.client -import android.app.Application +import com.walletconnect.android.RelayConnectionInterface object Chat { @@ -60,7 +60,7 @@ object Chat { } sealed class Params { - data class Init(val application: Application, val keyServerUrl: String) : Params() + data class Init(val relay: RelayConnectionInterface, val keyServerUrl: String) : Params() data class Register(val account: Model.AccountId, val private: Boolean? = false) : Params() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index 9d97c302d4..356cebae5f 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -1,53 +1,51 @@ package com.walletconnect.chat.client -import com.walletconnect.android.common.di.commonModule import com.walletconnect.android.common.scope +import com.walletconnect.android.common.wcKoinApp import com.walletconnect.android.impl.di.cryptoModule import com.walletconnect.android.impl.di.networkModule +import com.walletconnect.android.impl.utils.Logger import com.walletconnect.chat.client.mapper.toClient import com.walletconnect.chat.client.mapper.toEngineDO import com.walletconnect.chat.client.mapper.toVO import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey -import com.walletconnect.chat.di.engineModule +import com.walletconnect.chat.di.* +import com.walletconnect.chat.di.commonModule +import com.walletconnect.chat.di.jsonRpcModule import com.walletconnect.chat.di.keyServerModule import com.walletconnect.chat.engine.domain.ChatEngine import com.walletconnect.chat.engine.model.EngineDO import com.walletconnect.foundation.common.model.PublicKey import kotlinx.coroutines.launch -import org.koin.android.ext.koin.androidContext import org.koin.core.KoinApplication internal class ChatProtocol : ChatInterface { - private val wcKoinApp: KoinApplication = KoinApplication.init() private lateinit var chatEngine: ChatEngine companion object { val instance = ChatProtocol() + const val storageSuffix: String = "_chat" } @Throws(IllegalStateException::class) override fun initialize(init: Chat.Params.Init, onError: (Chat.Model.Error) -> Unit) { + Logger.init() with(init) { wcKoinApp.run { - androidContext(application) modules( + networkModule(relay), commonModule(), cryptoModule(), keyServerModule(keyServerUrl), -// TODO: Figure out how to get relay as in Sign in here -// networkModule(serverUrl, relay, connectionType.toRelayConnectionType()), - //todo: add serverUrl as init param - networkModule("serverUrl"), //TODO: refactor, network module should be initialized in RelayClient -// relayerModule(), -// storageModule(), - com.walletconnect.chat.di.storageModule(), // TODO: Refactor storage module into one + jsonRpcModule(), + storageModule(storageSuffix), engineModule() ) - - chatEngine = koin.get() } } + + chatEngine = wcKoinApp.koin.get() } override fun setChatDelegate(delegate: ChatInterface.ChatDelegate) { @@ -58,8 +56,8 @@ internal class ChatProtocol : ChatInterface { when (event) { is EngineDO.Events.OnInvite -> delegate.onInvite(event.toClient()) is EngineDO.Events.OnJoined -> delegate.onJoined(event.toClient()) - is EngineDO.Events.OnLeft -> Unit is EngineDO.Events.OnMessage -> delegate.onMessage(event.toClient()) + is EngineDO.Events.OnLeft -> Unit } } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt new file mode 100644 index 0000000000..0d29a482d9 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt @@ -0,0 +1,30 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.di + +import com.squareup.moshi.Moshi +import com.tinder.scarlet.utils.getRawType +import com.walletconnect.android.common.JsonRpcResponse +import com.walletconnect.android.common.di.AndroidCommonDITags +import com.walletconnect.chat.common.adapter.JsonRpcResultAdapter +import org.koin.core.qualifier.named +import org.koin.dsl.module +import kotlin.reflect.jvm.jvmName + +@JvmSynthetic +internal fun commonModule() = module { + + includes(com.walletconnect.android.common.di.commonModule()) + + single { + get(named(AndroidCommonDITags.MOSHI)) + .newBuilder() + .add { type, _, moshi -> + when (type.getRawType().name) { + JsonRpcResponse.JsonRpcResult::class.jvmName -> JsonRpcResultAdapter(moshi) + else -> null + } + } + .build() + } +} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt new file mode 100644 index 0000000000..54a4846803 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt @@ -0,0 +1,19 @@ +@file:JvmSynthetic + +package com.walletconnect.chat.di + +import com.walletconnect.chat.json_rpc.data.JsonRpcSerializer +import com.walletconnect.chat.json_rpc.domain.JsonRpcInteractor +import org.koin.dsl.module + +@JvmSynthetic +internal fun jsonRpcModule() = module { + + single { + JsonRpcSerializer(get()) + } + + single { + JsonRpcInteractor(get(), get(), get(), get()) + } +} \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt index 64653d8a77..9dd3413719 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt @@ -1,11 +1,18 @@ package com.walletconnect.chat.di +import com.walletconnect.android.impl.di.coreStorageModule import com.walletconnect.chat.Database import com.walletconnect.chat.storage.ChatStorageRepository import org.koin.dsl.module @JvmSynthetic -internal fun storageModule() = module { +internal fun storageModule(storageSuffix: String) = module { + + includes(coreStorageModule(Database.Schema, storageSuffix)) + + single { + Database(get()) + } single { get().contactsQueries diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 9693546f6d..d9405ba217 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -3,6 +3,7 @@ package com.walletconnect.chat.engine.domain import com.walletconnect.android.common.JsonRpcResponse +import com.walletconnect.android.common.model.Tags import com.walletconnect.android.common.scope import com.walletconnect.android.exception.GenericException import com.walletconnect.android.impl.common.model.IrnParams @@ -10,8 +11,9 @@ import com.walletconnect.android.impl.common.model.Participants import com.walletconnect.android.impl.common.model.sync.WCRequest import com.walletconnect.android.impl.common.model.sync.WCResponse import com.walletconnect.android.impl.common.model.type.enums.EnvelopeType +import com.walletconnect.android.impl.crypto.KeyManagementRepository +import com.walletconnect.android.impl.utils.DAY_IN_SECONDS import com.walletconnect.android.impl.utils.Logger -import com.walletconnect.chat.copiedFromSign.KeyManagementRepository import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.common.json_rpc.ChatRpc @@ -19,6 +21,7 @@ import com.walletconnect.chat.common.json_rpc.ChatParams import com.walletconnect.chat.discovery.keyserver.domain.use_case.RegisterAccountUseCase import com.walletconnect.chat.discovery.keyserver.domain.use_case.ResolveAccountUseCase import com.walletconnect.chat.engine.model.EngineDO +import com.walletconnect.chat.json_rpc.domain.JsonRpcInteractor import com.walletconnect.chat.storage.ChatStorageRepository import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic @@ -122,25 +125,22 @@ internal class ChatEngine( val inviteTopic = Topic(keyManagementRepository.getHash(publicKeyString)) // Topic I keyManagementRepository.setKeyAgreement(inviteTopic, senderPublicKey, receiverPublicKey) - val participantsVO = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = receiverPublicKey) - + val participants = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = receiverPublicKey) val inviteParams = ChatParams.InviteParams(invite.message, invite.accountId.value, senderPublicKey.keyAsHex, invite.signature) val payload = ChatRpc.ChatInvite(id = generateId(), params = inviteParams) - val acceptTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) + keyManagementRepository.setSymmetricKey(acceptTopic, symmetricKey) jsonRpcInteractor.subscribe(acceptTopic) - val irnParams = IrnParams(Tags.CHAT_INVITE, Ttl(Time.dayInSeconds), true) - jsonRpcInteractor.publishJsonRpcRequests(inviteTopic, irnParams, payload, EnvelopeType.ONE, - { - Logger.log("Chat invite sent successfully") - }, + val irnParams = IrnParams(Tags.CHAT_INVITE, Ttl(DAY_IN_SECONDS), true) + jsonRpcInteractor.publishJsonRpcRequest(inviteTopic, irnParams, payload, EnvelopeType.ONE, participants, + { Logger.log("Chat invite sent successfully") }, { throwable -> Logger.log("Chat invite error: $throwable") jsonRpcInteractor.unsubscribe(acceptTopic) onFailure(throwable) - }, participantsVO) + }) } catch (error: Exception) { onFailure(error) @@ -171,8 +171,12 @@ internal class ChatEngine( inviteRequestMap[wcRequest.id] = wcRequest // todo when to remove it? scope.launch { - _events.emit(EngineDO.Events.OnInvite(wcRequest.id, - EngineDO.Invite(AccountId(params.account), params.message, params.signature))) + _events.emit( + EngineDO.Events.OnInvite( + wcRequest.id, + EngineDO.Invite(AccountId(params.account), params.message, params.signature) + ) + ) } //TODO: Add adding invites to storage. For MVP we will use only emitted event. @@ -193,7 +197,7 @@ internal class ChatEngine( val acceptanceParams = ChatParams.AcceptanceParams(publicKey.keyAsHex) - val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(Time.dayInSeconds)) + val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(DAY_IN_SECONDS)) jsonRpcInteractor.respondWithParams(request.copy(topic = acceptTopic), acceptanceParams, irnParams, EnvelopeType.ZERO) @@ -223,11 +227,11 @@ internal class ChatEngine( val messageParams = ChatParams.MessageParams(sendMessage.message, sendMessage.author.value, System.currentTimeMillis(), sendMessage.media) val payload = ChatRpc.ChatMessage(id = generateId(), params = messageParams) - val irnParams = IrnParams(Tags.CHAT_MESSAGE, Ttl(Time.dayInSeconds), true) + val irnParams = IrnParams(Tags.CHAT_MESSAGE, Ttl(DAY_IN_SECONDS), true) - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, payload, EnvelopeType.ZERO, - { Logger.log("Chat message sent successfully") }, - { throwable -> + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, payload, + onSuccess = { Logger.log("Chat message sent successfully") }, + onFailure = { throwable -> Logger.log("Chat message error: $throwable") onFailure(throwable) }) @@ -235,8 +239,12 @@ internal class ChatEngine( private fun onMessage(wcRequest: WCRequest, params: ChatParams.MessageParams) { scope.launch { - _events.emit(EngineDO.Events.OnMessage(wcRequest.topic.value, - EngineDO.Message(params.message, AccountId(params.authorAccount), params.timestamp, params.media))) + _events.emit( + EngineDO.Events.OnMessage( + wcRequest.topic.value, + EngineDO.Message(params.message, AccountId(params.authorAccount), params.timestamp, params.media) + ) + ) } //TODO: Add adding messages to storage. For MVP we will use only emitted event. @@ -246,11 +254,11 @@ internal class ChatEngine( //todo: correct define params val leaveParams = ChatParams.LeaveParams() val payload = ChatRpc.ChatLeave(id = generateId(), params = leaveParams) - val irnParams = IrnParams(Tags.CHAT_LEAVE, Ttl(Time.dayInSeconds), true) + val irnParams = IrnParams(Tags.CHAT_LEAVE, Ttl(DAY_IN_SECONDS), true) - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, payload, EnvelopeType.ZERO, - { Logger.log("Chat message sent successfully") }, - { throwable -> + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, payload, EnvelopeType.ZERO, + onSuccess = { Logger.log("Chat message sent successfully") }, + onFailure = { throwable -> Logger.log("Chat message error: $throwable") onFailure(throwable) }) @@ -285,9 +293,11 @@ internal class ChatEngine( if (chatStorage.doesContactNotExists(accountIdWithPublicKeyVO.accountId)) { chatStorage.createContact(EngineDO.Contact(accountIdWithPublicKeyVO, accountIdWithPublicKeyVO.accountId.value)) } else { - chatStorage.updateContact(accountIdWithPublicKeyVO.accountId, + chatStorage.updateContact( + accountIdWithPublicKeyVO.accountId, accountIdWithPublicKeyVO.publicKey, - accountIdWithPublicKeyVO.accountId.value) + accountIdWithPublicKeyVO.accountId.value + ) } } catch (error: Exception) { onFailure(error) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/Validator.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/Validator.kt index 613bd96332..e0bf1f5eaf 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/Validator.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/Validator.kt @@ -1,8 +1,8 @@ package com.walletconnect.chat.engine.domain +// TODO: This was copied from Sign SDK. Maybe we should move it to core? internal object Validator { - // TODO: This was copied from Sign SDK. Maybe we should move it to core? @JvmSynthetic internal fun isAccountIdCAIP10Compliant(accountId: String): Boolean { val elements = accountId.split(":") @@ -14,7 +14,6 @@ internal object Validator { ACCOUNT_ADDRESS_REGEX.toRegex().matches(accountAddress) } - // TODO: This was copied from Sign SDK. Maybe we should move it to core? private const val NAMESPACE_REGEX: String = "^[-a-z0-9]{3,8}$" private const val REFERENCE_REGEX: String = "^[-a-zA-Z0-9]{1,32}$" private const val ACCOUNT_ADDRESS_REGEX: String = "^[a-zA-Z0-9]{1,64}$" diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt index 233273b4b2..5a2852b11c 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt @@ -5,13 +5,14 @@ package com.walletconnect.chat.json_rpc.data import com.squareup.moshi.Moshi import com.walletconnect.android.common.SerializableJsonRpc import com.walletconnect.android.impl.common.model.type.ClientParams +import com.walletconnect.android.impl.json_rpc.data.JsonRpcSerializerAbstract import com.walletconnect.chat.common.json_rpc.ChatRpc import com.walletconnect.chat.json_rpc.model.JsonRpcMethod +import com.walletconnect.util.Empty -//TODO: Should there be a copy for every SDK with specific methods or one file with all methods. -internal class JsonRpcSerializer(private val moshi: Moshi) { +internal class JsonRpcSerializer(override val moshi: Moshi) : JsonRpcSerializerAbstract(moshi) { - internal fun deserialize(method: String, json: String): ClientParams? = + override fun deserialize(method: String, json: String): ClientParams? = when (method) { JsonRpcMethod.WC_CHAT_MESSAGE -> tryDeserialize(json)?.params JsonRpcMethod.WC_CHAT_INVITE -> tryDeserialize(json)?.params @@ -20,17 +21,12 @@ internal class JsonRpcSerializer(private val moshi: Moshi) { else -> null } - fun serialize(payload: SerializableJsonRpc): String = + override fun sdkSpecificSerialize(payload: SerializableJsonRpc): String = when (payload) { is ChatRpc.ChatMessage -> trySerialize(payload) is ChatRpc.ChatInvite -> trySerialize(payload) is ChatRpc.ChatLeave -> trySerialize(payload) is ChatRpc.ChatPing -> trySerialize(payload) - is RelayerDO.JsonRpcResponse.JsonRpcResult -> trySerialize(payload) - is RelayerDO.JsonRpcResponse.JsonRpcError -> trySerialize(payload) else -> String.Empty } - - inline fun tryDeserialize(json: String): T? = runCatching { moshi.adapter(T::class.java).fromJson(json) }.getOrNull() - private inline fun trySerialize(type: T): String = moshi.adapter(T::class.java).toJson(type) } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt index f48da0caeb..c9a2b09740 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt @@ -1,4 +1,14 @@ package com.walletconnect.chat.json_rpc.domain -class JsonRpcInteractor { -} \ No newline at end of file +import com.walletconnect.android.RelayConnectionInterface +import com.walletconnect.android.impl.crypto.Codec +import com.walletconnect.android.impl.json_rpc.domain.BaseJsonRpcInteractor +import com.walletconnect.android.impl.storage.JsonRpcHistory +import com.walletconnect.chat.json_rpc.data.JsonRpcSerializer + +internal class JsonRpcInteractor( + relay: RelayConnectionInterface, + chaChaPolyCodec: Codec, + jsonRpcHistory: JsonRpcHistory, + serializer: JsonRpcSerializer +) : BaseJsonRpcInteractor(relay, serializer, chaChaPolyCodec, jsonRpcHistory) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt index 494f39dd80..55e7d9dba3 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt @@ -1,6 +1,5 @@ package com.walletconnect.chat.json_rpc.model -//TODO: Should there be a copy for every SDK with specific methods or one file with all methods. internal object JsonRpcMethod { @get:JvmSynthetic const val WC_CHAT_INVITE: String = "wc_chatInvite" diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt index 0e46926f80..de83c26c74 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt @@ -8,10 +8,8 @@ import com.walletconnect.chat.storage.data.dao.Contacts import com.walletconnect.chat.storage.data.dao.ContactsQueries import com.walletconnect.foundation.common.model.PublicKey -internal class ChatStorageRepository( - private val contactsQueries: ContactsQueries, +internal class ChatStorageRepository(private val contactsQueries: ContactsQueries) { - ) { @JvmSynthetic internal fun doesContactNotExists(accountIdVO: AccountId): Boolean = contactsQueries.doesContactNotExists(accountIdVO.value).executeAsOne() @@ -24,11 +22,11 @@ internal class ChatStorageRepository( ) @JvmSynthetic - internal fun getContact(accountIdVO: AccountId) : Contacts = contactsQueries.getContact(accountIdVO.value).executeAsOne() + internal fun getContact(accountId: AccountId): Contacts = contactsQueries.getContact(accountId.value).executeAsOne() @JvmSynthetic - internal fun updateContact(accountIdVO: AccountId, publicKey: PublicKey, displayName: String) { - contactsQueries.updateContactPublicKey(publicKey.keyAsHex, accountIdVO.value) - contactsQueries.updateContactDisplayName(displayName, accountIdVO.value) + internal fun updateContact(accountId: AccountId, publicKey: PublicKey, displayName: String) { + contactsQueries.updateContactPublicKey(publicKey.keyAsHex, accountId.value) + contactsQueries.updateContactDisplayName(displayName, accountId.value) } } \ No newline at end of file diff --git a/chat/sdk/src/main/sqldelight/com/walletconnect/chat/storage/data/dao/JsonRpcHistory.sq b/chat/sdk/src/main/sqldelight/com/walletconnect/chat/storage/data/dao/JsonRpcHistory.sq deleted file mode 100644 index 7b48975313..0000000000 --- a/chat/sdk/src/main/sqldelight/com/walletconnect/chat/storage/data/dao/JsonRpcHistory.sq +++ /dev/null @@ -1,42 +0,0 @@ -CREATE TABLE JsonRpcHistoryDao( - id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - request_id INTEGER UNIQUE NOT NULL, - topic TEXT NOT NULL, - method TEXT NOT NULL, - body TEXT NOT NULL, - response TEXT AS String -); - -insertOrAbortJsonRpcHistory: -INSERT OR ABORT INTO JsonRpcHistoryDao (request_id, topic, method, body) -VALUES (?, ?, ?, ?); - -updateJsonRpcHistory: -UPDATE JsonRpcHistoryDao -SET response = ? -WHERE request_id = ?; - -getJsonRpcHistoryRecord: -SELECT request_id, topic, method, body, response -FROM JsonRpcHistoryDao -WHERE request_id = ?; - -getJsonRpcRequestsDaos: -SELECT request_id, topic, method, body, response -FROM JsonRpcHistoryDao -WHERE topic = ?; - -doesJsonRpcNotExist: -SELECT NOT EXISTS ( - SELECT 1 - FROM JsonRpcHistoryDao - WHERE request_id = ? - LIMIT 1 -); - -selectLastInsertedRowId: -SELECT last_insert_rowid(); - -deleteJsonRpcHistory: -DELETE FROM JsonRpcHistoryDao -WHERE topic = ?; \ No newline at end of file diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/client/Sign.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/client/Sign.kt index f61c22fca9..eb20c3f45f 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/client/Sign.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/client/Sign.kt @@ -181,7 +181,6 @@ object Sign { sealed class Params { - // TODO: Maybe convert this into a Builder data class Init constructor( val metadata: Model.AppMetaData, val relay: RelayConnectionInterface, diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index b9835569ec..7b4166db6f 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -106,7 +106,7 @@ internal class SignEngine( jsonRpcInteractor.subscribe(pairingTopic) onProposedSequence(proposedSequence) - jsonRpcInteractor.publishJsonRpcRequests(pairingTopic, irnParams, request, + jsonRpcInteractor.publishJsonRpcRequest(pairingTopic, irnParams, request, onSuccess = { Logger.log("Session proposal sent successfully") }, @@ -181,7 +181,11 @@ internal class SignEngine( sessionProposalRequest.remove(proposerPublicKey) val irnParams = IrnParams(Tags.SESSION_PROPOSE_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) - jsonRpcInteractor.respondWithError(request, PeerError.EIP1193.UserRejectedRequest(reason), irnParams, onFailure = { error -> onFailure(error) }) + jsonRpcInteractor.respondWithError( + request, + PeerError.EIP1193.UserRejectedRequest(reason), + irnParams, + onFailure = { error -> onFailure(error) }) } internal fun approve( @@ -205,7 +209,7 @@ internal class SignEngine( val sessionSettle = SessionRpcVO.SessionSettle(id = generateId(), params = params) val irnParams = IrnParams(Tags.SESSION_SETTLE, Ttl(FIVE_MINUTES_IN_SECONDS)) - jsonRpcInteractor.publishJsonRpcRequests(sessionTopic, irnParams, sessionSettle, onFailure = { error -> onFailure(error) }) + jsonRpcInteractor.publishJsonRpcRequest(sessionTopic, irnParams, sessionSettle, onFailure = { error -> onFailure(error) }) } catch (e: SQLiteException) { onFailure(e) } @@ -261,7 +265,7 @@ internal class SignEngine( val irnParams = IrnParams(com.walletconnect.android.common.model.Tags.SESSION_UPDATE, Ttl(DAY_IN_SECONDS)) sequenceStorageRepository.insertTempNamespaces(topic, namespaces.toMapOfNamespacesVOSession(), sessionUpdate.id, onSuccess = { - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionUpdate, + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, sessionUpdate, onSuccess = { Logger.log("Update sent successfully") }, onFailure = { error -> Logger.error("Sending session update error: $error") @@ -292,7 +296,7 @@ internal class SignEngine( val sessionPayload = SessionRpcVO.SessionRequest(id = generateId(), params = params) val irnParams = IrnParams(Tags.SESSION_REQUEST, Ttl(FIVE_MINUTES_IN_SECONDS), true) - jsonRpcInteractor.publishJsonRpcRequests( + jsonRpcInteractor.publishJsonRpcRequest( Topic(request.topic), irnParams, sessionPayload, @@ -348,11 +352,9 @@ internal class SignEngine( else -> throw CannotFindSequenceForTopic("$NO_SEQUENCE_FOR_TOPIC_MESSAGE$topic") } - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, pingPayload, + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, pingPayload, onSuccess = { - Logger.log("Ping sent successfully") - scope.launch { try { withTimeout(THIRTY_SECONDS_TIMEOUT) { @@ -364,9 +366,7 @@ internal class SignEngine( onSuccess(topic) }, onFailure = { error -> - Logger.log("Ping peer response error: $error") - onFailure(error) }) } @@ -407,7 +407,7 @@ internal class SignEngine( val sessionEvent = SessionRpcVO.SessionEvent(id = generateId(), params = eventParams) val irnParams = IrnParams(Tags.SESSION_EVENT, Ttl(FIVE_MINUTES_IN_SECONDS), true) - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionEvent, + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, sessionEvent, onSuccess = { Logger.log("Event sent successfully") }, onFailure = { error -> Logger.error("Sending event error: $error") @@ -434,7 +434,7 @@ internal class SignEngine( val sessionExtend = SessionRpcVO.SessionExtend(id = generateId(), params = SessionParamsVO.ExtendParams(newExpiration)) val irnParams = IrnParams(Tags.SESSION_EXTEND, Ttl(DAY_IN_SECONDS)) - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionExtend, + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, sessionExtend, onSuccess = { Logger.log("Session extend sent successfully") }, onFailure = { error -> Logger.error("Sending session extend error: $error") @@ -453,7 +453,7 @@ internal class SignEngine( jsonRpcInteractor.unsubscribe(Topic(topic)) val irnParams = IrnParams(Tags.SESSION_DELETE, Ttl(DAY_IN_SECONDS)) - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, sessionDelete, + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, sessionDelete, onSuccess = { Logger.error("Disconnect sent successfully") }, onFailure = { error -> Logger.error("Sending session disconnect error: $error") }) } @@ -576,7 +576,11 @@ internal class SignEngine( private fun onPairingDelete(request: WCRequest, params: PairingParamsVO.DeleteParams) { if (!sequenceStorageRepository.isPairingValid(request.topic)) { val irnParams = IrnParams(Tags.PAIRING_DELETE_RESPONSE, Ttl(DAY_IN_SECONDS)) - jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.PAIRING.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError( + request, + PeerError.Uncategorized.NoMatchingTopic(Sequences.PAIRING.name, request.topic.value), + irnParams + ) return } @@ -591,7 +595,11 @@ internal class SignEngine( private fun onSessionDelete(request: WCRequest, params: SessionParamsVO.DeleteParams) { if (!sequenceStorageRepository.isSessionValid(request.topic)) { val irnParams = IrnParams(Tags.SESSION_DELETE_RESPONSE, Ttl(DAY_IN_SECONDS)) - jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError( + request, + PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), + irnParams + ) return } @@ -611,7 +619,11 @@ internal class SignEngine( } if (!sequenceStorageRepository.isSessionValid(request.topic)) { - jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError( + request, + PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), + irnParams + ) return } @@ -636,7 +648,11 @@ internal class SignEngine( } if (!sequenceStorageRepository.isSessionValid(request.topic)) { - jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError( + request, + PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), + irnParams + ) return } @@ -646,7 +662,11 @@ internal class SignEngine( return } if (!session.isAcknowledged) { - jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError( + request, + PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), + irnParams + ) return } @@ -664,7 +684,11 @@ internal class SignEngine( private fun onSessionUpdate(request: WCRequest, params: SessionParamsVO.UpdateNamespacesParams) { val irnParams = IrnParams(Tags.SESSION_UPDATE_RESPONSE, Ttl(DAY_IN_SECONDS)) if (!sequenceStorageRepository.isSessionValid(request.topic)) { - jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError( + request, + PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), + irnParams + ) return } @@ -703,7 +727,11 @@ internal class SignEngine( private fun onSessionExtend(request: WCRequest, requestParams: SessionParamsVO.ExtendParams) { val irnParams = IrnParams(Tags.SESSION_EXTEND_RESPONSE, Ttl(DAY_IN_SECONDS)) if (!sequenceStorageRepository.isSessionValid(request.topic)) { - jsonRpcInteractor.respondWithError(request, PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), irnParams) + jsonRpcInteractor.respondWithError( + request, + PeerError.Uncategorized.NoMatchingTopic(Sequences.SESSION.name, request.topic.value), + irnParams + ) return } diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt index 75eaf38b56..974078b414 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt @@ -27,7 +27,7 @@ internal class JsonRpcSerializer(override val moshi: Moshi) : JsonRpcSerializerA else -> null } - override fun sdkSpecificSerialize(payload: com.walletconnect.android.common.SerializableJsonRpc): String = + override fun sdkSpecificSerialize(payload: SerializableJsonRpc): String = when (payload) { is PairingRpcVO.SessionPropose -> trySerialize(payload) is PairingRpcVO.PairingPing -> trySerialize(payload) diff --git a/sign/sdk/src/test/kotlin/com/walletconnect/sign/json_rpc/domain/RelayerInteractorTest.kt b/sign/sdk/src/test/kotlin/com/walletconnect/sign/json_rpc/domain/RelayerInteractorTest.kt index 3f6e7539e7..6d3c72420e 100644 --- a/sign/sdk/src/test/kotlin/com/walletconnect/sign/json_rpc/domain/RelayerInteractorTest.kt +++ b/sign/sdk/src/test/kotlin/com/walletconnect/sign/json_rpc/domain/RelayerInteractorTest.kt @@ -6,7 +6,6 @@ import com.walletconnect.android.impl.common.model.type.ClientParams import com.walletconnect.android.impl.common.model.type.JsonRpcClientSync import com.walletconnect.android.impl.crypto.Codec import com.walletconnect.android.RelayConnectionInterface -import com.walletconnect.android.common.connection.ConnectivityState import com.walletconnect.android.exception.WalletConnectException import com.walletconnect.android.impl.storage.JsonRpcHistory import com.walletconnect.android.impl.utils.Logger @@ -102,7 +101,7 @@ internal class RelayerInteractorTest { private fun publishJsonRpcRequests() { val irnParamsVO = IrnParams(com.walletconnect.android.common.model.Tags.SESSION_PING, Ttl(300)) - sut.publishJsonRpcRequests( + sut.publishJsonRpcRequest( topicVO, irnParamsVO, settlementSequence, From def9e3f1b3c50d9adc8ac93aec2f0a8fa3160f73 Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 25 Oct 2022 09:46:12 +0200 Subject: [PATCH 04/30] Tweaks after merge --- .../model/JsonRpcInteractorInterface.kt | 2 +- .../android/pairing/PairingClient.kt | 4 ++-- .../auth/engine/domain/AuthEngine.kt | 22 +++++++++---------- chat/sdk/build.gradle.kts | 5 +++-- .../chat/common/json_rpc/ChatParams.kt | 2 +- .../chat/common/json_rpc/ChatRpc.kt | 2 +- .../chat/engine/domain/ChatEngine.kt | 18 +++++---------- .../chat/json_rpc/domain/JsonRpcInteractor.kt | 14 ------------ .../sign/engine/domain/SignEngine.kt | 14 ++++++------ 9 files changed, 32 insertions(+), 51 deletions(-) delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/JsonRpcInteractorInterface.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/JsonRpcInteractorInterface.kt index 5ca5fbdc91..c1e0ce23c1 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/JsonRpcInteractorInterface.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/JsonRpcInteractorInterface.kt @@ -20,7 +20,7 @@ interface JsonRpcInteractorInterface { fun unsubscribe(topic: Topic, onSuccess: () -> Unit = {}, onFailure: (Throwable) -> Unit = {}) - fun publishJsonRpcRequests( + fun publishJsonRpcRequest( topic: Topic, params: IrnParams, payload: JsonRpcClientSync<*>, diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt index 501d49d621..8396c6b86a 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt @@ -93,7 +93,7 @@ internal object PairingClient : PairingInterface { val pingPayload = PairingRpc.PairingPing(id = generateId(), params = PairingParams.PingParams()) val irnParams = IrnParams(Tags.PAIRING_PING, Ttl(THIRTY_SECONDS)) - jsonRpcInteractor.publishJsonRpcRequests(Topic(ping.topic), irnParams, pingPayload, + jsonRpcInteractor.publishJsonRpcRequest(Topic(ping.topic), irnParams, pingPayload, onSuccess = { scope.launch { try { @@ -213,7 +213,7 @@ internal object PairingClient : PairingInterface { val pairingDelete = PairingRpc.PairingDelete(id = generateId(), params = deleteParams) val irnParams = IrnParams(Tags.PAIRING_DELETE, Ttl(DAY_IN_SECONDS)) - jsonRpcInteractor.publishJsonRpcRequests(Topic(topic), irnParams, pairingDelete, + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, pairingDelete, onSuccess = { logger.log("Disconnect sent successfully") }, onFailure = { error -> logger.error("Sending session disconnect error: $error") } ) diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt index 0f723719cb..c321d75aec 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt @@ -41,7 +41,7 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch internal class AuthEngine( - private val relayer: JsonRpcInteractorInterface, + private val jsonRpcInteractor: JsonRpcInteractorInterface, private val getPendingJsonRpcHistoryEntriesUseCase: GetPendingJsonRpcHistoryEntriesUseCase, private val getPendingJsonRpcHistoryEntryByIdUseCase: GetPendingJsonRpcHistoryEntryByIdUseCase, private val crypto: KeyManagementRepository, @@ -68,7 +68,7 @@ internal class AuthEngine( } internal fun handleInitializationErrors(onError: (WalletConnectException) -> Unit) { - relayer.initializationErrorsFlow.onEach { walletConnectException -> onError(walletConnectException) }.launchIn(scope) + jsonRpcInteractor.initializationErrorsFlow.onEach { walletConnectException -> onError(walletConnectException) }.launchIn(scope) } internal fun request( @@ -86,10 +86,10 @@ internal class AuthEngine( val pairingTopic = pairing.topic crypto.setSelfParticipant(responsePublicKey, responseTopic) - relayer.publishJsonRpcRequests(pairingTopic, irnParams, authRequest, + jsonRpcInteractor.publishJsonRpcRequest(pairingTopic, irnParams, authRequest, onSuccess = { Logger.log("Auth request sent successfully on topic:${pairingTopic}, awaiting response on topic:$responseTopic") // todo: Remove after Alpha - relayer.subscribe(responseTopic) + jsonRpcInteractor.subscribe(responseTopic) pairingTopicToResponseTopicMap[pairingTopic] = responseTopic onSuccess() }, @@ -133,7 +133,7 @@ internal class AuthEngine( crypto.setSymmetricKey(responseTopic, symmetricKey) val irnParams = IrnParams(Tags.AUTH_REQUEST_RESPONSE, Ttl(DAY_IN_SECONDS), false) - relayer.publishJsonRpcResponse( + jsonRpcInteractor.publishJsonRpcResponse( responseTopic, irnParams, response, envelopeType = EnvelopeType.ONE, participants = Participants(senderPublicKey, receiverPublicKey), onSuccess = { Logger.log("Success Responded on topic: $responseTopic") }, onFailure = { Logger.error("Error Responded on topic: $responseTopic") } @@ -156,7 +156,7 @@ internal class AuthEngine( } } else { val irnParams = IrnParams(Tags.AUTH_REQUEST_RESPONSE, Ttl(DAY_IN_SECONDS), false) - relayer.respondWithError(wcRequest, PeerError.MissingIssuer, irnParams) + jsonRpcInteractor.respondWithError(wcRequest, PeerError.MissingIssuer, irnParams) } } @@ -199,21 +199,21 @@ internal class AuthEngine( } private fun collectJsonRpcRequests() { - relayer.clientSyncJsonRpc + jsonRpcInteractor.clientSyncJsonRpc .filter { request -> request.params is AuthParams.RequestParams } .onEach { request -> onAuthRequest(request, request.params as AuthParams.RequestParams) } .launchIn(scope) } private fun collectJsonRpcResponses() { - relayer.peerResponse + jsonRpcInteractor.peerResponse .filter { response -> response.params is AuthParams.RequestParams } .onEach { response -> onAuthRequestResponse(response, response.params as AuthParams.RequestParams) } .launchIn(scope) } private fun resubscribeToSequences() { - relayer.isConnectionAvailable + jsonRpcInteractor.isConnectionAvailable .onEach { isAvailable -> _engineEvent.emit(ConnectionState(isAvailable)) } .filter { isAvailable: Boolean -> isAvailable } .onEach { @@ -228,12 +228,12 @@ internal class AuthEngine( pairingTopicToResponseTopicMap .map { it.value } .onEach { responseTopic: Topic -> - relayer.subscribe(responseTopic) + jsonRpcInteractor.subscribe(responseTopic) } } private fun collectInternalErrors() { - relayer.internalErrors + jsonRpcInteractor.internalErrors .onEach { exception -> _engineEvent.emit(SDKError(exception)) } .launchIn(scope) } diff --git a/chat/sdk/build.gradle.kts b/chat/sdk/build.gradle.kts index a17c7227c3..3ec344b38b 100644 --- a/chat/sdk/build.gradle.kts +++ b/chat/sdk/build.gradle.kts @@ -41,13 +41,14 @@ android { sqldelight { database("Database") { packageName = "com.walletconnect.chat" - dependency(project(":androidCore:impl")) + schemaOutputDirectory = file("src/debug/sqldelight/databases") + verifyMigrations = false } } dependencies { debugImplementation(project(":androidCore:impl")) - releaseImplementation("com.walletconnect:android-core-impl:1.0.0") + releaseImplementation("com.walletconnect:android-core-impl:1.1.0") retrofit() navigationComponent() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatParams.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatParams.kt index 9d1ba58b42..89178de93d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatParams.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatParams.kt @@ -2,7 +2,7 @@ package com.walletconnect.chat.common.json_rpc import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import com.walletconnect.android.impl.common.model.type.ClientParams +import com.walletconnect.android.internal.common.model.ClientParams import com.walletconnect.chat.common.model.Media internal sealed class ChatParams : ClientParams { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt index 3385157134..ed5b21b8aa 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt @@ -2,7 +2,7 @@ package com.walletconnect.chat.common.json_rpc import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import com.walletconnect.android.impl.common.model.type.JsonRpcClientSync +import com.walletconnect.android.internal.common.model.JsonRpcClientSync import com.walletconnect.chat.json_rpc.model.JsonRpcMethod internal sealed class ChatRpc : JsonRpcClientSync { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index d9405ba217..605ef9b972 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -2,18 +2,13 @@ package com.walletconnect.chat.engine.domain -import com.walletconnect.android.common.JsonRpcResponse -import com.walletconnect.android.common.model.Tags -import com.walletconnect.android.common.scope -import com.walletconnect.android.exception.GenericException -import com.walletconnect.android.impl.common.model.IrnParams -import com.walletconnect.android.impl.common.model.Participants -import com.walletconnect.android.impl.common.model.sync.WCRequest -import com.walletconnect.android.impl.common.model.sync.WCResponse -import com.walletconnect.android.impl.common.model.type.enums.EnvelopeType -import com.walletconnect.android.impl.crypto.KeyManagementRepository import com.walletconnect.android.impl.utils.DAY_IN_SECONDS import com.walletconnect.android.impl.utils.Logger +import com.walletconnect.android.internal.common.JsonRpcResponse +import com.walletconnect.android.internal.common.crypto.KeyManagementRepository +import com.walletconnect.android.internal.common.exception.GenericException +import com.walletconnect.android.internal.common.model.* +import com.walletconnect.android.internal.common.scope import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.common.json_rpc.ChatRpc @@ -21,7 +16,6 @@ import com.walletconnect.chat.common.json_rpc.ChatParams import com.walletconnect.chat.discovery.keyserver.domain.use_case.RegisterAccountUseCase import com.walletconnect.chat.discovery.keyserver.domain.use_case.ResolveAccountUseCase import com.walletconnect.chat.engine.model.EngineDO -import com.walletconnect.chat.json_rpc.domain.JsonRpcInteractor import com.walletconnect.chat.storage.ChatStorageRepository import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic @@ -37,7 +31,7 @@ internal class ChatEngine( private val registerAccountUseCase: RegisterAccountUseCase, private val resolveAccountUseCase: ResolveAccountUseCase, private val keyManagementRepository: KeyManagementRepository, - private val jsonRpcInteractor: JsonRpcInteractor, + private val jsonRpcInteractor: JsonRpcInteractorInterface, private val chatStorage: ChatStorageRepository, ) { private val _events: MutableSharedFlow = MutableSharedFlow() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt deleted file mode 100644 index c9a2b09740..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/domain/JsonRpcInteractor.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.walletconnect.chat.json_rpc.domain - -import com.walletconnect.android.RelayConnectionInterface -import com.walletconnect.android.impl.crypto.Codec -import com.walletconnect.android.impl.json_rpc.domain.BaseJsonRpcInteractor -import com.walletconnect.android.impl.storage.JsonRpcHistory -import com.walletconnect.chat.json_rpc.data.JsonRpcSerializer - -internal class JsonRpcInteractor( - relay: RelayConnectionInterface, - chaChaPolyCodec: Codec, - jsonRpcHistory: JsonRpcHistory, - serializer: JsonRpcSerializer -) : BaseJsonRpcInteractor(relay, serializer, chaChaPolyCodec, jsonRpcHistory) diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index ef6d77e22b..12407c92ef 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -114,7 +114,7 @@ internal class SignEngine( val irnParams = IrnParams(Tags.SESSION_PROPOSE, Ttl(FIVE_MINUTES_IN_SECONDS), true) jsonRpcInteractor.subscribe(pairing.topic) - relayer.publishJsonRpcRequests(pairing.topic, irnParams, request, + jsonRpcInteractor.publishJsonRpcRequest(pairing.topic, irnParams, request, onSuccess = { Logger.log("Session proposal sent successfully") onSuccess() @@ -187,8 +187,8 @@ internal class SignEngine( val approvalParams = proposal.toSessionApproveParams(selfPublicKey) val irnParams = IrnParams(Tags.SESSION_PROPOSE_RESPONSE, Ttl(FIVE_MINUTES_IN_SECONDS)) - relayer.subscribe(sessionTopic) - relayer.respondWithParams(request, approvalParams, irnParams) + jsonRpcInteractor.subscribe(sessionTopic) + jsonRpcInteractor.respondWithParams(request, approvalParams, irnParams) sessionSettle(request.id, proposal, sessionTopic, request.topic) } @@ -448,7 +448,7 @@ onFailure(error) } private fun collectJsonRpcRequests() { - relayer.clientSyncJsonRpc + jsonRpcInteractor.clientSyncJsonRpc .filter { request -> request.params is SignParamsVO } .onEach { request -> when (val requestParams = request.params) { @@ -465,7 +465,7 @@ onFailure(error) } private fun collectInternalErrors() { - merge(relayer.internalErrors, pairingInterface.findWrongMethodsFlow) + merge(jsonRpcInteractor.internalErrors, pairingInterface.findWrongMethodsFlow) .onEach { exception -> _engineEvent.emit(SDKError(exception)) } .launchIn(scope) } @@ -549,7 +549,7 @@ onFailure(error) return } - relayer.unsubscribe(request.topic, onSuccess = { + jsonRpcInteractor.unsubscribe(request.topic, onSuccess = { crypto.removeKeys(request.topic.value) sessionStorageRepository.deleteSession(request.topic) scope.launch { _engineEvent.emit(params.toEngineDO(request.topic)) } @@ -832,7 +832,7 @@ onFailure(error) pairingInterface.topicExpiredFlow.onEach { topic -> sessionStorageRepository.getAllSessionTopicsByPairingTopic(topic).onEach { sessionTopic -> - relayer.unsubscribe(Topic(sessionTopic), onSuccess = { + jsonRpcInteractor.unsubscribe(Topic(sessionTopic), onSuccess = { sessionStorageRepository.deleteSession(Topic(sessionTopic)) crypto.removeKeys(sessionTopic) }) From 162a0e91ac037d68e37a01e0540a8a37de150bef Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 25 Oct 2022 09:49:28 +0200 Subject: [PATCH 05/30] Fix import --- .../kotlin/com/walletconnect/android/impl/di/StorageModule.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt b/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt index cf3f1c7049..407dbe3a01 100644 --- a/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt +++ b/androidCore/impl/src/debug/kotlin/com/walletconnect/android/impl/di/StorageModule.kt @@ -4,6 +4,7 @@ import com.squareup.sqldelight.android.AndroidSqliteDriver import com.squareup.sqldelight.db.SqlDriver import com.walletconnect.android.impl.core.AndroidCoreDatabase import org.koin.android.ext.koin.androidContext +import org.koin.core.qualifier.named import org.koin.dsl.module fun coreStorageModule() = module { From 0c6bbad39aabfe29934286659553cc0bf30c38a6 Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 25 Oct 2022 11:30:46 +0200 Subject: [PATCH 06/30] Tweaks after merging new android core --- .../impl/json_rpc/domain/JsonRpcInteractor.kt | 3 +- .../android/impl/utils/UtilFunctions.kt | 11 ++----- .../common/crypto/KeyManagementRepository.kt | 2 ++ .../auth/engine/domain/AuthEngine.kt | 3 -- .../chatsample/ChatSampleApplication.kt | 16 +++++++--- .../ui/shared/ChatSharedViewModel.kt | 6 ++-- .../com/walletconnect/chat/client/Chat.kt | 4 +-- .../walletconnect/chat/client/ChatProtocol.kt | 10 ++---- .../common/adapter/JsonRpcResultAdapter.kt | 2 +- .../com/walletconnect/chat/di/CommonModule.kt | 13 ++++---- .../walletconnect/chat/di/JsonRpcModule.kt | 23 ++++++++----- .../walletconnect/chat/di/KeyServerModule.kt | 4 ++- .../walletconnect/chat/di/StorageModule.kt | 3 +- .../chat/engine/domain/ChatEngine.kt | 5 +-- .../chat/json_rpc/data/JsonRpcSerializer.kt | 32 ------------------- .../walletconnect/sign/di/JsonRpcModule.kt | 1 + 16 files changed, 56 insertions(+), 82 deletions(-) delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt index 25f0df8c57..034b84bd4f 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt @@ -28,8 +28,7 @@ internal class JsonRpcInteractor( private val chaChaPolyCodec: Codec, private val jsonRpcHistory: JsonRpcHistory, ) : JsonRpcInteractorInterface { - private val serializer: JsonRpcSerializer - get() = wcKoinApp.koin.get() + private val serializer: JsonRpcSerializer get() = wcKoinApp.koin.get() private val _clientSyncJsonRpc: MutableSharedFlow = MutableSharedFlow() override val clientSyncJsonRpc: SharedFlow = _clientSyncJsonRpc.asSharedFlow() diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/UtilFunctions.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/UtilFunctions.kt index 87f159b928..992bd1808b 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/UtilFunctions.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/UtilFunctions.kt @@ -2,9 +2,7 @@ package com.walletconnect.utils -import com.walletconnect.android.impl.di.AndroidCoreDITags import com.walletconnect.android.impl.utils.CURRENT_TIME_IN_SECONDS -import com.walletconnect.android.impl.utils.Logger import com.walletconnect.android.internal.common.SerializableJsonRpc import com.walletconnect.android.internal.common.model.Expiry import org.koin.core.module.KoinDefinition @@ -32,12 +30,7 @@ val String.Companion.HexPrefix get() = "0x" inline fun Module.addSerializerEntry(value: KClass): KoinDefinition<*> = - single(qualifier = named("key_${T::class.getFullName()}")) { - value - } - + single(qualifier = named("key_${T::class.getFullName()}")) { value } fun Module.addDeserializerEntry(key: String, value: KClass<*>): KoinDefinition<*> = - single(qualifier = named("${key::class.getFullName()}_${value::class.getFullName()}_$key")) { - key to value - } \ No newline at end of file + single(qualifier = named("${key::class.getFullName()}_${value::class.getFullName()}_$key")) { key to value } \ No newline at end of file diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt index c987762bbd..b7fe7d6568 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt @@ -24,8 +24,10 @@ interface KeyManagementRepository { //Added with Chat SDK fun generateInviteSelfKeyPair(): Pair + fun getInviteSelfPublicKey(): PublicKey fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) + fun getHash(string: String): String fun getInvitePublicKey(topic: Topic): PublicKey fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt index c321d75aec..d4a66ae004 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt @@ -162,13 +162,10 @@ internal class AuthEngine( private fun onAuthRequestResponse(wcResponse: WCResponse, requestParams: AuthParams.RequestParams) { val pairingTopic = wcResponse.topic - pairingInterface.updateExpiry(pairingTopic.value, Expiry(MONTH_IN_SECONDS)) pairingInterface.updateMetadata(pairingTopic.value, requestParams.requester.metadata.toClient(), AppMetaDataType.PEER) pairingInterface.activate(pairingTopic.value) - if (!pairingInterface.getPairings().any { pairing -> pairing.topic == pairingTopic.value }) return - pairingTopicToResponseTopicMap.remove(pairingTopic) when (val response = wcResponse.response) { diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt index a123e2a48e..1ecb654b54 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt @@ -2,8 +2,9 @@ package com.walletconnect.chatsample import android.app.Application import android.util.Log -import com.walletconnect.android.RelayClient -import com.walletconnect.android.connection.ConnectionType +import com.walletconnect.android.Core +import com.walletconnect.android.CoreClient +import com.walletconnect.android.relay.ConnectionType import com.walletconnect.chat.client.Chat import com.walletconnect.chat.client.ChatClient import com.walletconnect.chatsample.utils.tag @@ -14,10 +15,17 @@ class ChatSampleApplication : Application() { override fun onCreate() { super.onCreate() + val metadata = Core.Model.AppMetaData( + name = "Kotlin Wallet", + description = "Wallet description", + url = "example.wallet", + icons = listOf("https://gblobscdn.gitbook.com/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media"), + redirect = "kotlin-wallet-wc:/request", + ) val serverUri = "wss://$WALLET_CONNECT_PROD_RELAY_URL?projectId=${BuildConfig.PROJECT_ID}" - RelayClient.initialize(relayServerUrl = serverUri, connectionType = ConnectionType.AUTOMATIC, application = this) + CoreClient.initialize(relayServerUrl = serverUri, connectionType = ConnectionType.AUTOMATIC, application = this, metaData = metadata) - ChatClient.initialize(Chat.Params.Init(RelayClient, "https://keys.walletconnect.com")) { error -> + ChatClient.initialize(Chat.Params.Init(CoreClient, "https://keys.walletconnect.com")) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } } diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index 251b868f02..e2be0d87f7 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -109,7 +109,9 @@ class ChatSharedViewModel : ViewModel() { } fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { + ensToAccountIdMap[contact]?.let { accountId -> + ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(accountId)), object : Chat.Listeners.Resolve { override fun onError(error: Chat.Model.Error) { runBlocking(Dispatchers.Main) { @@ -173,8 +175,8 @@ class ChatSharedViewModel : ViewModel() { private const val isPrimary = true - val SELF_ACCOUNT = if (isPrimary) KOTLIN_ACCOUNT_ID else TEST_ACCOUNT_ID - val SELF_ENS = if (isPrimary) KOTLIN_ENS else TEST_ENS + val SELF_ACCOUNT = if (isPrimary) KOTLIN_ACCOUNT_ID else TEST_ACCOUNT_ID // SWIFT_ACCOUNT_ID + val SELF_ENS = if (isPrimary) KOTLIN_ENS else TEST_ENS // SWIFT_ENS val ensToAccountIdMap = mapOf( SWIFT_ENS to SWIFT_ACCOUNT_ID, diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt index a395ebf50d..4abbbc7ae9 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt @@ -1,6 +1,6 @@ package com.walletconnect.chat.client -import com.walletconnect.android.RelayConnectionInterface +import com.walletconnect.android.CoreClient object Chat { @@ -60,7 +60,7 @@ object Chat { } sealed class Params { - data class Init(val relay: RelayConnectionInterface, val keyServerUrl: String) : Params() + data class Init(val core: CoreClient, val keyServerUrl: String) : Params() data class Register(val account: Model.AccountId, val private: Boolean? = false) : Params() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index 356cebae5f..e288ffccb2 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -1,24 +1,19 @@ package com.walletconnect.chat.client -import com.walletconnect.android.common.scope -import com.walletconnect.android.common.wcKoinApp import com.walletconnect.android.impl.di.cryptoModule -import com.walletconnect.android.impl.di.networkModule import com.walletconnect.android.impl.utils.Logger +import com.walletconnect.android.internal.common.scope +import com.walletconnect.android.internal.common.wcKoinApp import com.walletconnect.chat.client.mapper.toClient import com.walletconnect.chat.client.mapper.toEngineDO import com.walletconnect.chat.client.mapper.toVO import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.di.* -import com.walletconnect.chat.di.commonModule -import com.walletconnect.chat.di.jsonRpcModule -import com.walletconnect.chat.di.keyServerModule import com.walletconnect.chat.engine.domain.ChatEngine import com.walletconnect.chat.engine.model.EngineDO import com.walletconnect.foundation.common.model.PublicKey import kotlinx.coroutines.launch -import org.koin.core.KoinApplication internal class ChatProtocol : ChatInterface { private lateinit var chatEngine: ChatEngine @@ -34,7 +29,6 @@ internal class ChatProtocol : ChatInterface { with(init) { wcKoinApp.run { modules( - networkModule(relay), commonModule(), cryptoModule(), keyServerModule(keyServerUrl), diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/adapter/JsonRpcResultAdapter.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/adapter/JsonRpcResultAdapter.kt index e68fa1c8f4..d5add148b5 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/adapter/JsonRpcResultAdapter.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/adapter/JsonRpcResultAdapter.kt @@ -7,7 +7,7 @@ import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import com.squareup.moshi.Moshi import com.squareup.moshi.internal.Util -import com.walletconnect.android.common.JsonRpcResponse +import com.walletconnect.android.internal.common.JsonRpcResponse import com.walletconnect.chat.common.json_rpc.ChatParams import org.json.JSONArray import org.json.JSONObject diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt index 0d29a482d9..9744a2b32a 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/CommonModule.kt @@ -4,27 +4,26 @@ package com.walletconnect.chat.di import com.squareup.moshi.Moshi import com.tinder.scarlet.utils.getRawType -import com.walletconnect.android.common.JsonRpcResponse -import com.walletconnect.android.common.di.AndroidCommonDITags +import com.walletconnect.android.internal.common.JsonRpcResponse +import com.walletconnect.android.internal.common.di.AndroidCommonDITags import com.walletconnect.chat.common.adapter.JsonRpcResultAdapter import org.koin.core.qualifier.named import org.koin.dsl.module import kotlin.reflect.jvm.jvmName +import com.walletconnect.android.internal.common.di.commonModule as androidCommonModule @JvmSynthetic internal fun commonModule() = module { - includes(com.walletconnect.android.common.di.commonModule()) + includes(androidCommonModule()) - single { - get(named(AndroidCommonDITags.MOSHI)) - .newBuilder() + single() { + get(named(AndroidCommonDITags.MOSHI)) .add { type, _, moshi -> when (type.getRawType().name) { JsonRpcResponse.JsonRpcResult::class.jvmName -> JsonRpcResultAdapter(moshi) else -> null } } - .build() } } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt index 54a4846803..83f96ac8ba 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt @@ -2,18 +2,25 @@ package com.walletconnect.chat.di -import com.walletconnect.chat.json_rpc.data.JsonRpcSerializer -import com.walletconnect.chat.json_rpc.domain.JsonRpcInteractor +import com.walletconnect.chat.common.json_rpc.ChatRpc +import com.walletconnect.chat.json_rpc.model.JsonRpcMethod +import com.walletconnect.utils.addDeserializerEntry +import com.walletconnect.utils.addSerializerEntry import org.koin.dsl.module +import com.walletconnect.android.impl.di.jsonRpcModule as coreJsonRpcModule @JvmSynthetic internal fun jsonRpcModule() = module { - single { - JsonRpcSerializer(get()) - } + includes(coreJsonRpcModule()) - single { - JsonRpcInteractor(get(), get(), get(), get()) - } + addSerializerEntry(ChatRpc.ChatMessage::class) + addSerializerEntry(ChatRpc.ChatInvite::class) + addSerializerEntry(ChatRpc.ChatLeave::class) + addSerializerEntry(ChatRpc.ChatPing::class) + + addDeserializerEntry(JsonRpcMethod.WC_CHAT_MESSAGE, ChatRpc.ChatMessage::class) + addDeserializerEntry(JsonRpcMethod.WC_CHAT_INVITE, ChatRpc.ChatInvite::class) + addDeserializerEntry(JsonRpcMethod.WC_CHAT_LEAVE, ChatRpc.ChatLeave::class) + addDeserializerEntry(JsonRpcMethod.WC_CHAT_PING, ChatRpc.ChatPing::class) } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/KeyServerModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/KeyServerModule.kt index 70ff941eb1..6bd8497ff7 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/KeyServerModule.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/KeyServerModule.kt @@ -2,11 +2,13 @@ package com.walletconnect.chat.di +import com.walletconnect.android.internal.common.di.AndroidCommonDITags import com.walletconnect.chat.discovery.keyserver.data.client.KeyServerClient import com.walletconnect.chat.discovery.keyserver.data.service.KeyServerService import com.walletconnect.chat.discovery.keyserver.domain.use_case.RegisterAccountUseCase import com.walletconnect.chat.discovery.keyserver.domain.use_case.ResolveAccountUseCase import okhttp3.OkHttpClient +import org.koin.core.qualifier.named import org.koin.dsl.module import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory @@ -30,7 +32,7 @@ internal fun keyServerModule(keyServerUrl: String) = module { Retrofit.Builder() .baseUrl(keyServerUrl) .client(get()) - .addConverterFactory(MoshiConverterFactory.create(get())) + .addConverterFactory(MoshiConverterFactory.create(get(named(AndroidCommonDITags.MOSHI)))) .build() } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt index 9dd3413719..91ce9ab447 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt @@ -1,6 +1,7 @@ package com.walletconnect.chat.di import com.walletconnect.android.impl.di.coreStorageModule +import com.walletconnect.android.impl.di.sdkBaseStorageModule import com.walletconnect.chat.Database import com.walletconnect.chat.storage.ChatStorageRepository import org.koin.dsl.module @@ -8,7 +9,7 @@ import org.koin.dsl.module @JvmSynthetic internal fun storageModule(storageSuffix: String) = module { - includes(coreStorageModule(Database.Schema, storageSuffix)) + includes(coreStorageModule(), sdkBaseStorageModule(Database.Schema, storageSuffix)) single { Database(get()) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 605ef9b972..d452ac84cd 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -41,6 +41,7 @@ internal class ChatEngine( init { collectJsonRpcRequests() collectPeerResponses() + jsonRpcInteractor.initializationErrorsFlow.onEach { error -> Logger.error(error) }.launchIn(scope) jsonRpcInteractor.isConnectionAvailable .onEach { isAvailable -> @@ -76,6 +77,7 @@ internal class ChatEngine( fun _onSuccess(publicKey: PublicKey) { val topic = Topic(keyManagementRepository.getHash(publicKey.keyAsHex)) keyManagementRepository.setInviteSelfPublicKey(topic, publicKey) + keyManagementRepository.setSelfParticipant(publicKey, topic) trySubscribeToInviteTopic() onSuccess(publicKey.keyAsHex) } @@ -207,7 +209,6 @@ internal class ChatEngine( onFailure(error) } - internal fun reject(inviteId: String, onFailure: (Throwable) -> Unit) { // //todo: correct define params // val request = WCRequest() @@ -276,7 +277,7 @@ internal class ChatEngine( private fun collectPeerResponses() { scope.launch { jsonRpcInteractor.peerResponse.collect { response -> - when (val params = response.params) { + when (response.params) { is ChatParams.InviteParams -> onInviteResponse(response) } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt deleted file mode 100644 index 5a2852b11c..0000000000 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/data/JsonRpcSerializer.kt +++ /dev/null @@ -1,32 +0,0 @@ -@file:JvmSynthetic - -package com.walletconnect.chat.json_rpc.data - -import com.squareup.moshi.Moshi -import com.walletconnect.android.common.SerializableJsonRpc -import com.walletconnect.android.impl.common.model.type.ClientParams -import com.walletconnect.android.impl.json_rpc.data.JsonRpcSerializerAbstract -import com.walletconnect.chat.common.json_rpc.ChatRpc -import com.walletconnect.chat.json_rpc.model.JsonRpcMethod -import com.walletconnect.util.Empty - -internal class JsonRpcSerializer(override val moshi: Moshi) : JsonRpcSerializerAbstract(moshi) { - - override fun deserialize(method: String, json: String): ClientParams? = - when (method) { - JsonRpcMethod.WC_CHAT_MESSAGE -> tryDeserialize(json)?.params - JsonRpcMethod.WC_CHAT_INVITE -> tryDeserialize(json)?.params - JsonRpcMethod.WC_CHAT_LEAVE -> tryDeserialize(json)?.params - JsonRpcMethod.WC_CHAT_PING -> tryDeserialize(json)?.params - else -> null - } - - override fun sdkSpecificSerialize(payload: SerializableJsonRpc): String = - when (payload) { - is ChatRpc.ChatMessage -> trySerialize(payload) - is ChatRpc.ChatInvite -> trySerialize(payload) - is ChatRpc.ChatLeave -> trySerialize(payload) - is ChatRpc.ChatPing -> trySerialize(payload) - else -> String.Empty - } -} \ No newline at end of file diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/di/JsonRpcModule.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/di/JsonRpcModule.kt index 9f32077b0d..243413eccb 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/di/JsonRpcModule.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/di/JsonRpcModule.kt @@ -8,6 +8,7 @@ import com.walletconnect.utils.addDeserializerEntry import com.walletconnect.utils.addSerializerEntry import org.koin.dsl.module import com.walletconnect.android.impl.di.jsonRpcModule as coreJsonRpcModule + @JvmSynthetic internal fun jsonRpcModule() = module { From b2eb8d6c855f7005d8d7515ece4a17b3a0361a2e Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 25 Oct 2022 12:19:01 +0200 Subject: [PATCH 07/30] Clean up for KeyStore --- .../BouncyCastleKeyManagementRepository.kt | 16 ++++------ .../common/crypto/KeyManagementRepository.kt | 5 ++-- .../internal/common/storage/KeyChain.kt | 30 ++++--------------- .../internal/common/storage/KeyStore.kt | 8 +---- .../chat/engine/domain/ChatEngine.kt | 2 +- 5 files changed, 15 insertions(+), 46 deletions(-) diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt index 7feeed452c..ba075730b0 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt @@ -35,7 +35,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } override fun getSymmetricKey(topic: Topic): SymmetricKey { - val symmetricKey = keyChain.getKey(topic.value) + val symmetricKey = keyChain.getKey(topic.value) ?: throw Exception("Unable to find symmetric key") return SymmetricKey(symmetricKey) } @@ -67,7 +67,7 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } override fun getSelfParticipant(topic: Topic): PublicKey? { - val keyAsHex = keyChain.getKey("$SELF_PARTICIPANT_CONTEXT${topic.value}") + val keyAsHex = keyChain.getKey("$SELF_PARTICIPANT_CONTEXT${topic.value}") ?: throw Exception("Unable to find self participant key") return if (keyAsHex == String.Empty) null else PublicKey(keyAsHex) } @@ -146,7 +146,6 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor const val KEY_AGREEMENT_CONTEXT = "key_agreement/" const val SELF_PARTICIPANT_CONTEXT = "self_participant/" - const val INVITE_CONTEXT = "invite/" const val SELF_INVITE_PUBLIC_KEY = "selfInviteKey/" } @@ -162,14 +161,13 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor // Added with Chat SDK override fun getInviteSelfPublicKey(): PublicKey { - val publicKey = keyChain.getInviteSelfPublicKey(SELF_INVITE_PUBLIC_KEY) ?: throw Exception("TODO: Name me / Create exception") + val publicKey = keyChain.getKey(SELF_INVITE_PUBLIC_KEY) ?: throw Exception("No Invite SelfPublicKey") return PublicKey(publicKey) } // Added with Chat SDK - override fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) { - keyChain.setInviteSelfPublicKey(SELF_INVITE_PUBLIC_KEY, publicKey) - keyChain.setPublicKey("$INVITE_CONTEXT${topic.value}", publicKey) + override fun setInviteSelfPublicKey(publicKey: PublicKey, topic: Topic) { + keyChain.setKey(SELF_INVITE_PUBLIC_KEY, publicKey) } // Added with Chat SDK. TODO: This could be removed after proper refactor @@ -199,8 +197,4 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor // Added with Chat SDK override fun getHash(string: String): String = sha256(string) - - - // Added with Chat SDK - override fun getInvitePublicKey(topic: Topic): PublicKey = PublicKey(keyChain.getPublicKey("$INVITE_CONTEXT${topic.value}")) } \ No newline at end of file diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt index b7fe7d6568..b102cba8b8 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt @@ -26,10 +26,11 @@ interface KeyManagementRepository { fun generateInviteSelfKeyPair(): Pair fun getInviteSelfPublicKey(): PublicKey - fun setInviteSelfPublicKey(topic: Topic, publicKey: PublicKey) + fun setInviteSelfPublicKey(publicKey: PublicKey, topic: Topic) fun getHash(string: String): String - fun getInvitePublicKey(topic: Topic): PublicKey + + // fun getInvitePublicKey(topic: Topic): PublicKey fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic } \ No newline at end of file diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyChain.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyChain.kt index dc51d5eb23..9261a5c4e8 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyChain.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyChain.kt @@ -15,18 +15,18 @@ internal class KeyChain(private val sharedPreferences: SharedPreferences) : KeyS sharedPreferences.edit().putString(tag, key.keyAsHex).apply() } - override fun getKey(tag: String): String { - return sharedPreferences.getString(tag, String.Empty) ?: String.Empty //todo: Return null instead of String.Empty + override fun getKey(tag: String): String? { + return sharedPreferences.getString(tag, null) } - override fun setKeys(tag: String, keyA: Key, keyB: Key) { - val keys = concatKeys(keyA, keyB) + override fun setKeys(tag: String, key1: Key, key2: Key) { + val keys = concatKeys(key1, key2) sharedPreferences.edit().putString(tag, keys).apply() } @Throws(InternalError::class) override fun getKeys(tag: String): Pair { - val concatKeys = sharedPreferences.getString(tag, null) ?: throw InternalError("unable to find keys") + val concatKeys = sharedPreferences.getString(tag, null) ?: throw InternalError("Unable to find keys") return splitKeys(concatKeys) } @@ -49,24 +49,4 @@ internal class KeyChain(private val sharedPreferences: SharedPreferences) : KeyS return keyA.bytesToHex() to keyB.bytesToHex() } - - // Added With Chat SDK - override fun getInviteSelfPublicKey(tag: String): String? { - return sharedPreferences.getString(tag, null) - } - - // Added With Chat SDK - override fun setInviteSelfPublicKey(tag: String, key: Key) { - sharedPreferences.edit().putString(tag, key.keyAsHex).apply() - } - - // Added With Chat SDK - override fun getPublicKey(tag: String): String { - return sharedPreferences.getString(tag, String.Empty) ?: String.Empty - } - - // Added With Chat SDK - override fun setPublicKey(tag: String, publicKey: PublicKey) { - sharedPreferences.edit().putString(tag, publicKey.keyAsHex).apply() - } } \ No newline at end of file diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt index 166613fbf2..055d7e7a2e 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt @@ -6,7 +6,7 @@ import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PublicKey interface KeyStore { - fun getKey(tag: String): String + fun getKey(tag: String): String? fun setKey(tag: String, key: Key) @Throws(InternalError::class) @@ -15,10 +15,4 @@ interface KeyStore { fun deleteKeys(tag: String) fun checkKeys(tag: String): Boolean - - // Added With Chat SDK - fun getInviteSelfPublicKey(tag: String): String? - fun setInviteSelfPublicKey(tag: String, key: Key) - fun getPublicKey(tag: String): String - fun setPublicKey(tag: String, publicKey: PublicKey) } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index d452ac84cd..82b4a8b4c4 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -76,7 +76,7 @@ internal class ChatEngine( ) { fun _onSuccess(publicKey: PublicKey) { val topic = Topic(keyManagementRepository.getHash(publicKey.keyAsHex)) - keyManagementRepository.setInviteSelfPublicKey(topic, publicKey) + keyManagementRepository.setInviteSelfPublicKey(publicKey, topic) keyManagementRepository.setSelfParticipant(publicKey, topic) trySubscribeToInviteTopic() onSuccess(publicKey.keyAsHex) From b701d59f52d54979d5d1d6c4ba8f5e4a90bf2a84 Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 25 Oct 2022 14:56:38 +0200 Subject: [PATCH 08/30] Clean up for KeyManagementRepository.kt --- .../impl/data/codec/ChaChaPolyCodec.kt | 10 +- .../BouncyCastleKeyManagementRepository.kt | 140 +++++------------- .../android/impl/utils/Context.kt | 4 + .../impl/BouncyCastleCryptoRepositoryTest.kt | 9 +- .../android/impl/ChaChaPolyCodecTest.kt | 19 +-- .../common/crypto/KeyManagementRepository.kt | 30 ++-- .../internal/common/storage/KeyStore.kt | 1 - .../android/pairing/PairingClient.kt | 8 +- .../auth/engine/domain/AuthEngine.kt | 7 +- .../chat/engine/domain/ChatEngine.kt | 41 ++--- .../sign/engine/domain/SignEngine.kt | 2 +- 11 files changed, 108 insertions(+), 163 deletions(-) create mode 100644 androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/Context.kt diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt index 2d2d784e81..747707ed97 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt @@ -9,6 +9,7 @@ import com.walletconnect.android.internal.common.model.Participants import com.walletconnect.android.internal.common.model.SymmetricKey import com.walletconnect.android.internal.common.model.EnvelopeType import com.walletconnect.android.impl.crypto.Codec +import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic @@ -54,7 +55,10 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen return when (val envelopeType = encryptedPayloadBytes.envelopeType) { EnvelopeType.ZERO.id -> decryptType0(topic, encryptedPayloadBytes) - EnvelopeType.ONE.id -> decryptType1(encryptedPayloadBytes, keyManagementRepository.getSelfParticipant(topic)) + EnvelopeType.ONE.id -> decryptType1( + encryptedPayloadBytes, + keyManagementRepository.getKey("$SELF_PARTICIPANT_CONTEXT${topic.value}", PublicKey::class) as PublicKey + ) else -> throw UnknownEnvelopeTypeException("Decrypt; Unknown envelope type: $envelopeType") } } @@ -70,7 +74,7 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen byteBuffer.get(nonce) byteBuffer.get(encryptedMessageBytes) - val symmetricKey = keyManagementRepository.getSymmetricKey(topic) + val symmetricKey = keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey val decryptedTextBytes = decryptPayload(symmetricKey, nonce, encryptedMessageBytes) return String(decryptedTextBytes, Charsets.UTF_8) @@ -99,7 +103,7 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen } private fun encryptEnvelopeType0(topic: Topic, nonceBytes: ByteArray, input: ByteArray, envelopeType: EnvelopeType): String { - val symmetricKey = keyManagementRepository.getSymmetricKey(topic) + val symmetricKey = keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey val cipherBytes = encryptPayload(symmetricKey, nonceBytes, input) val payloadSize = cipherBytes.size + NONCE_SIZE + ENVELOPE_TYPE_SIZE diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt index ba075730b0..bfc4cd972e 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt @@ -2,15 +2,15 @@ package com.walletconnect.android.impl.data.repository -import com.walletconnect.android.internal.common.storage.KeyStore -import com.walletconnect.android.internal.common.model.SymmetricKey import com.walletconnect.android.internal.common.crypto.KeyManagementRepository +import com.walletconnect.android.internal.common.model.SymmetricKey +import com.walletconnect.android.internal.common.storage.KeyStore +import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic import com.walletconnect.util.bytesToHex import com.walletconnect.util.hexToBytes -import com.walletconnect.utils.Empty import org.bouncycastle.crypto.digests.SHA256Digest import org.bouncycastle.crypto.generators.HKDFBytesGenerator import org.bouncycastle.crypto.params.HKDFParameters @@ -18,26 +18,34 @@ import org.bouncycastle.math.ec.rfc7748.X25519 import java.security.MessageDigest import java.security.SecureRandom import javax.crypto.KeyGenerator -import com.walletconnect.foundation.common.model.Key as WCKey +import kotlin.reflect.KClass -//todo: Refactor internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStore) : KeyManagementRepository { - override fun generateAndStoreSymmetricKey(topic: Topic): SymmetricKey { - val symmetricKey = generateSymmetricKey() - keyChain.setKey(topic.value, symmetricKey) - return symmetricKey - } - override fun generateSymmetricKey(): SymmetricKey = SymmetricKey(createSymmetricKey().bytesToHex()) + override fun setKey(key: Key, tag: String) { + keyChain.setKey(tag, key) + } - override fun setSymmetricKey(topic: Topic, symmetricKey: SymmetricKey) { - keyChain.setKey(topic.value, symmetricKey) + override fun getKey(tag: String, clazz: KClass): Key { + val key = keyChain.getKey(tag) ?: throw Exception("No Key for tag: $tag") + return when (clazz) { + PublicKey::class -> PublicKey(key) + SymmetricKey::class -> SymmetricKey(key) + PrivateKey::class -> PrivateKey(key) + else -> throw Exception("Wrong key type: $clazz") + } } - override fun getSymmetricKey(topic: Topic): SymmetricKey { - val symmetricKey = keyChain.getKey(topic.value) ?: throw Exception("Unable to find symmetric key") + override fun getKeyAgreement(topic: Topic): Pair { + val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" + val (selfPublic, peerPublic) = keyChain.getKeys(tag) - return SymmetricKey(symmetricKey) + return Pair(PublicKey(selfPublic), PublicKey(peerPublic)) + } + + override fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) { + val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" + keyChain.setKeys(tag, self, peer) } override fun generateKeyPair(): PublicKey { @@ -45,30 +53,15 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor val privateKey = ByteArray(KEY_SIZE) X25519.generatePrivateKey(SecureRandom(ByteArray(KEY_SIZE)), privateKey) X25519.generatePublicKey(privateKey, 0, publicKey, 0) - setKeyPair(PublicKey(publicKey.bytesToHex().lowercase()), PrivateKey(privateKey.bytesToHex().lowercase())) + setKeyPair(PublicKey(publicKey.bytesToHex().lowercase()), PrivateKey(privateKey.bytesToHex().lowercase())) return PublicKey(publicKey.bytesToHex().lowercase()) } - override fun generateTopicFromKeyAgreementAndSafeSymKey(self: PublicKey, peer: PublicKey): Topic { - val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer) - val topic = Topic(sha256(symmetricKey.keyAsHex)) - keyChain.setKey(topic.value.lowercase(), symmetricKey) - setKeyAgreement(topic, self, peer) - - return topic - } - - override fun getTopicFromKey(key: WCKey): Topic = Topic(sha256(key.keyAsHex)) - - override fun setSelfParticipant(key: PublicKey, topic: Topic) { - val tag = "$SELF_PARTICIPANT_CONTEXT${topic.value}" - keyChain.setKey(tag, key) - } - - override fun getSelfParticipant(topic: Topic): PublicKey? { - val keyAsHex = keyChain.getKey("$SELF_PARTICIPANT_CONTEXT${topic.value}") ?: throw Exception("Unable to find self participant key") - return if (keyAsHex == String.Empty) null else PublicKey(keyAsHex) + override fun generateAndStoreSymmetricKey(topic: Topic): SymmetricKey { + val symmetricKey = SymmetricKey(createSymmetricKey().bytesToHex()) + keyChain.setKey(topic.value, symmetricKey) + return symmetricKey } override fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey { @@ -81,6 +74,16 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor return SymmetricKey(symmetricKeyBytes.bytesToHex()) } + override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic { + val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer) + val topic = Topic(sha256(symmetricKey.keyAsHex)) + keyChain.setKey(topic.value.lowercase(), symmetricKey) + setKeyAgreement(topic, self, peer) + return topic + } + + override fun getTopicFromKey(key: Key): Topic = Topic(sha256(key.keyAsHex)) + override fun removeKeys(tag: String) { val (publicKey, _) = keyChain.getKeys(tag) with(keyChain) { @@ -89,23 +92,11 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor } } - override fun getKeyAgreement(topic: Topic): Pair { - val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" - val (selfPublic, peerPublic) = keyChain.getKeys(tag) - - return Pair(PublicKey(selfPublic), PublicKey(peerPublic)) - } - - override fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) { - val tag = "$KEY_AGREEMENT_CONTEXT${topic.value}" - keyChain.setKeys(tag, self, peer) - } - internal fun setKeyPair(publicKey: PublicKey, privateKey: PrivateKey) { keyChain.setKeys(publicKey.keyAsHex, publicKey, privateKey) } - internal fun getKeyPair(wcKey: WCKey): Pair { + internal fun getKeyPair(wcKey: Key): Pair { val (publicKeyHex, privateKeyHex) = keyChain.getKeys(wcKey.keyAsHex) return Pair(PublicKey(publicKeyHex), PrivateKey(privateKeyHex)) @@ -145,56 +136,5 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor const val AES: String = "AES" const val KEY_AGREEMENT_CONTEXT = "key_agreement/" - const val SELF_PARTICIPANT_CONTEXT = "self_participant/" - const val SELF_INVITE_PUBLIC_KEY = "selfInviteKey/" - } - - - // Added with Chat SDK - override fun generateInviteSelfKeyPair(): Pair { - val keyPair: Pair = generateWithoutSavingKeyPair() // TODO: Refactor on extracting core. - // Note: This could be cleaner with refactor of such method as generateKeyPair so it wont save keys - // Note: I wont do it here because I don't want two versions of this file - setKeyPair(keyPair.first, keyPair.second) - return keyPair - } - - // Added with Chat SDK - override fun getInviteSelfPublicKey(): PublicKey { - val publicKey = keyChain.getKey(SELF_INVITE_PUBLIC_KEY) ?: throw Exception("No Invite SelfPublicKey") - return PublicKey(publicKey) } - - // Added with Chat SDK - override fun setInviteSelfPublicKey(publicKey: PublicKey, topic: Topic) { - keyChain.setKey(SELF_INVITE_PUBLIC_KEY, publicKey) - } - - // Added with Chat SDK. TODO: This could be removed after proper refactor - private fun generateWithoutSavingKeyPair(): Pair { - val publicKey = ByteArray(KEY_SIZE) - val privateKey = ByteArray(KEY_SIZE) - X25519.generatePrivateKey(SecureRandom(ByteArray(KEY_SIZE)), privateKey) - X25519.generatePublicKey(privateKey, 0, publicKey, 0) - - return PublicKey(publicKey.bytesToHex().lowercase()) to PrivateKey(privateKey.bytesToHex().lowercase()) - } - - // Added with Chat SDK - override fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic { - val symmetricKey = generateSymmetricKeyFromKeyAgreement(self, peer) - val topic = generateTopicFromSymmetricKey(symmetricKey) - setKeyAgreement(topic, self, peer) - return topic - } - - // Added with Chat SDK - private fun generateTopicFromSymmetricKey(symmetricKey: SymmetricKey): Topic { - val topic = Topic(sha256(symmetricKey.keyAsHex)) - keyChain.setKey(topic.value.lowercase(), symmetricKey) - return topic - } - - // Added with Chat SDK - override fun getHash(string: String): String = sha256(string) } \ No newline at end of file diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/Context.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/Context.kt new file mode 100644 index 0000000000..8b3755d75a --- /dev/null +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/utils/Context.kt @@ -0,0 +1,4 @@ +package com.walletconnect.android.impl.utils + +const val SELF_PARTICIPANT_CONTEXT = "self_participant/" +const val SELF_INVITE_PUBLIC_KEY_CONTEXT = "self_inviteKey/" \ No newline at end of file diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt index 9389cf07d0..42a2a7de03 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt @@ -2,6 +2,7 @@ package com.walletconnect.android.impl import com.walletconnect.android.internal.common.storage.KeyStore import com.walletconnect.android.impl.data.repository.BouncyCastleKeyManagementRepository +import com.walletconnect.android.internal.common.model.SymmetricKey import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic @@ -44,7 +45,7 @@ internal class BouncyCastleCryptoRepositoryTest { val symKey = sut.generateAndStoreSymmetricKey(topicVO) assert(symKey.keyAsHex.length == 64) - val secretKey = sut.getSymmetricKey(topicVO) + val secretKey = sut.getKey(topicVO.value, SymmetricKey::class) as SymmetricKey assertEquals(symKey.keyAsHex, secretKey.keyAsHex) assert(secretKey.keyAsHex.length == 64) } @@ -52,7 +53,7 @@ internal class BouncyCastleCryptoRepositoryTest { @Test fun `Generate a shared key and return a Topic object`() { val peerKey = PublicKey("ff7a7d5767c362b0a17ad92299ebdb7831dcbd9a56959c01368c7404543b3342") - val topic = sut.generateTopicFromKeyAgreementAndSafeSymKey(publicKey, peerKey) + val topic = sut.generateTopicFromKeyAgreement(publicKey, peerKey) assert(topic.value.isNotBlank()) assert(topic.value.length == 64) @@ -99,12 +100,12 @@ internal class BouncyCastleCryptoRepositoryTest { fun `Generated SymmetricKey gets removed when using a TopicVO as the tag for removeKeys`() { val symKey = sut.generateAndStoreSymmetricKey(topicVO) - val secretKey = sut.getSymmetricKey(topicVO) + val secretKey = sut.getKey(topicVO.value, SymmetricKey::class) as SymmetricKey assertEquals(symKey.keyAsHex, secretKey.keyAsHex) sut.removeKeys(topicVO.value) - val secretKeyAfterRemoval = sut.getSymmetricKey(topicVO) + val secretKeyAfterRemoval = sut.getKey(topicVO.value, SymmetricKey::class) as SymmetricKey assertEquals(String.Empty, secretKeyAfterRemoval.keyAsHex) } } \ No newline at end of file diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt index b58ec5fd21..7160318672 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt @@ -3,10 +3,11 @@ package com.walletconnect.android.impl import com.walletconnect.android.impl.common.MissingParticipantsException import com.walletconnect.android.impl.common.MissingReceiverPublicKeyException import com.walletconnect.android.internal.common.model.Participants -import com.walletconnect.android.internal.common.model.SymmetricKey + import com.walletconnect.android.internal.common.model.EnvelopeType import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.impl.data.codec.ChaChaPolyCodec +import com.walletconnect.android.internal.common.model.SymmetricKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic import com.walletconnect.utils.Empty @@ -37,7 +38,7 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 0 with the same key`() { - every { keyManagementRepository.getSymmetricKey(topic) } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey listOf("secretMessage", "", "👍🏻").forEach { message -> val encryptedMessage = codec.encrypt(topic, message, EnvelopeType.ZERO) @@ -47,10 +48,10 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 1 with the same key`() { - every { keyManagementRepository.getSymmetricKey(topic) } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(self, peer) } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(peer, self) } returns symmetricKey - every { keyManagementRepository.getSelfParticipant(topic) } returns peer + every { keyManagementRepository.getKey(topic.value, PublicKey::class) as PublicKey } returns peer listOf("secretMessage", "", "👍🏻").forEach { message -> val encryptedMessage = codec.encrypt(topic, message, EnvelopeType.ONE, participants) @@ -68,9 +69,9 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 decryption envelope type 1 throws missing receiver key`() { assertThrows(MissingReceiverPublicKeyException::class.java) { - every { keyManagementRepository.getSymmetricKey(topic) } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(self, peer) } returns symmetricKey - every { keyManagementRepository.getSelfParticipant(topic) } returns null + every { keyManagementRepository.getKey(topic.value, PublicKey::class) as PublicKey } throws Exception("Missing key") val encryptedMessage = codec.encrypt(topic, MESSAGE, EnvelopeType.ONE, participants) codec.decrypt(topic, encryptedMessage) @@ -80,7 +81,7 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption envelope type 0 with key that is not 64 Byte long throws`() { listOf(String.Empty, KEY_32_BYTES, KEY_128_BYTES).forEach { encryptionKeyAsHex -> - every { keyManagementRepository.getSymmetricKey(topic) } returns SymmetricKey(encryptionKeyAsHex) + every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns SymmetricKey(encryptionKeyAsHex) assertThrows(Exception::class.java) { codec.encrypt(topic, MESSAGE, EnvelopeType.ZERO) } @@ -90,10 +91,10 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 0 with the different key throws`() { assertThrows(Exception::class.java) { - every { keyManagementRepository.getSymmetricKey(topic) } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey val encryptedMessage = codec.encrypt(topic, MESSAGE, EnvelopeType.ZERO) - every { keyManagementRepository.getSymmetricKey(topic) } returns invalidKey + every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns invalidKey codec.decrypt(topic, encryptedMessage) } } diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt index b102cba8b8..5319619945 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt @@ -5,32 +5,20 @@ import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic +import kotlin.reflect.KClass interface KeyManagementRepository { - fun generateAndStoreSymmetricKey(topic: Topic): SymmetricKey - fun generateSymmetricKey(): SymmetricKey - fun setSymmetricKey(topic: Topic, symmetricKey: SymmetricKey) - fun getSymmetricKey(topic: Topic): SymmetricKey - - fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey - fun generateTopicFromKeyAgreementAndSafeSymKey(self: PublicKey, peer: PublicKey): Topic - fun getTopicFromKey(key: Key): Topic - fun getKeyAgreement(topic: Topic): Pair - fun generateKeyPair(): PublicKey - + fun setKey(key: Key, tag: String) + fun getKey(tag: String, clazz: KClass): Key fun removeKeys(tag: String) - fun setSelfParticipant(key: PublicKey, topic: Topic) - fun getSelfParticipant(topic: Topic): PublicKey? - - //Added with Chat SDK - fun generateInviteSelfKeyPair(): Pair - fun getInviteSelfPublicKey(): PublicKey - fun setInviteSelfPublicKey(publicKey: PublicKey, topic: Topic) + fun generateKeyPair(): PublicKey + fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) + fun getKeyAgreement(topic: Topic): Pair - fun getHash(string: String): String + fun generateAndStoreSymmetricKey(topic: Topic): SymmetricKey + fun generateSymmetricKeyFromKeyAgreement(self: PublicKey, peer: PublicKey): SymmetricKey - // fun getInvitePublicKey(topic: Topic): PublicKey - fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) + fun getTopicFromKey(key: Key): Topic fun generateTopicFromKeyAgreement(self: PublicKey, peer: PublicKey): Topic } \ No newline at end of file diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt index 055d7e7a2e..8c07ab3b86 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/storage/KeyStore.kt @@ -3,7 +3,6 @@ package com.walletconnect.android.internal.common.storage import com.walletconnect.foundation.common.model.Key -import com.walletconnect.foundation.common.model.PublicKey interface KeyStore { fun getKey(tag: String): String? diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt index 8396c6b86a..9dac3c0847 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/pairing/PairingClient.kt @@ -151,7 +151,11 @@ internal object PairingClient : PairingInterface { override fun pair(pair: Core.Params.Pair, onError: (Core.Model.Error) -> Unit) { scope.launch(Dispatchers.IO) { awaitConnection({ - val walletConnectUri: WalletConnectUri = Validator.validateWCUri(pair.uri) ?: return@awaitConnection onError(Core.Model.Error(MalformedWalletConnectUri(MALFORMED_PAIRING_URI_MESSAGE))) + val walletConnectUri: WalletConnectUri = Validator.validateWCUri(pair.uri) ?: return@awaitConnection onError( + Core.Model.Error( + MalformedWalletConnectUri(MALFORMED_PAIRING_URI_MESSAGE) + ) + ) if (isPairingValid(walletConnectUri.topic.value)) { return@awaitConnection onError(Core.Model.Error(PairWithExistingPairingIsNotAllowed(PAIRING_NOW_ALLOWED_MESSAGE))) @@ -175,7 +179,7 @@ internal object PairingClient : PairingInterface { val activePairing = Pairing(walletConnectUri, registeredMethods) val symmetricKey = walletConnectUri.symKey - crypto.setSymmetricKey(walletConnectUri.topic, symmetricKey) + crypto.setKey(symmetricKey, walletConnectUri.topic.value) try { pairingRepository.insertPairing(activePairing) diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt index d4a66ae004..dba7c22e66 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt @@ -12,6 +12,7 @@ import com.walletconnect.android.internal.common.scope import com.walletconnect.android.impl.utils.DAY_IN_SECONDS import com.walletconnect.android.impl.utils.Logger import com.walletconnect.android.impl.utils.MONTH_IN_SECONDS +import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT import com.walletconnect.android.internal.common.model.* import com.walletconnect.android.pairing.PairingInterface import com.walletconnect.android.pairing.toClient @@ -85,7 +86,9 @@ internal class AuthEngine( val irnParams = IrnParams(Tags.AUTH_REQUEST, Ttl(DAY_IN_SECONDS), true) val pairingTopic = pairing.topic - crypto.setSelfParticipant(responsePublicKey, responseTopic) +// crypto.setSelfParticipant(responsePublicKey, responseTopic) + crypto.setKey(responsePublicKey, "${SELF_PARTICIPANT_CONTEXT}${responseTopic}") + jsonRpcInteractor.publishJsonRpcRequest(pairingTopic, irnParams, authRequest, onSuccess = { Logger.log("Auth request sent successfully on topic:${pairingTopic}, awaiting response on topic:$responseTopic") // todo: Remove after Alpha @@ -130,7 +133,7 @@ internal class AuthEngine( val senderPublicKey: PublicKey = crypto.generateKeyPair() val symmetricKey: SymmetricKey = crypto.generateSymmetricKeyFromKeyAgreement(senderPublicKey, receiverPublicKey) val responseTopic: Topic = crypto.getTopicFromKey(receiverPublicKey) - crypto.setSymmetricKey(responseTopic, symmetricKey) + crypto.setKey(symmetricKey, responseTopic.value) val irnParams = IrnParams(Tags.AUTH_REQUEST_RESPONSE, Ttl(DAY_IN_SECONDS), false) jsonRpcInteractor.publishJsonRpcResponse( diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 82b4a8b4c4..3519af0e3a 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -4,6 +4,8 @@ package com.walletconnect.chat.engine.domain import com.walletconnect.android.impl.utils.DAY_IN_SECONDS import com.walletconnect.android.impl.utils.Logger +import com.walletconnect.android.impl.utils.SELF_INVITE_PUBLIC_KEY_CONTEXT +import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT import com.walletconnect.android.internal.common.JsonRpcResponse import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.internal.common.exception.GenericException @@ -74,34 +76,33 @@ internal class ChatEngine( onFailure: (Throwable) -> Unit, private: Boolean, ) { - fun _onSuccess(publicKey: PublicKey) { - val topic = Topic(keyManagementRepository.getHash(publicKey.keyAsHex)) - keyManagementRepository.setInviteSelfPublicKey(publicKey, topic) - keyManagementRepository.setSelfParticipant(publicKey, topic) + fun onSuccess(publicKey: PublicKey) { + val topic = keyManagementRepository.getTopicFromKey(publicKey) + keyManagementRepository.setKey(publicKey, SELF_INVITE_PUBLIC_KEY_CONTEXT) + keyManagementRepository.setKey(publicKey, "$SELF_PARTICIPANT_CONTEXT${topic.value}") trySubscribeToInviteTopic() onSuccess(publicKey.keyAsHex) } - val (publicKey, _) = keyManagementRepository.generateInviteSelfKeyPair() - + val publicKey = keyManagementRepository.generateKeyPair() if (!private) { scope.launch { supervisorScope { registerAccountUseCase(AccountIdWithPublicKey(accountId, publicKey)).fold( - onSuccess = { _onSuccess(publicKey) }, + onSuccess = { onSuccess(publicKey) }, onFailure = { error -> onFailure(error) } ) } } } else { - _onSuccess(publicKey) + onSuccess(publicKey) } } private fun trySubscribeToInviteTopic() { try { - val publicKey = keyManagementRepository.getInviteSelfPublicKey() - val topic = Topic(keyManagementRepository.getHash(publicKey.keyAsHex)) + val publicKey = keyManagementRepository.getKey(SELF_INVITE_PUBLIC_KEY_CONTEXT, PublicKey::class) as PublicKey + val topic = keyManagementRepository.getTopicFromKey(publicKey) jsonRpcInteractor.subscribe(topic) Logger.log("Listening for invite on: $topic, pubKey X:$publicKey") } catch (error: Exception) { @@ -118,15 +119,15 @@ internal class ChatEngine( val receiverPublicKey = PublicKey(publicKeyString) // KeyPair X val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(senderPublicKey, receiverPublicKey) // SymKey I - val inviteTopic = Topic(keyManagementRepository.getHash(publicKeyString)) // Topic I + val inviteTopic = keyManagementRepository.getTopicFromKey(receiverPublicKey) // Topic I keyManagementRepository.setKeyAgreement(inviteTopic, senderPublicKey, receiverPublicKey) val participants = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = receiverPublicKey) val inviteParams = ChatParams.InviteParams(invite.message, invite.accountId.value, senderPublicKey.keyAsHex, invite.signature) val payload = ChatRpc.ChatInvite(id = generateId(), params = inviteParams) - val acceptTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) + val acceptTopic = keyManagementRepository.getTopicFromKey(symmetricKey) - keyManagementRepository.setSymmetricKey(acceptTopic, symmetricKey) + keyManagementRepository.setKey(symmetricKey, acceptTopic.value) jsonRpcInteractor.subscribe(acceptTopic) val irnParams = IrnParams(Tags.CHAT_INVITE, Ttl(DAY_IN_SECONDS), true) @@ -153,8 +154,8 @@ internal class ChatEngine( val pubKeyZ = PublicKey(acceptParams.publicKey) // PubKey Z val (selfPubKey, _) = keyManagementRepository.getKeyAgreement(wcResponse.topic) val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(selfPubKey, pubKeyZ) // SymKey T - val threadTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) - keyManagementRepository.setSymmetricKey(threadTopic, symmetricKey) + val threadTopic = keyManagementRepository.getTopicFromKey(symmetricKey) + keyManagementRepository.setKey(symmetricKey, threadTopic.value) jsonRpcInteractor.subscribe(threadTopic) scope.launch { _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) @@ -184,10 +185,10 @@ internal class ChatEngine( val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) // PubKey Y inviteRequestMap.remove(inviteId) - val invitePublicKey = keyManagementRepository.getInviteSelfPublicKey() // PubKey X + val invitePublicKey = keyManagementRepository.getKey(SELF_INVITE_PUBLIC_KEY_CONTEXT, PublicKey::class) as PublicKey // PubKey X val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) // SymKey I - val acceptTopic = Topic(keyManagementRepository.getHash(symmetricKey.keyAsHex)) // Topic T - keyManagementRepository.setSymmetricKey(acceptTopic, symmetricKey) + val acceptTopic = keyManagementRepository.getTopicFromKey(symmetricKey) // Topic T + keyManagementRepository.setKey(symmetricKey, acceptTopic.value) val publicKey = keyManagementRepository.generateKeyPair() // KeyPair Z @@ -198,8 +199,8 @@ internal class ChatEngine( jsonRpcInteractor.respondWithParams(request.copy(topic = acceptTopic), acceptanceParams, irnParams, EnvelopeType.ZERO) val threadSymmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(publicKey, senderPublicKey) // SymKey T - val threadTopic = Topic(keyManagementRepository.getHash(threadSymmetricKey.keyAsHex)) // Topic T - keyManagementRepository.setSymmetricKey(threadTopic, threadSymmetricKey) + val threadTopic = keyManagementRepository.getTopicFromKey(threadSymmetricKey) // Topic T + keyManagementRepository.setKey(threadSymmetricKey, threadTopic.value) jsonRpcInteractor.subscribe(threadTopic) scope.launch { diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index 12407c92ef..65e29644fe 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -722,7 +722,7 @@ onFailure(error) val selfPublicKey = PublicKey(params.proposer.publicKey) val approveParams = response.result as SignParamsVO.ApprovalParams val responderPublicKey = PublicKey(approveParams.responderPublicKey) - val sessionTopic = crypto.generateTopicFromKeyAgreementAndSafeSymKey(selfPublicKey, responderPublicKey) + val sessionTopic = crypto.generateTopicFromKeyAgreement(selfPublicKey, responderPublicKey) jsonRpcInteractor.subscribe(sessionTopic) } is JsonRpcResponse.JsonRpcError -> { From d1becf53c57cdb398fe346d7c30aa76234ea06d8 Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 25 Oct 2022 15:09:42 +0200 Subject: [PATCH 09/30] Fix for auth envelope type 1 key --- .../kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt index dba7c22e66..88b183cbf2 100644 --- a/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt +++ b/auth/sdk/src/main/kotlin/com/walletconnect/auth/engine/domain/AuthEngine.kt @@ -85,9 +85,7 @@ internal class AuthEngine( val authRequest: AuthRpc.AuthRequest = AuthRpc.AuthRequest(generateId(), params = authParams) val irnParams = IrnParams(Tags.AUTH_REQUEST, Ttl(DAY_IN_SECONDS), true) val pairingTopic = pairing.topic - -// crypto.setSelfParticipant(responsePublicKey, responseTopic) - crypto.setKey(responsePublicKey, "${SELF_PARTICIPANT_CONTEXT}${responseTopic}") + crypto.setKey(responsePublicKey, "${SELF_PARTICIPANT_CONTEXT}${responseTopic.value}") jsonRpcInteractor.publishJsonRpcRequest(pairingTopic, irnParams, authRequest, onSuccess = { From 487fee02c9e354cbd0a5db7e13becc1f9df802df Mon Sep 17 00:00:00 2001 From: kubel Date: Tue, 25 Oct 2022 15:17:59 +0200 Subject: [PATCH 10/30] Address PR comments --- auth/sdk/build.gradle.kts | 2 +- .../walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt | 0 .../auth/json_rpc/domain/JsonRpcInteractor.kt | 0 chat/sdk/build.gradle.kts | 2 +- .../kotlin/com/walletconnect/chat/di/StorageModule.kt | 8 ++++---- .../walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt | 0 6 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt delete mode 100644 auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/domain/JsonRpcInteractor.kt delete mode 100644 sign/sdk/src/main/kotlin/com/walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt diff --git a/auth/sdk/build.gradle.kts b/auth/sdk/build.gradle.kts index 25e3ead3d0..425b9a7d97 100644 --- a/auth/sdk/build.gradle.kts +++ b/auth/sdk/build.gradle.kts @@ -20,7 +20,7 @@ android { minSdk = MIN_SDK targetSdk = TARGET_SDK - buildConfigField(type = "String", name = "sdkVersion", value = "\"1.0.0-alpha01\"") + buildConfigField(type = "String", name = "sdkVersion", value = "\"${requireNotNull(extra.get(KEY_PUBLISH_VERSION))}\"") buildConfigField("String", "PROJECT_ID", "\"${System.getenv("WC_CLOUD_PROJECT_ID") ?: ""}\"") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/data/JsonRpcSerializer.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/domain/JsonRpcInteractor.kt b/auth/sdk/src/main/kotlin/com/walletconnect/auth/json_rpc/domain/JsonRpcInteractor.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/chat/sdk/build.gradle.kts b/chat/sdk/build.gradle.kts index 3ec344b38b..cf24835604 100644 --- a/chat/sdk/build.gradle.kts +++ b/chat/sdk/build.gradle.kts @@ -39,7 +39,7 @@ android { } sqldelight { - database("Database") { + database("ChatDatabase") { packageName = "com.walletconnect.chat" schemaOutputDirectory = file("src/debug/sqldelight/databases") verifyMigrations = false diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt index 91ce9ab447..6a83335ff0 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/StorageModule.kt @@ -2,21 +2,21 @@ package com.walletconnect.chat.di import com.walletconnect.android.impl.di.coreStorageModule import com.walletconnect.android.impl.di.sdkBaseStorageModule -import com.walletconnect.chat.Database +import com.walletconnect.chat.ChatDatabase import com.walletconnect.chat.storage.ChatStorageRepository import org.koin.dsl.module @JvmSynthetic internal fun storageModule(storageSuffix: String) = module { - includes(coreStorageModule(), sdkBaseStorageModule(Database.Schema, storageSuffix)) + includes(coreStorageModule(), sdkBaseStorageModule(ChatDatabase.Schema, storageSuffix)) single { - Database(get()) + ChatDatabase(get()) } single { - get().contactsQueries + get().contactsQueries } single { diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/json_rpc/data/JsonRpcSerializer.kt deleted file mode 100644 index e69de29bb2..0000000000 From 1d434c9965746d2fefa414f4cda334f50fd1d550 Mon Sep 17 00:00:00 2001 From: kubel Date: Wed, 26 Oct 2022 08:47:53 +0200 Subject: [PATCH 11/30] Test fixing --- .../android/impl/data/codec/ChaChaPolyCodec.kt | 9 +++++---- .../BouncyCastleKeyManagementRepository.kt | 13 +++++-------- .../impl/BouncyCastleCryptoRepositoryTest.kt | 7 ++++--- .../android/impl/ChaChaPolyCodecTest.kt | 18 ++++++++++-------- .../common/crypto/KeyManagementRepository.kt | 5 ++--- .../com/walletconnect/android/utils/KeyType.kt | 5 +++++ 6 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt index 747707ed97..407dbbdd00 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt @@ -11,6 +11,7 @@ import com.walletconnect.android.internal.common.model.EnvelopeType import com.walletconnect.android.impl.crypto.Codec import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT import com.walletconnect.android.internal.common.crypto.KeyManagementRepository +import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic import com.walletconnect.util.bytesToHex @@ -57,7 +58,7 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen EnvelopeType.ZERO.id -> decryptType0(topic, encryptedPayloadBytes) EnvelopeType.ONE.id -> decryptType1( encryptedPayloadBytes, - keyManagementRepository.getKey("$SELF_PARTICIPANT_CONTEXT${topic.value}", PublicKey::class) as PublicKey + keyManagementRepository.getKey("$SELF_PARTICIPANT_CONTEXT${topic.value}", KeyType.PublicKey) as PublicKey ) else -> throw UnknownEnvelopeTypeException("Decrypt; Unknown envelope type: $envelopeType") } @@ -74,7 +75,7 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen byteBuffer.get(nonce) byteBuffer.get(encryptedMessageBytes) - val symmetricKey = keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey + val symmetricKey = keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey val decryptedTextBytes = decryptPayload(symmetricKey, nonce, encryptedMessageBytes) return String(decryptedTextBytes, Charsets.UTF_8) @@ -103,8 +104,8 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen } private fun encryptEnvelopeType0(topic: Topic, nonceBytes: ByteArray, input: ByteArray, envelopeType: EnvelopeType): String { - val symmetricKey = keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey - val cipherBytes = encryptPayload(symmetricKey, nonceBytes, input) + val symmetricKey = keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) + val cipherBytes = encryptPayload(symmetricKey as SymmetricKey, nonceBytes, input) val payloadSize = cipherBytes.size + NONCE_SIZE + ENVELOPE_TYPE_SIZE //tp + iv + sb diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt index bfc4cd972e..e2e229d4aa 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt @@ -5,6 +5,7 @@ package com.walletconnect.android.impl.data.repository import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.internal.common.model.SymmetricKey import com.walletconnect.android.internal.common.storage.KeyStore +import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey @@ -18,21 +19,17 @@ import org.bouncycastle.math.ec.rfc7748.X25519 import java.security.MessageDigest import java.security.SecureRandom import javax.crypto.KeyGenerator -import kotlin.reflect.KClass internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStore) : KeyManagementRepository { - override fun setKey(key: Key, tag: String) { keyChain.setKey(tag, key) } - override fun getKey(tag: String, clazz: KClass): Key { + override fun getKey(tag: String, type: KeyType): Key { val key = keyChain.getKey(tag) ?: throw Exception("No Key for tag: $tag") - return when (clazz) { - PublicKey::class -> PublicKey(key) - SymmetricKey::class -> SymmetricKey(key) - PrivateKey::class -> PrivateKey(key) - else -> throw Exception("Wrong key type: $clazz") + return when (type) { + KeyType.SymmetricKey -> PublicKey(key) + KeyType.PublicKey -> SymmetricKey(key) } } diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt index 42a2a7de03..7deac7edd5 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt @@ -3,6 +3,7 @@ package com.walletconnect.android.impl import com.walletconnect.android.internal.common.storage.KeyStore import com.walletconnect.android.impl.data.repository.BouncyCastleKeyManagementRepository import com.walletconnect.android.internal.common.model.SymmetricKey +import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic @@ -45,7 +46,7 @@ internal class BouncyCastleCryptoRepositoryTest { val symKey = sut.generateAndStoreSymmetricKey(topicVO) assert(symKey.keyAsHex.length == 64) - val secretKey = sut.getKey(topicVO.value, SymmetricKey::class) as SymmetricKey + val secretKey = sut.getKey(topicVO.value, KeyType.SymmetricKey) as SymmetricKey assertEquals(symKey.keyAsHex, secretKey.keyAsHex) assert(secretKey.keyAsHex.length == 64) } @@ -100,12 +101,12 @@ internal class BouncyCastleCryptoRepositoryTest { fun `Generated SymmetricKey gets removed when using a TopicVO as the tag for removeKeys`() { val symKey = sut.generateAndStoreSymmetricKey(topicVO) - val secretKey = sut.getKey(topicVO.value, SymmetricKey::class) as SymmetricKey + val secretKey = sut.getKey(topicVO.value, KeyType.SymmetricKey) as SymmetricKey assertEquals(symKey.keyAsHex, secretKey.keyAsHex) sut.removeKeys(topicVO.value) - val secretKeyAfterRemoval = sut.getKey(topicVO.value, SymmetricKey::class) as SymmetricKey + val secretKeyAfterRemoval = sut.getKey(topicVO.value, KeyType.SymmetricKey) as SymmetricKey assertEquals(String.Empty, secretKeyAfterRemoval.keyAsHex) } } \ No newline at end of file diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt index 7160318672..18edc8efb2 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt @@ -8,6 +8,8 @@ import com.walletconnect.android.internal.common.model.EnvelopeType import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.impl.data.codec.ChaChaPolyCodec import com.walletconnect.android.internal.common.model.SymmetricKey +import com.walletconnect.android.utils.KeyType +import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic import com.walletconnect.utils.Empty @@ -38,7 +40,7 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 0 with the same key`() { - every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) } returns symmetricKey listOf("secretMessage", "", "👍🏻").forEach { message -> val encryptedMessage = codec.encrypt(topic, message, EnvelopeType.ZERO) @@ -48,10 +50,10 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 1 with the same key`() { - every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(self, peer) } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(peer, self) } returns symmetricKey - every { keyManagementRepository.getKey(topic.value, PublicKey::class) as PublicKey } returns peer + every { keyManagementRepository.getKey(topic.value, KeyType.PublicKey) as PublicKey } returns peer listOf("secretMessage", "", "👍🏻").forEach { message -> val encryptedMessage = codec.encrypt(topic, message, EnvelopeType.ONE, participants) @@ -69,9 +71,9 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 decryption envelope type 1 throws missing receiver key`() { assertThrows(MissingReceiverPublicKeyException::class.java) { - every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(self, peer) } returns symmetricKey - every { keyManagementRepository.getKey(topic.value, PublicKey::class) as PublicKey } throws Exception("Missing key") + every { keyManagementRepository.getKey(topic.value, KeyType.PublicKey) as PublicKey } throws Exception("Missing key") val encryptedMessage = codec.encrypt(topic, MESSAGE, EnvelopeType.ONE, participants) codec.decrypt(topic, encryptedMessage) @@ -81,7 +83,7 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption envelope type 0 with key that is not 64 Byte long throws`() { listOf(String.Empty, KEY_32_BYTES, KEY_128_BYTES).forEach { encryptionKeyAsHex -> - every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns SymmetricKey(encryptionKeyAsHex) + every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns SymmetricKey(encryptionKeyAsHex) assertThrows(Exception::class.java) { codec.encrypt(topic, MESSAGE, EnvelopeType.ZERO) } @@ -91,10 +93,10 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 0 with the different key throws`() { assertThrows(Exception::class.java) { - every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns symmetricKey + every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns symmetricKey val encryptedMessage = codec.encrypt(topic, MESSAGE, EnvelopeType.ZERO) - every { keyManagementRepository.getKey(topic.value, SymmetricKey::class) as SymmetricKey } returns invalidKey + every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns invalidKey codec.decrypt(topic, encryptedMessage) } } diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt index 5319619945..880bb18414 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt @@ -1,15 +1,14 @@ package com.walletconnect.android.internal.common.crypto import com.walletconnect.android.internal.common.model.SymmetricKey +import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.Key -import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic -import kotlin.reflect.KClass interface KeyManagementRepository { fun setKey(key: Key, tag: String) - fun getKey(tag: String, clazz: KClass): Key + fun getKey(tag: String, type: KeyType): Key fun removeKeys(tag: String) fun generateKeyPair(): PublicKey diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt new file mode 100644 index 0000000000..5ca98b9421 --- /dev/null +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt @@ -0,0 +1,5 @@ +package com.walletconnect.android.utils + +enum class KeyType { + SymmetricKey, PublicKey +} \ No newline at end of file From 0795446dc58e83c02e6258376cf71da71c80070d Mon Sep 17 00:00:00 2001 From: kubel Date: Wed, 26 Oct 2022 09:03:55 +0200 Subject: [PATCH 12/30] Address PR comments --- .../walletconnect/android/internal/common/model/Tags.kt | 2 ++ chat/sdk/build.gradle.kts | 2 +- .../kotlin/com/walletconnect/chat/client/ChatProtocol.kt | 6 +++--- .../com/walletconnect/chat/client/mapper/ClientMapper.kt | 8 ++++---- .../com/walletconnect/chat/engine/domain/ChatEngine.kt | 2 +- sign/sdk/build.gradle.kts | 2 +- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/Tags.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/Tags.kt index 91a4da4fcf..abc8e2ba32 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/Tags.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/model/Tags.kt @@ -47,4 +47,6 @@ enum class Tags(val id: Int) { AUTH_REQUEST(3000), AUTH_REQUEST_RESPONSE(3001) + + //todo: Discuss: Should Tags be in specific SDKs? } \ No newline at end of file diff --git a/chat/sdk/build.gradle.kts b/chat/sdk/build.gradle.kts index cf24835604..00464d1719 100644 --- a/chat/sdk/build.gradle.kts +++ b/chat/sdk/build.gradle.kts @@ -42,7 +42,7 @@ sqldelight { database("ChatDatabase") { packageName = "com.walletconnect.chat" schemaOutputDirectory = file("src/debug/sqldelight/databases") - verifyMigrations = false + verifyMigrations = true } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index e288ffccb2..fa5857791d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -6,7 +6,7 @@ import com.walletconnect.android.internal.common.scope import com.walletconnect.android.internal.common.wcKoinApp import com.walletconnect.chat.client.mapper.toClient import com.walletconnect.chat.client.mapper.toEngineDO -import com.walletconnect.chat.client.mapper.toVO +import com.walletconnect.chat.client.mapper.toCommon import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.di.* @@ -84,7 +84,7 @@ internal class ChatProtocol : ChatInterface { override fun invite(invite: Chat.Params.Invite, onError: (Chat.Model.Error) -> Unit) { checkEngineInitialization() - chatEngine.invite(invite.account.toVO(), invite.toEngineDO()) { error -> onError(Chat.Model.Error(error)) } + chatEngine.invite(invite.account.toCommon(), invite.toEngineDO()) { error -> onError(Chat.Model.Error(error)) } } @Throws(IllegalStateException::class) @@ -125,7 +125,7 @@ internal class ChatProtocol : ChatInterface { @Throws(IllegalStateException::class) override fun addContact(addContact: Chat.Params.AddContact, onError: (Chat.Model.Error) -> Unit) { checkEngineInitialization() - chatEngine.addContact(AccountIdWithPublicKey(addContact.account.toVO(), PublicKey(addContact.publicKey))) { error -> + chatEngine.addContact(AccountIdWithPublicKey(addContact.account.toCommon(), PublicKey(addContact.publicKey))) { error -> onError(Chat.Model.Error(error)) } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt index 365508ff22..de3dda4468 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt @@ -10,21 +10,21 @@ import com.walletconnect.chat.engine.model.EngineDO //TODO: Figure out what to do with models separation @JvmSynthetic internal fun Chat.Params.Invite.toEngineDO(): EngineDO.Invite { - return EngineDO.Invite(invite.account.toVO(), invite.message, invite.signature) + return EngineDO.Invite(invite.account.toCommon(), invite.message, invite.signature) } @JvmSynthetic internal fun Chat.Params.Message.toEngineDO(): EngineDO.SendMessage { - return EngineDO.SendMessage(author.toVO(), message, media?.toVO()) + return EngineDO.SendMessage(author.toCommon(), message, media?.toCommon()) } @JvmSynthetic -private fun Chat.Model.Media.toVO(): Media { +private fun Chat.Model.Media.toCommon(): Media { return Media(type, data) } @JvmSynthetic -internal fun Chat.Model.AccountId.toVO(): AccountId { +internal fun Chat.Model.AccountId.toCommon(): AccountId { return AccountId(value) } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index d452ac84cd..c152e36c10 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -32,7 +32,7 @@ internal class ChatEngine( private val resolveAccountUseCase: ResolveAccountUseCase, private val keyManagementRepository: KeyManagementRepository, private val jsonRpcInteractor: JsonRpcInteractorInterface, - private val chatStorage: ChatStorageRepository, + private val chatStorage: ChatStorageRepository ) { private val _events: MutableSharedFlow = MutableSharedFlow() val events: SharedFlow = _events.asSharedFlow() diff --git a/sign/sdk/build.gradle.kts b/sign/sdk/build.gradle.kts index 24fcebed32..a862c19def 100644 --- a/sign/sdk/build.gradle.kts +++ b/sign/sdk/build.gradle.kts @@ -57,7 +57,7 @@ sqldelight { database("SignDatabase") { packageName = "com.walletconnect.sign" schemaOutputDirectory = file("src/debug/sqldelight/databases") - verifyMigrations = false + verifyMigrations = true } } From 2e6b6013fe4e5048106971fc58d55f5922ef30ae Mon Sep 17 00:00:00 2001 From: kubel Date: Wed, 26 Oct 2022 09:37:09 +0200 Subject: [PATCH 13/30] Test fixing --- .../android/impl/common/CryptoException.kt | 2 +- .../impl/data/codec/ChaChaPolyCodec.kt | 15 +++++----- .../BouncyCastleKeyManagementRepository.kt | 16 +++++----- .../impl/BouncyCastleCryptoRepositoryTest.kt | 6 ++-- .../android/impl/ChaChaPolyCodecTest.kt | 30 +++++++++---------- .../common/crypto/KeyManagementRepository.kt | 4 +-- .../chat/engine/domain/ChatEngine.kt | 4 +-- 7 files changed, 38 insertions(+), 39 deletions(-) diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/common/CryptoException.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/common/CryptoException.kt index c6777d9925..d53fd9c0b6 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/common/CryptoException.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/common/CryptoException.kt @@ -4,4 +4,4 @@ import com.walletconnect.android.internal.common.exception.WalletConnectExceptio class UnknownEnvelopeTypeException(override val message: String?) : WalletConnectException(message) class MissingParticipantsException(override val message: String?) : WalletConnectException(message) -class MissingReceiverPublicKeyException(override val message: String?) : WalletConnectException(message) \ No newline at end of file +class MissingKeyException(override val message: String?) : WalletConnectException(message) \ No newline at end of file diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt index 407dbbdd00..621418a47b 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/codec/ChaChaPolyCodec.kt @@ -3,7 +3,7 @@ package com.walletconnect.android.impl.data.codec import com.walletconnect.android.impl.common.MissingParticipantsException -import com.walletconnect.android.impl.common.MissingReceiverPublicKeyException +import com.walletconnect.android.impl.common.MissingKeyException import com.walletconnect.android.impl.common.UnknownEnvelopeTypeException import com.walletconnect.android.internal.common.model.Participants import com.walletconnect.android.internal.common.model.SymmetricKey @@ -11,7 +11,6 @@ import com.walletconnect.android.internal.common.model.EnvelopeType import com.walletconnect.android.impl.crypto.Codec import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT import com.walletconnect.android.internal.common.crypto.KeyManagementRepository -import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic import com.walletconnect.util.bytesToHex @@ -49,7 +48,7 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen @Throws( UnknownEnvelopeTypeException::class, - MissingReceiverPublicKeyException::class + MissingKeyException::class ) override fun decrypt(topic: Topic, cipherText: String): String { val encryptedPayloadBytes = Base64.decode(cipherText) @@ -58,7 +57,7 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen EnvelopeType.ZERO.id -> decryptType0(topic, encryptedPayloadBytes) EnvelopeType.ONE.id -> decryptType1( encryptedPayloadBytes, - keyManagementRepository.getKey("$SELF_PARTICIPANT_CONTEXT${topic.value}", KeyType.PublicKey) as PublicKey + keyManagementRepository.getPublicKey("$SELF_PARTICIPANT_CONTEXT${topic.value}") ) else -> throw UnknownEnvelopeTypeException("Decrypt; Unknown envelope type: $envelopeType") } @@ -75,14 +74,14 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen byteBuffer.get(nonce) byteBuffer.get(encryptedMessageBytes) - val symmetricKey = keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey + val symmetricKey = keyManagementRepository.getSymmetricKey(topic.value) val decryptedTextBytes = decryptPayload(symmetricKey, nonce, encryptedMessageBytes) return String(decryptedTextBytes, Charsets.UTF_8) } private fun decryptType1(encryptedPayloadBytes: ByteArray, receiverPublicKey: PublicKey?): String { - if (receiverPublicKey == null) throw MissingReceiverPublicKeyException("Missing receiver public key") + if (receiverPublicKey == null) throw MissingKeyException("Missing receiver public key") val envelopeType = ByteArray(ENVELOPE_TYPE_SIZE) val nonce = ByteArray(NONCE_SIZE) @@ -104,8 +103,8 @@ internal class ChaChaPolyCodec(private val keyManagementRepository: KeyManagemen } private fun encryptEnvelopeType0(topic: Topic, nonceBytes: ByteArray, input: ByteArray, envelopeType: EnvelopeType): String { - val symmetricKey = keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) - val cipherBytes = encryptPayload(symmetricKey as SymmetricKey, nonceBytes, input) + val symmetricKey = keyManagementRepository.getSymmetricKey(topic.value) + val cipherBytes = encryptPayload(symmetricKey, nonceBytes, input) val payloadSize = cipherBytes.size + NONCE_SIZE + ENVELOPE_TYPE_SIZE //tp + iv + sb diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt index e2e229d4aa..b7337840fd 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/data/repository/BouncyCastleKeyManagementRepository.kt @@ -2,10 +2,10 @@ package com.walletconnect.android.impl.data.repository +import com.walletconnect.android.impl.common.MissingKeyException import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.internal.common.model.SymmetricKey import com.walletconnect.android.internal.common.storage.KeyStore -import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey @@ -25,12 +25,14 @@ internal class BouncyCastleKeyManagementRepository(private val keyChain: KeyStor keyChain.setKey(tag, key) } - override fun getKey(tag: String, type: KeyType): Key { - val key = keyChain.getKey(tag) ?: throw Exception("No Key for tag: $tag") - return when (type) { - KeyType.SymmetricKey -> PublicKey(key) - KeyType.PublicKey -> SymmetricKey(key) - } + override fun getPublicKey(tag: String): PublicKey { + val key = keyChain.getKey(tag) ?: throw MissingKeyException("No SymmetricKey for tag: $tag") + return PublicKey(key) + } + + override fun getSymmetricKey(tag: String): SymmetricKey { + val key = keyChain.getKey(tag) ?: throw MissingKeyException("No PublicKey for tag: $tag") + return SymmetricKey(key) } override fun getKeyAgreement(topic: Topic): Pair { diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt index 7deac7edd5..c1156efec7 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt @@ -46,7 +46,7 @@ internal class BouncyCastleCryptoRepositoryTest { val symKey = sut.generateAndStoreSymmetricKey(topicVO) assert(symKey.keyAsHex.length == 64) - val secretKey = sut.getKey(topicVO.value, KeyType.SymmetricKey) as SymmetricKey + val secretKey = sut.getSymmetricKey(topicVO.value) assertEquals(symKey.keyAsHex, secretKey.keyAsHex) assert(secretKey.keyAsHex.length == 64) } @@ -101,12 +101,12 @@ internal class BouncyCastleCryptoRepositoryTest { fun `Generated SymmetricKey gets removed when using a TopicVO as the tag for removeKeys`() { val symKey = sut.generateAndStoreSymmetricKey(topicVO) - val secretKey = sut.getKey(topicVO.value, KeyType.SymmetricKey) as SymmetricKey + val secretKey = sut.getSymmetricKey(topicVO.value) assertEquals(symKey.keyAsHex, secretKey.keyAsHex) sut.removeKeys(topicVO.value) - val secretKeyAfterRemoval = sut.getKey(topicVO.value, KeyType.SymmetricKey) as SymmetricKey + val secretKeyAfterRemoval = sut.getSymmetricKey(topicVO.value) assertEquals(String.Empty, secretKeyAfterRemoval.keyAsHex) } } \ No newline at end of file diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt index 18edc8efb2..4a47ddab37 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/ChaChaPolyCodecTest.kt @@ -1,15 +1,13 @@ package com.walletconnect.android.impl import com.walletconnect.android.impl.common.MissingParticipantsException -import com.walletconnect.android.impl.common.MissingReceiverPublicKeyException -import com.walletconnect.android.internal.common.model.Participants - -import com.walletconnect.android.internal.common.model.EnvelopeType -import com.walletconnect.android.internal.common.crypto.KeyManagementRepository +import com.walletconnect.android.impl.common.MissingKeyException import com.walletconnect.android.impl.data.codec.ChaChaPolyCodec +import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT +import com.walletconnect.android.internal.common.crypto.KeyManagementRepository +import com.walletconnect.android.internal.common.model.EnvelopeType +import com.walletconnect.android.internal.common.model.Participants import com.walletconnect.android.internal.common.model.SymmetricKey -import com.walletconnect.android.utils.KeyType -import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic import com.walletconnect.utils.Empty @@ -40,7 +38,7 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 0 with the same key`() { - every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) } returns symmetricKey + every { keyManagementRepository.getSymmetricKey(topic.value) } returns symmetricKey listOf("secretMessage", "", "👍🏻").forEach { message -> val encryptedMessage = codec.encrypt(topic, message, EnvelopeType.ZERO) @@ -50,10 +48,10 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 1 with the same key`() { - every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) } returns symmetricKey + every { keyManagementRepository.getSymmetricKey(topic.value) } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(self, peer) } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(peer, self) } returns symmetricKey - every { keyManagementRepository.getKey(topic.value, KeyType.PublicKey) as PublicKey } returns peer + every { keyManagementRepository.getPublicKey("$SELF_PARTICIPANT_CONTEXT${topic.value}") } returns peer listOf("secretMessage", "", "👍🏻").forEach { message -> val encryptedMessage = codec.encrypt(topic, message, EnvelopeType.ONE, participants) @@ -70,10 +68,10 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 decryption envelope type 1 throws missing receiver key`() { - assertThrows(MissingReceiverPublicKeyException::class.java) { - every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns symmetricKey + assertThrows(MissingKeyException::class.java) { + every { keyManagementRepository.getSymmetricKey(topic.value) } returns symmetricKey every { keyManagementRepository.generateSymmetricKeyFromKeyAgreement(self, peer) } returns symmetricKey - every { keyManagementRepository.getKey(topic.value, KeyType.PublicKey) as PublicKey } throws Exception("Missing key") + every { keyManagementRepository.getPublicKey("$SELF_PARTICIPANT_CONTEXT${topic.value}") } throws MissingKeyException("Missing key") val encryptedMessage = codec.encrypt(topic, MESSAGE, EnvelopeType.ONE, participants) codec.decrypt(topic, encryptedMessage) @@ -83,7 +81,7 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption envelope type 0 with key that is not 64 Byte long throws`() { listOf(String.Empty, KEY_32_BYTES, KEY_128_BYTES).forEach { encryptionKeyAsHex -> - every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns SymmetricKey(encryptionKeyAsHex) + every { keyManagementRepository.getSymmetricKey(topic.value) } returns SymmetricKey(encryptionKeyAsHex) assertThrows(Exception::class.java) { codec.encrypt(topic, MESSAGE, EnvelopeType.ZERO) } @@ -93,10 +91,10 @@ class ChaChaPolyCodecTest { @Test fun `ChaCha20-Poly1305 encryption and decryption envelope type 0 with the different key throws`() { assertThrows(Exception::class.java) { - every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns symmetricKey + every { keyManagementRepository.getSymmetricKey(topic.value) } returns symmetricKey val encryptedMessage = codec.encrypt(topic, MESSAGE, EnvelopeType.ZERO) - every { keyManagementRepository.getKey(topic.value, KeyType.SymmetricKey) as SymmetricKey } returns invalidKey + every { keyManagementRepository.getSymmetricKey(topic.value) } returns invalidKey codec.decrypt(topic, encryptedMessage) } } diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt index 880bb18414..f77f8a0601 100644 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt +++ b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/internal/common/crypto/KeyManagementRepository.kt @@ -1,15 +1,15 @@ package com.walletconnect.android.internal.common.crypto import com.walletconnect.android.internal.common.model.SymmetricKey -import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.Key import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic interface KeyManagementRepository { fun setKey(key: Key, tag: String) - fun getKey(tag: String, type: KeyType): Key fun removeKeys(tag: String) + fun getPublicKey(tag: String): PublicKey + fun getSymmetricKey(tag: String): SymmetricKey fun generateKeyPair(): PublicKey fun setKeyAgreement(topic: Topic, self: PublicKey, peer: PublicKey) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 3519af0e3a..209867f16d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -101,7 +101,7 @@ internal class ChatEngine( private fun trySubscribeToInviteTopic() { try { - val publicKey = keyManagementRepository.getKey(SELF_INVITE_PUBLIC_KEY_CONTEXT, PublicKey::class) as PublicKey + val publicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT) val topic = keyManagementRepository.getTopicFromKey(publicKey) jsonRpcInteractor.subscribe(topic) Logger.log("Listening for invite on: $topic, pubKey X:$publicKey") @@ -185,7 +185,7 @@ internal class ChatEngine( val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) // PubKey Y inviteRequestMap.remove(inviteId) - val invitePublicKey = keyManagementRepository.getKey(SELF_INVITE_PUBLIC_KEY_CONTEXT, PublicKey::class) as PublicKey // PubKey X + val invitePublicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT)// PubKey X val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) // SymKey I val acceptTopic = keyManagementRepository.getTopicFromKey(symmetricKey) // Topic T keyManagementRepository.setKey(symmetricKey, acceptTopic.value) From d34e186dd2314880f0aed5de5f3e0f38fe317e99 Mon Sep 17 00:00:00 2001 From: kubel Date: Wed, 26 Oct 2022 09:37:44 +0200 Subject: [PATCH 14/30] Delete unused file --- .../android/impl/BouncyCastleCryptoRepositoryTest.kt | 2 -- .../main/kotlin/com/walletconnect/android/utils/KeyType.kt | 5 ----- 2 files changed, 7 deletions(-) delete mode 100644 androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt diff --git a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt index c1156efec7..76fdc9a80c 100644 --- a/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt +++ b/androidCore/impl/src/test/kotlin/com/walletconnect/android/impl/BouncyCastleCryptoRepositoryTest.kt @@ -2,8 +2,6 @@ package com.walletconnect.android.impl import com.walletconnect.android.internal.common.storage.KeyStore import com.walletconnect.android.impl.data.repository.BouncyCastleKeyManagementRepository -import com.walletconnect.android.internal.common.model.SymmetricKey -import com.walletconnect.android.utils.KeyType import com.walletconnect.foundation.common.model.PrivateKey import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic diff --git a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt b/androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt deleted file mode 100644 index 5ca98b9421..0000000000 --- a/androidCore/sdk/src/main/kotlin/com/walletconnect/android/utils/KeyType.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.walletconnect.android.utils - -enum class KeyType { - SymmetricKey, PublicKey -} \ No newline at end of file From d864f7e70f419b861970355fa8f4961ab35a3964 Mon Sep 17 00:00:00 2001 From: kubel Date: Wed, 26 Oct 2022 10:20:55 +0200 Subject: [PATCH 15/30] Fix removing session from database --- .../chatsample/ui/shared/ChatSharedViewModel.kt | 4 ++-- .../com/walletconnect/sign/engine/domain/SignEngine.kt | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index e2be0d87f7..5b6f0e91e3 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -175,8 +175,8 @@ class ChatSharedViewModel : ViewModel() { private const val isPrimary = true - val SELF_ACCOUNT = if (isPrimary) KOTLIN_ACCOUNT_ID else TEST_ACCOUNT_ID // SWIFT_ACCOUNT_ID - val SELF_ENS = if (isPrimary) KOTLIN_ENS else TEST_ENS // SWIFT_ENS + val SELF_ACCOUNT = SWIFT_ACCOUNT_ID //if (isPrimary) KOTLIN_ACCOUNT_ID else TEST_ACCOUNT_ID // + val SELF_ENS = SWIFT_ENS //if (isPrimary) KOTLIN_ENS else TEST_ENS // val ensToAccountIdMap = mapOf( SWIFT_ENS to SWIFT_ACCOUNT_ID, diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index 65e29644fe..4f65e8236b 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -551,11 +551,12 @@ onFailure(error) jsonRpcInteractor.unsubscribe(request.topic, onSuccess = { crypto.removeKeys(request.topic.value) - sessionStorageRepository.deleteSession(request.topic) - scope.launch { _engineEvent.emit(params.toEngineDO(request.topic)) } }, onFailure = { error -> Logger.error(error) }) + + sessionStorageRepository.deleteSession(request.topic) + scope.launch { _engineEvent.emit(params.toEngineDO(request.topic)) } } // listened by WalletDelegate From 718783674353d7c88abd6fd76fb0cd8fdff11c0b Mon Sep 17 00:00:00 2001 From: kubel Date: Wed, 26 Oct 2022 17:08:07 +0200 Subject: [PATCH 16/30] Add reject invitation --- .../impl/json_rpc/domain/JsonRpcInteractor.kt | 2 + .../ui/accounts/uri/ScannerFragment.kt | 2 +- .../chatsample/domain/ChatDelegate.kt | 14 +- .../chatsample/ui/host/ChatSampleActivity.kt | 21 ++- .../chatsample/ui/invites/InvitesAdapter.kt | 23 ++- .../chatsample/ui/invites/InvitesFragment.kt | 12 +- .../ui/messages/MessagesFragment.kt | 11 +- .../chatsample/ui/shared/ChatSharedEvents.kt | 4 +- .../ui/shared/ChatSharedViewModel.kt | 177 ++++++++++++------ .../thread_invite/ThreadInviteBottomSheet.kt | 6 +- .../com/walletconnect/chat/client/Chat.kt | 4 +- .../chat/client/ChatInterface.kt | 3 +- .../walletconnect/chat/client/ChatProtocol.kt | 7 +- .../chat/client/mapper/ClientMapper.kt | 10 + .../chat/common/exceptions/PeerError.kt | 11 ++ .../chat/common/json_rpc/ChatRpc.kt | 2 +- .../walletconnect/chat/di/JsonRpcModule.kt | 2 +- .../chat/engine/domain/ChatEngine.kt | 42 +++-- .../chat/engine/model/EngineDO.kt | 6 +- .../json_rpc/{model => }/JsonRpcMethod.kt | 2 +- .../chat/storage/ChatStorageRepository.kt | 4 +- 21 files changed, 255 insertions(+), 110 deletions(-) create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/PeerError.kt rename chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/{model => }/JsonRpcMethod.kt (88%) diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt index 034b84bd4f..b8075ca589 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt @@ -193,6 +193,8 @@ internal class JsonRpcInteractor( val topic = Topic(relayRequest.subscriptionTopic) val message = chaChaPolyCodec.decrypt(topic, relayRequest.message) + Logger.error("Peer message: $message") + Pair(message, topic) }.collect { (decryptedMessage, topic) -> manageSubscriptions(decryptedMessage, topic) } } diff --git a/auth/responder/src/main/kotlin/com/walletconnect/responder/ui/accounts/uri/ScannerFragment.kt b/auth/responder/src/main/kotlin/com/walletconnect/responder/ui/accounts/uri/ScannerFragment.kt index 6f0504f39a..c1c87a0048 100644 --- a/auth/responder/src/main/kotlin/com/walletconnect/responder/ui/accounts/uri/ScannerFragment.kt +++ b/auth/responder/src/main/kotlin/com/walletconnect/responder/ui/accounts/uri/ScannerFragment.kt @@ -129,7 +129,7 @@ class ScannerFragment : Fragment(R.layout.fragment_scanner) { } .addOnFailureListener { Log.e(tag(this@ScannerFragment), it.message.toString()) - Toast.makeText(requireContext(), "Failed to capture QR Code", Toast.LENGTH_SHORT).show() + clearAnalyzer() findNavController().popBackStack() diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt index b96feceb6b..355e2cedb5 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt @@ -1,5 +1,6 @@ package com.walletconnect.chatsample.domain +import android.util.Log import com.walletconnect.chat.client.Chat import com.walletconnect.chat.client.ChatClient import kotlinx.coroutines.* @@ -24,23 +25,32 @@ object ChatDelegate : ChatClient.ChatDelegate { override fun onJoined(onJoined: Chat.Model.Events.OnJoined) { scope.launch { + Log.e("kobe", "onJoined DELEGATE") _wcEventModels.emit(onJoined) clearCache() } } + override fun onReject(onReject: Chat.Model.Events.OnReject) { + scope.launch { + _wcEventModels.emit(onReject) + clearCache() + } + } + override fun onMessage(onMessage: Chat.Model.Events.OnMessage) { scope.launch { _wcEventModels.emit(onMessage) clearCache() - }} + } + } override fun onLeft(onLeft: Chat.Model.Events.OnLeft) { TODO("Not yet implemented") } @OptIn(ExperimentalCoroutinesApi::class) - private fun clearCache() { + fun clearCache() { _wcEventModels.resetReplayCache() } } \ No newline at end of file diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt index 6352837837..409ebca9fc 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt @@ -1,15 +1,21 @@ package com.walletconnect.chatsample.ui.host import android.os.Bundle +import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContentProviderCompat.requireContext +import androidx.core.os.bundleOf import androidx.lifecycle.Lifecycle import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope +import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.fragment.findNavController import com.google.android.material.snackbar.Snackbar import com.walletconnect.chatsample.R import com.walletconnect.chatsample.databinding.ActivityChatSampleBinding +import com.walletconnect.chatsample.ui.messages.MessagesFragment import com.walletconnect.chatsample.ui.shared.ChatSharedEvents import com.walletconnect.chatsample.ui.shared.ChatSharedViewModel import com.walletconnect.chatsample.utils.viewBinding @@ -32,15 +38,24 @@ class ChatSampleActivity : AppCompatActivity() { .onEach { event -> when (event) { is ChatSharedEvents.OnInvite -> showOnInviteSnackbar(event) + is ChatSharedEvents.OnJoined -> { + binding.root.findNavController().navigate( + R.id.action_threadsFragment_to_messagesFragment, + bundleOf(MessagesFragment.peerNameKey to viewModel.whoWasInvitedContact) + ) + } + is ChatSharedEvents.OnReject -> Toast.makeText(this, "Invitation rejected", Toast.LENGTH_SHORT).show() else -> Unit } }.launchIn(lifecycleScope) } - private fun showOnInviteSnackbar(event: ChatSharedEvents.OnInvite) = Snackbar.make(binding.root, - "\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31 You got an invite from: ${ChatSharedViewModel.accountIdToEnsMap[event.invite.account.value]}", - Snackbar.LENGTH_LONG).show() + private fun showOnInviteSnackbar(event: ChatSharedEvents.OnInvite) = Snackbar.make( + binding.root, + "\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31 You got an invite from: ${ChatSharedViewModel.accountIdToEnsMap[event.invite.account.value] ?: event.invite.account.value}", + Snackbar.LENGTH_LONG + ).show() override fun onSupportNavigateUp(): Boolean { return navHostFragment.navController.navigateUp() || super.onSupportNavigateUp() diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesAdapter.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesAdapter.kt index 2400e924b8..7264903be5 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesAdapter.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesAdapter.kt @@ -12,7 +12,10 @@ import com.walletconnect.chatsample.databinding.ListItemInviteBinding import com.walletconnect.chatsample.ui.messages.MessagesFragment import com.walletconnect.chatsample.ui.shared.ChatUI -class InvitesAdapter(private val onClick: (ChatUI) -> Unit) : ListAdapter(DIFF_UTIL) { +class InvitesAdapter( + private val onAccept: (ChatUI) -> Unit, + private val onReject: (id: Long?) -> Unit +) : ListAdapter(DIFF_UTIL) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(ListItemInviteBinding.inflate(LayoutInflater.from(parent.context), parent, false)) @@ -20,15 +23,17 @@ class InvitesAdapter(private val onClick: (ChatUI) -> Unit) : ListAdapter + viewModel.acceptInvitation(chatUI) +// findNavController().navigateUp() + }, onReject = { id -> viewModel.rejectInvitation(id) }) + } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.rvChatRequests.adapter = invitesAdapter - viewModel.listOfInvitesStateFlow .flowWithLifecycle(viewLifecycleOwner.lifecycle) - .onEach { invitesAdapter.submitList(it.toList()) } + .onEach { chatUIList -> invitesAdapter.submitList(chatUIList) } .launchIn(viewLifecycleOwner.lifecycleScope) } } \ No newline at end of file diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt index 9fb7abdf6e..17d958c422 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt @@ -51,12 +51,17 @@ class MessagesFragment : Fragment(R.layout.fragment_messages) { } binding.tvThreadTime.text = "TODAY ${SimpleDateFormat("h:mm a").format(Date())}" - binding.ivPeerIcon.setImageDrawable(resources.getDrawable(ChatSharedViewModel.ensToIconMap[peerName]!!, null)) + binding.ivPeerIcon.setImageDrawable( + resources.getDrawable( + ChatSharedViewModel.ensToIconMap[peerName] ?: R.drawable.ic_chat_icon_3, + null + ) + ) viewModel.listOfMessagesStateFlow .flowWithLifecycle(viewLifecycleOwner.lifecycle) .onEach { messages -> - messagesAdapter.submitList( messages + messagesAdapter.submitList(messages .filter { it.peerName == peerName } .map { it.toMessageBubbleUI() }) } @@ -64,7 +69,7 @@ class MessagesFragment : Fragment(R.layout.fragment_messages) { } private fun MessageUI.toMessageBubbleUI(): MessageBubbleUI = when (peerName) { - author -> MessageBubbleUI.Peer(ChatSharedViewModel.ensToIconMap[peerName]!!, text) + author -> MessageBubbleUI.Peer(ChatSharedViewModel.ensToIconMap[peerName] ?: R.drawable.ic_chat_icon_3, text) else -> MessageBubbleUI.Self(text) } diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedEvents.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedEvents.kt index 7a760e45d3..267b1ca76c 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedEvents.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedEvents.kt @@ -7,6 +7,7 @@ sealed class ChatSharedEvents { data class OnInvite(val id: Long, val invite: Chat.Model.Invite) : ChatSharedEvents() data class OnJoined(val topic: String) : ChatSharedEvents() + data class OnReject(val topic: String) : ChatSharedEvents() data class OnMessage(val topic: String, val message: Chat.Model.Message) : ChatSharedEvents() data class OnLeft(val topic: String) : ChatSharedEvents() } @@ -14,4 +15,5 @@ sealed class ChatSharedEvents { fun Chat.Model.Events.OnInvite.toChatSharedEvents() = ChatSharedEvents.OnInvite(id, invite) fun Chat.Model.Events.OnJoined.toChatSharedEvents() = ChatSharedEvents.OnJoined(topic) fun Chat.Model.Events.OnMessage.toChatSharedEvents() = ChatSharedEvents.OnMessage(topic, message) -fun Chat.Model.Events.OnLeft.toChatSharedEvents() = ChatSharedEvents.OnLeft(topic) \ No newline at end of file +fun Chat.Model.Events.OnLeft.toChatSharedEvents() = ChatSharedEvents.OnLeft(topic) +fun Chat.Model.Events.OnReject.toChatSharedEvents() = ChatSharedEvents.OnReject(topic) \ No newline at end of file diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index 5b6f0e91e3..6575b024d9 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -14,7 +14,7 @@ import kotlinx.coroutines.runBlocking class ChatSharedViewModel : ViewModel() { var currentInvite: Chat.Model.Invite? = null - var whoWasInvitedENS: String? = null + var whoWasInvitedContact: String? = null val userNameToTopicMap: MutableMap = mutableMapOf() val listOfInvites: MutableList = mutableListOf() @@ -38,7 +38,7 @@ class ChatSharedViewModel : ViewModel() { is Chat.Model.Events.OnInvite -> walletEvent.toChatSharedEvents().also { onInvite(it) } is Chat.Model.Events.OnJoined -> walletEvent.toChatSharedEvents().also { onJoined(it) } is Chat.Model.Events.OnMessage -> walletEvent.toChatSharedEvents().also { onMessage(it) } - is Chat.Model.Events.OnLeft -> walletEvent.toChatSharedEvents() + is Chat.Model.Events.OnReject -> walletEvent.toChatSharedEvents().also { onReject(it) } else -> ChatSharedEvents.NoAction } }.shareIn(viewModelScope, SharingStarted.WhileSubscribed()) @@ -47,15 +47,14 @@ class ChatSharedViewModel : ViewModel() { private fun onInvite(event: ChatSharedEvents.OnInvite) { Log.d(tag(this), "Invited: ${event.invite.message}") - accountIdToEnsMap[event.invite.account.value]?.let { ens -> - currentInvite = event.invite + val contact = accountIdToEnsMap[event.invite.account.value] ?: event.invite.account.value + currentInvite = event.invite - listOfInvites.add(ChatUI(ensToIconMap[ens]!!, ens, event.invite.message, event.id)) - _listOfInvitesStateFlow.update { listOfInvites.toList() } + listOfInvites.add(ChatUI(ensToIconMap[contact] ?: R.drawable.ic_chat_icon_3, contact, event.invite.message, event.id)) + _listOfInvitesStateFlow.update { listOfInvites.toList() } - listOfMessages.add(MessageUI(ens, event.invite.message, System.currentTimeMillis(), ens)) - _listOfMessagesStateFlow.value = listOfMessages.toList() - } ?: Log.e(tag(this), "Unable to find accountId: ${event.invite.account.value}") + listOfMessages.add(MessageUI(contact, event.invite.message, System.currentTimeMillis(), contact)) + _listOfMessagesStateFlow.value = listOfMessages.toList() } private fun onJoined(event: ChatSharedEvents.OnJoined) { @@ -66,16 +65,25 @@ class ChatSharedViewModel : ViewModel() { if (ens != SELF_ENS) { Log.e(tag(this), "ens != SELF_ENS") - listOfThreads.add(ChatUI(ensToIconMap[ens]!!, ens, currentInvite!!.message, null)) + listOfThreads.add(ChatUI(ensToIconMap[ens] ?: R.drawable.ic_chat_icon_3, ens, currentInvite!!.message, null)) _listOfThreadsStateFlow.value = listOfThreads.toList() userNameToTopicMap.put(ens, event.topic) } else { Log.e(tag(this), "ens == SELF_ENS") - listOfThreads.add(ChatUI(ensToIconMap[whoWasInvitedENS]!!, whoWasInvitedENS!!, currentInvite!!.message, null)) + + listOfThreads.add( + ChatUI( + ensToIconMap[whoWasInvitedContact] ?: R.drawable.ic_chat_icon_3, + whoWasInvitedContact!!, + currentInvite!!.message, + null + ) + ) _listOfThreadsStateFlow.value = listOfThreads.toList() - userNameToTopicMap.put(whoWasInvitedENS!!, event.topic) + userNameToTopicMap.put(whoWasInvitedContact!!, event.topic) } + } } else Log.e(tag(this), "Unable to find currentInvite: $event") } @@ -93,55 +101,59 @@ class ChatSharedViewModel : ViewModel() { } } - fun acceptRequest(chatUI: ChatUI) { - chatUI.id?.let { id -> - ChatClient.accept(Chat.Params.Accept(id)) { error -> - Log.e(tag(this), error.throwable.stackTraceToString()) - } + private fun onReject(event: ChatSharedEvents.OnReject) { - listOfInvites.removeIf { it.username == chatUI.username } - _listOfInvitesStateFlow.value = listOfInvites.toList() - } ?: Log.e(tag(this), "Unable to find id: $chatUI") - } + Log.e("Kobe", "ON REJECT VM") - fun register(listener: Chat.Listeners.Register) { - ChatClient.register(Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)), listener) } - fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { - - ensToAccountIdMap[contact]?.let { accountId -> + fun acceptInvitation(chatUI: ChatUI) { + chatUI.id?.let { id -> + ChatClient.accept(Chat.Params.Accept(id), onSuccess = { threadTopic -> + + if (currentInvite != null) { + accountIdToEnsMap[currentInvite?.account?.value]?.let { ens -> + if (ens != SELF_ENS) { + Log.e(tag(this), "ens != SELF_ENS") + + listOfThreads.add(ChatUI(ensToIconMap[ens] ?: R.drawable.ic_chat_icon_3, ens, currentInvite!!.message, null)) + _listOfThreadsStateFlow.value = listOfThreads.toList() + + userNameToTopicMap.put(ens, threadTopic) + } else { + Log.e(tag(this), "ens == SELF_ENS") + + listOfThreads.add( + ChatUI( + ensToIconMap[whoWasInvitedContact] ?: R.drawable.ic_chat_icon_3, + whoWasInvitedContact!!, + currentInvite!!.message, + null + ) + ) + _listOfThreadsStateFlow.value = listOfThreads.toList() + userNameToTopicMap.put(whoWasInvitedContact!!, threadTopic) + } - ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(accountId)), object : Chat.Listeners.Resolve { - override fun onError(error: Chat.Model.Error) { - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) } - } + } else Log.e(tag(this), "Unable to find currentInvite") - override fun onSuccess(publicKey: String) { - ChatClient.addContact(Chat.Params.AddContact(Chat.Model.AccountId(accountId), publicKey)) { error -> - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) - } - } + }, { error -> Log.e(tag(this), error.throwable.stackTraceToString()) }) - val inviteModel = Chat.Model.Invite(Chat.Model.AccountId(SELF_ACCOUNT), openingMessage) - Chat.Params.Invite(Chat.Model.AccountId(accountId), inviteModel).also { invite -> - ChatClient.invite(invite) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } - } - runBlocking(Dispatchers.Main) { - currentInvite = inviteModel - whoWasInvitedENS = contact - Log.e(tag(this), "invite: $currentInvite") - listOfMessages.add(MessageUI(contact, inviteModel.message, System.currentTimeMillis(), SELF_ENS)) - _listOfMessagesStateFlow.value = listOfMessages.toList() - afterInviteSent() - } - } - }) + listOfInvites.removeIf { it.username == chatUI.username } + _listOfInvitesStateFlow.value = listOfInvites.toList() + + } ?: Log.e(tag(this), "Unable to find id on accpet invitation: $chatUI") + } + + fun rejectInvitation(id: Long?) { + id?.let { + val reject = Chat.Params.Reject(it) + ChatClient.reject(reject) { error -> Log.e(tag(this), "Unable to find reject invitation: $error") } - } ?: Log.e(tag(this), "Unable to find contact: $contact") + listOfInvites.removeIf { invite -> invite.id == id } + _listOfInvitesStateFlow.value = listOfInvites.toList() + } ?: Log.e(tag(this), "Unable to find id on reject invitation: $id") } fun sendMessage(message: String, peername: String) { @@ -151,15 +163,61 @@ class ChatSharedViewModel : ViewModel() { listOfMessages.add(MessageUI(ens, message, System.currentTimeMillis(), SELF_ENS)) _listOfMessagesStateFlow.value = listOfMessages.toList() - if (ensToAccountIdMap[ens] != null) { - ChatClient.message(Chat.Params.Message(topic, Chat.Model.AccountId(ensToAccountIdMap[SELF_ENS]!!), message)) { error -> +// if (ensToAccountIdMap[ens] != null) { + + //todo: fix state + ChatClient.message( + Chat.Params.Message( + topic, + Chat.Model.AccountId(ensToAccountIdMap[SELF_ENS] ?: "eip155:4:0xab16a96d359ec26a11e2c2b3d8f8b89488888888"), + message + ) + ) { error -> + runBlocking(Dispatchers.Main) { + Log.e(tag(this), error.throwable.stackTraceToString()) + } + } +// } else { +// Log.e(tag(this), "Unable to find contact: $ens") +// } + } + + fun register(listener: Chat.Listeners.Register) { + ChatClient.register(Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)), listener) + } + + fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { + + val accountId = ensToAccountIdMap[contact] ?: contact + + ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(accountId)), object : Chat.Listeners.Resolve { + override fun onError(error: Chat.Model.Error) { runBlocking(Dispatchers.Main) { Log.e(tag(this), error.throwable.stackTraceToString()) } } - } else { - Log.e(tag(this), "Unable to find contact: $ens") - } + + override fun onSuccess(publicKey: String) { + ChatClient.addContact(Chat.Params.AddContact(Chat.Model.AccountId(accountId), publicKey)) { error -> + runBlocking(Dispatchers.Main) { + Log.e(tag(this), error.throwable.stackTraceToString()) + } + } + + val inviteModel = Chat.Model.Invite(Chat.Model.AccountId(SELF_ACCOUNT), openingMessage) + Chat.Params.Invite(Chat.Model.AccountId(accountId), inviteModel).also { invite -> + ChatClient.invite(invite) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } + } + runBlocking(Dispatchers.Main) { + currentInvite = inviteModel + whoWasInvitedContact = contact + Log.e(tag(this), "invite: $currentInvite") + listOfMessages.add(MessageUI(contact, inviteModel.message, System.currentTimeMillis(), SELF_ENS)) + _listOfMessagesStateFlow.value = listOfMessages.toList() + afterInviteSent() + } + } + }) } companion object { @@ -175,8 +233,9 @@ class ChatSharedViewModel : ViewModel() { private const val isPrimary = true - val SELF_ACCOUNT = SWIFT_ACCOUNT_ID //if (isPrimary) KOTLIN_ACCOUNT_ID else TEST_ACCOUNT_ID // - val SELF_ENS = SWIFT_ENS //if (isPrimary) KOTLIN_ENS else TEST_ENS // + val SELF_ACCOUNT = + if (isPrimary) KOTLIN_ACCOUNT_ID else TEST_ACCOUNT_ID //SWIFT_ACCOUNT_ID + val SELF_ENS = if (isPrimary) KOTLIN_ENS else TEST_ENS //SWIFT_ENS val ensToAccountIdMap = mapOf( SWIFT_ENS to SWIFT_ACCOUNT_ID, diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/thread_invite/ThreadInviteBottomSheet.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/thread_invite/ThreadInviteBottomSheet.kt index 6e05f695d0..f45644171b 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/thread_invite/ThreadInviteBottomSheet.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/thread_invite/ThreadInviteBottomSheet.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.core.os.bundleOf import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController @@ -29,9 +30,8 @@ class ThreadInviteBottomSheet : BottomSheetDialogFragment() { with(binding) { btnInvite.setOnClickListener { viewModel.invite(etContact.text.toString(), OPENING_MESSAGE) { - findNavController().navigate( - R.id.action_threadInviteDialogFragment_to_messagesFragment, - bundleOf(MessagesFragment.peerNameKey to etContact.text.toString())) + Toast.makeText(requireContext(), "Invitation send successfully, wait for response!", Toast.LENGTH_SHORT).show() + findNavController().navigateUp() } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt index 4abbbc7ae9..0d214c43c7 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt @@ -53,6 +53,8 @@ object Chat { data class OnJoined(val topic: String) : Events() + data class OnReject(val topic: String) : Events() + data class OnMessage(val topic: String, val message: Message) : Events() data class OnLeft(val topic: String) : Events() @@ -70,7 +72,7 @@ object Chat { data class Accept(val inviteId: Long) : Params() - data class Reject(val inviteId: String) : Params() + data class Reject(val inviteId: Long) : Params() data class Message(val topic: String, val author: Model.AccountId, val message: String, val media: Model.Media? = null) : Params() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt index e313252940..97597f4298 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt @@ -5,6 +5,7 @@ interface ChatInterface { interface ChatDelegate { fun onInvite(onInvite: Chat.Model.Events.OnInvite) fun onJoined(onJoined: Chat.Model.Events.OnJoined) + fun onReject(onReject: Chat.Model.Events.OnReject) fun onMessage(onMessage: Chat.Model.Events.OnMessage) fun onLeft(onLeft: Chat.Model.Events.OnLeft) } @@ -15,7 +16,7 @@ interface ChatInterface { fun register(register: Chat.Params.Register, listener: Chat.Listeners.Register) fun resolve(resolve: Chat.Params.Resolve, listener: Chat.Listeners.Resolve) fun invite(invite: Chat.Params.Invite, onError: (Chat.Model.Error) -> Unit) - fun accept(accept: Chat.Params.Accept, onError: (Chat.Model.Error) -> Unit) + fun accept(accept: Chat.Params.Accept, onSuccess: (String) -> Unit, onError: (Chat.Model.Error) -> Unit) fun reject(reject: Chat.Params.Reject, onError: (Chat.Model.Error) -> Unit) fun message(message: Chat.Params.Message, onError: (Chat.Model.Error) -> Unit) fun ping(ping: Chat.Params.Ping, onError: (Chat.Model.Error) -> Unit) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index e288ffccb2..81ed2bdac2 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -50,8 +50,9 @@ internal class ChatProtocol : ChatInterface { when (event) { is EngineDO.Events.OnInvite -> delegate.onInvite(event.toClient()) is EngineDO.Events.OnJoined -> delegate.onJoined(event.toClient()) + is EngineDO.Events.OnReject -> delegate.onReject(event.toClient()) is EngineDO.Events.OnMessage -> delegate.onMessage(event.toClient()) - is EngineDO.Events.OnLeft -> Unit + is EngineDO.Events.OnLeft -> delegate.onLeft(event.toClient()) } } } @@ -88,10 +89,10 @@ internal class ChatProtocol : ChatInterface { } @Throws(IllegalStateException::class) - override fun accept(accept: Chat.Params.Accept, onError: (Chat.Model.Error) -> Unit) { + override fun accept(accept: Chat.Params.Accept, onSuccess: (String) -> Unit, onError: (Chat.Model.Error) -> Unit) { checkEngineInitialization() - chatEngine.accept(accept.inviteId) { error -> onError(Chat.Model.Error(error)) } + chatEngine.accept(accept.inviteId, { threadTopic -> onSuccess(threadTopic) }, { error -> onError(Chat.Model.Error(error)) }) } @Throws(IllegalStateException::class) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt index 365508ff22..d369047946 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt @@ -58,6 +58,16 @@ internal fun EngineDO.Events.OnMessage.toClient(): Chat.Model.Events.OnMessage { return Chat.Model.Events.OnMessage(topic, message.toClient()) } +@JvmSynthetic +internal fun EngineDO.Events.OnLeft.toClient(): Chat.Model.Events.OnLeft { + return Chat.Model.Events.OnLeft(topic) +} + +@JvmSynthetic +internal fun EngineDO.Events.OnReject.toClient(): Chat.Model.Events.OnReject { + return Chat.Model.Events.OnReject(topic) +} + @JvmSynthetic internal fun EngineDO.Message.toClient(): Chat.Model.Message { return Chat.Model.Message(message, authorAccountId.toClient(), timestamp, media?.toClient()) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/PeerError.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/PeerError.kt new file mode 100644 index 0000000000..e557b98bd0 --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/PeerError.kt @@ -0,0 +1,11 @@ +package com.walletconnect.chat.common.exceptions + +import com.walletconnect.android.internal.common.model.Error + +sealed class PeerError : Error { + + //TODO: Discuss error with team on later stage of development + data class UserRejectedInvitation(override val message: String) : PeerError() { + override val code: Int = 4001 + } +} diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt index ed5b21b8aa..b6bffc9d8b 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/json_rpc/ChatRpc.kt @@ -3,7 +3,7 @@ package com.walletconnect.chat.common.json_rpc import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import com.walletconnect.android.internal.common.model.JsonRpcClientSync -import com.walletconnect.chat.json_rpc.model.JsonRpcMethod +import com.walletconnect.chat.json_rpc.JsonRpcMethod internal sealed class ChatRpc : JsonRpcClientSync { abstract override val id: Long diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt index 83f96ac8ba..c901766c5d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/di/JsonRpcModule.kt @@ -3,7 +3,7 @@ package com.walletconnect.chat.di import com.walletconnect.chat.common.json_rpc.ChatRpc -import com.walletconnect.chat.json_rpc.model.JsonRpcMethod +import com.walletconnect.chat.json_rpc.JsonRpcMethod import com.walletconnect.utils.addDeserializerEntry import com.walletconnect.utils.addSerializerEntry import org.koin.dsl.module diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 209867f16d..666e107842 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -11,6 +11,7 @@ import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.internal.common.exception.GenericException import com.walletconnect.android.internal.common.model.* import com.walletconnect.android.internal.common.scope +import com.walletconnect.chat.common.exceptions.PeerError import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.common.json_rpc.ChatRpc @@ -60,6 +61,9 @@ internal class ChatEngine( } internal fun resolveAccount(accountId: AccountId, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { + //todo: add CAIP25 compatibility check + + //tod check if there's pubKey under given accountId if yes use it if not register scope.launch { supervisorScope { resolveAccountUseCase(accountId).fold( @@ -147,6 +151,9 @@ internal class ChatEngine( when (val response = wcResponse.response) { is JsonRpcResponse.JsonRpcError -> { Logger.log("Chat invite was rejected") + scope.launch { + _events.emit(EngineDO.Events.OnReject(wcResponse.topic.value)) + } } is JsonRpcResponse.JsonRpcResult -> { Logger.log("Chat invite was accepted") @@ -155,6 +162,7 @@ internal class ChatEngine( val (selfPubKey, _) = keyManagementRepository.getKeyAgreement(wcResponse.topic) val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(selfPubKey, pubKeyZ) // SymKey T val threadTopic = keyManagementRepository.getTopicFromKey(symmetricKey) + //todo: add thread to storage keyManagementRepository.setKey(symmetricKey, threadTopic.value) jsonRpcInteractor.subscribe(threadTopic) scope.launch { @@ -180,7 +188,7 @@ internal class ChatEngine( } - internal fun accept(inviteId: Long, onFailure: (Throwable) -> Unit) = try { + internal fun accept(inviteId: Long, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) = try { val request = inviteRequestMap[inviteId] ?: throw GenericException("No request for inviteId") val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) // PubKey Y inviteRequestMap.remove(inviteId) @@ -192,7 +200,6 @@ internal class ChatEngine( val publicKey = keyManagementRepository.generateKeyPair() // KeyPair Z - val acceptanceParams = ChatParams.AcceptanceParams(publicKey.keyAsHex) val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(DAY_IN_SECONDS)) @@ -203,19 +210,32 @@ internal class ChatEngine( keyManagementRepository.setKey(threadSymmetricKey, threadTopic.value) jsonRpcInteractor.subscribe(threadTopic) - scope.launch { - _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) - } + onSuccess(threadTopic.value) + +// scope.launch { +// _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) +// } } catch (error: Exception) { onFailure(error) } - internal fun reject(inviteId: String, onFailure: (Throwable) -> Unit) { -// //todo: correct define params -// val request = WCRequest() -// val error = PeerError.Error("reason", 1) -// -// jsonRpcInteractor.respondWithError(request, error, EnvelopeType.ZERO) { throwable -> onFailure(throwable) } + internal fun reject(inviteId: Long, onFailure: (Throwable) -> Unit) { + val request = inviteRequestMap[inviteId] ?: throw GenericException("No request for inviteId") + val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) // PubKey Y + inviteRequestMap.remove(inviteId) + + val invitePublicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT)// PubKey X + val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) // SymKey I + val rejectTopic = keyManagementRepository.getTopicFromKey(symmetricKey) // Topic T + keyManagementRepository.setKey(symmetricKey, rejectTopic.value) + + val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(DAY_IN_SECONDS)) + jsonRpcInteractor.respondWithError( + request.copy(topic = rejectTopic), + PeerError.UserRejectedInvitation("Invitation rejected by a user"), + irnParams + ) + { throwable -> onFailure(throwable) } } internal fun message(topic: String, sendMessage: EngineDO.SendMessage, onFailure: (Throwable) -> Unit) { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt index 097bb9aea5..1af4765335 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt @@ -29,7 +29,7 @@ internal sealed class EngineDO { ) : EngineDO() data class Contact( - val accountIdWithPublicKeyVO: AccountIdWithPublicKey, + val accountIdWithPublicKey: AccountIdWithPublicKey, val displayName: String, ) : EngineDO() @@ -41,11 +41,9 @@ internal sealed class EngineDO { sealed class Events : EngineDO() { data class OnInvite(val id: Long, val invite: Invite) : Events() - data class OnJoined(val topic: String) : Events() - + data class OnReject(val topic: String) : Events() data class OnMessage(val topic: String, val message: Message) : Events() - data class OnLeft(val topic: String) : Events() } } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/JsonRpcMethod.kt similarity index 88% rename from chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt rename to chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/JsonRpcMethod.kt index 55e7d9dba3..0858f15049 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/model/JsonRpcMethod.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/json_rpc/JsonRpcMethod.kt @@ -1,4 +1,4 @@ -package com.walletconnect.chat.json_rpc.model +package com.walletconnect.chat.json_rpc internal object JsonRpcMethod { @get:JvmSynthetic diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt index de83c26c74..1aaf7f394c 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt @@ -16,8 +16,8 @@ internal class ChatStorageRepository(private val contactsQueries: ContactsQuerie @JvmSynthetic internal fun createContact(contact: EngineDO.Contact) = contactsQueries.insertOrAbortContact( - contact.accountIdWithPublicKeyVO.accountId.value, - contact.accountIdWithPublicKeyVO.publicKey.keyAsHex, + contact.accountIdWithPublicKey.accountId.value, + contact.accountIdWithPublicKey.publicKey.keyAsHex, contact.displayName ) From bb4d1cedd6b519f2fc03d4b9f4ae83a97aa2e9a7 Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 27 Oct 2022 09:27:38 +0200 Subject: [PATCH 17/30] Add handling back button on MessagesFragment.kt --- .../chatsample/ui/invites/InvitesFragment.kt | 5 +-- .../ui/messages/MessagesFragment.kt | 33 +++++++++---------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt index 1db5b64b2b..97c6ead421 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt @@ -18,10 +18,7 @@ class InvitesFragment : Fragment(R.layout.fragment_invites) { private val binding by viewBinding(FragmentInvitesBinding::bind) private val viewModel: ChatSharedViewModel by activityViewModels() private val invitesAdapter by lazy { - InvitesAdapter(onAccept = { chatUI -> - viewModel.acceptInvitation(chatUI) -// findNavController().navigateUp() - }, onReject = { id -> viewModel.rejectInvitation(id) }) + InvitesAdapter(onAccept = { chatUI -> viewModel.acceptInvitation(chatUI) }, onReject = { id -> viewModel.rejectInvitation(id) }) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt index 17d958c422..f2a5d87212 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt @@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.RecyclerView import com.walletconnect.chatsample.R import com.walletconnect.chatsample.databinding.FragmentMessagesBinding @@ -27,11 +28,14 @@ class MessagesFragment : Fragment(R.layout.fragment_messages) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + initView() + } + private fun initView() = with(binding) { peerName = arguments?.get(peerNameKey)?.toString() ?: "Missing PeerName" - binding.tvPeername.text = peerName - binding.rvChatThread.itemAnimator = null - with(binding.rvChatThread) { + tvPeername.text = peerName + rvChatThread.itemAnimator = null + with(rvChatThread) { addItemDecoration(object : RecyclerView.ItemDecoration() { override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { if (parent.getChildAdapterPosition(view) != parent.adapter?.itemCount?.minus(1)) { @@ -39,35 +43,30 @@ class MessagesFragment : Fragment(R.layout.fragment_messages) { } } }) - adapter = messagesAdapter } - binding.btnSend.setOnClickListener { + clBackButton.setOnClickListener { + findNavController().navigateUp() + } + btnSend.setOnClickListener { if (binding.etMessage.text.isNotBlank()) { viewModel.sendMessage(binding.etMessage.text.toString(), peerName) - binding.etMessage.setText("") + etMessage.setText("") } } - binding.tvThreadTime.text = "TODAY ${SimpleDateFormat("h:mm a").format(Date())}" - binding.ivPeerIcon.setImageDrawable( - resources.getDrawable( - ChatSharedViewModel.ensToIconMap[peerName] ?: R.drawable.ic_chat_icon_3, - null - ) - ) - + tvThreadTime.text = "TODAY ${SimpleDateFormat("h:mm a").format(Date())}" + ivPeerIcon.setImageDrawable(resources.getDrawable(ChatSharedViewModel.ensToIconMap[peerName] ?: R.drawable.ic_chat_icon_3, null)) viewModel.listOfMessagesStateFlow .flowWithLifecycle(viewLifecycleOwner.lifecycle) .onEach { messages -> - messagesAdapter.submitList(messages - .filter { it.peerName == peerName } - .map { it.toMessageBubbleUI() }) + messagesAdapter.submitList(messages.filter { it.peerName == peerName }.map { it.toMessageBubbleUI() }) } .launchIn(viewLifecycleOwner.lifecycleScope) } + private fun MessageUI.toMessageBubbleUI(): MessageBubbleUI = when (peerName) { author -> MessageBubbleUI.Peer(ChatSharedViewModel.ensToIconMap[peerName] ?: R.drawable.ic_chat_icon_3, text) else -> MessageBubbleUI.Self(text) From 9bc9e2db0bd1ee02ce60c6a2bcffa1b3e46c84a7 Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 27 Oct 2022 13:23:14 +0200 Subject: [PATCH 18/30] Fix chat after removing hardcoded ens accounts --- .../chatsample/ui/host/ChatSampleActivity.kt | 11 +- .../chatsample/ui/invites/InvitesFragment.kt | 1 + .../ui/messages/MessagesFragment.kt | 4 +- .../ui/shared/ChatSharedViewModel.kt | 198 ++++++------------ .../chatsample/ui/threads/ThreadsFragment.kt | 90 ++++---- .../chat/engine/domain/ChatEngine.kt | 5 - 6 files changed, 120 insertions(+), 189 deletions(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt index 409ebca9fc..7a9003d129 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt @@ -51,11 +51,12 @@ class ChatSampleActivity : AppCompatActivity() { } - private fun showOnInviteSnackbar(event: ChatSharedEvents.OnInvite) = Snackbar.make( - binding.root, - "\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31 You got an invite from: ${ChatSharedViewModel.accountIdToEnsMap[event.invite.account.value] ?: event.invite.account.value}", - Snackbar.LENGTH_LONG - ).show() + private fun showOnInviteSnackbar(event: ChatSharedEvents.OnInvite) = + Snackbar.make( + binding.root, + "\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31 You got an invite from: ${event.invite.account.value}", + Snackbar.LENGTH_LONG + ).show() override fun onSupportNavigateUp(): Boolean { return navHostFragment.navController.navigateUp() || super.onSupportNavigateUp() diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt index 97c6ead421..2817af3bd7 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt @@ -28,5 +28,6 @@ class InvitesFragment : Fragment(R.layout.fragment_invites) { .flowWithLifecycle(viewLifecycleOwner.lifecycle) .onEach { chatUIList -> invitesAdapter.submitList(chatUIList) } .launchIn(viewLifecycleOwner.lifecycleScope) + binding.clBackButton.setOnClickListener { findNavController().navigateUp() } } } \ No newline at end of file diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt index f2a5d87212..33dc9598ed 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/messages/MessagesFragment.kt @@ -57,7 +57,7 @@ class MessagesFragment : Fragment(R.layout.fragment_messages) { } tvThreadTime.text = "TODAY ${SimpleDateFormat("h:mm a").format(Date())}" - ivPeerIcon.setImageDrawable(resources.getDrawable(ChatSharedViewModel.ensToIconMap[peerName] ?: R.drawable.ic_chat_icon_3, null)) + ivPeerIcon.setImageDrawable(resources.getDrawable(R.drawable.ic_chat_icon_3, null)) viewModel.listOfMessagesStateFlow .flowWithLifecycle(viewLifecycleOwner.lifecycle) .onEach { messages -> @@ -68,7 +68,7 @@ class MessagesFragment : Fragment(R.layout.fragment_messages) { private fun MessageUI.toMessageBubbleUI(): MessageBubbleUI = when (peerName) { - author -> MessageBubbleUI.Peer(ChatSharedViewModel.ensToIconMap[peerName] ?: R.drawable.ic_chat_icon_3, text) + author -> MessageBubbleUI.Peer(R.drawable.ic_chat_icon_3, text) else -> MessageBubbleUI.Self(text) } diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index 6575b024d9..2c78b6d32d 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -29,8 +29,7 @@ class ChatSharedViewModel : ViewModel() { private val _listOfMessagesStateFlow: MutableStateFlow> = MutableStateFlow(listOfMessages.toList()) val listOfMessagesStateFlow: StateFlow> = _listOfMessagesStateFlow - fun getLastMessage(peername: String) = listOfMessages.last { it.peerName == peername } - + fun getLastMessage(peerName: String) = listOfMessages.last { it.peerName == peerName } val emittedEvents: Flow = ChatDelegate.wcEventModels.map { walletEvent: Chat.Model.Events -> Log.d(tag(this), walletEvent.toString()) @@ -38,7 +37,7 @@ class ChatSharedViewModel : ViewModel() { is Chat.Model.Events.OnInvite -> walletEvent.toChatSharedEvents().also { onInvite(it) } is Chat.Model.Events.OnJoined -> walletEvent.toChatSharedEvents().also { onJoined(it) } is Chat.Model.Events.OnMessage -> walletEvent.toChatSharedEvents().also { onMessage(it) } - is Chat.Model.Events.OnReject -> walletEvent.toChatSharedEvents().also { onReject(it) } + is Chat.Model.Events.OnReject -> walletEvent.toChatSharedEvents() else -> ChatSharedEvents.NoAction } }.shareIn(viewModelScope, SharingStarted.WhileSubscribed()) @@ -47,45 +46,82 @@ class ChatSharedViewModel : ViewModel() { private fun onInvite(event: ChatSharedEvents.OnInvite) { Log.d(tag(this), "Invited: ${event.invite.message}") - val contact = accountIdToEnsMap[event.invite.account.value] ?: event.invite.account.value + val contact = event.invite.account.value currentInvite = event.invite - listOfInvites.add(ChatUI(ensToIconMap[contact] ?: R.drawable.ic_chat_icon_3, contact, event.invite.message, event.id)) + listOfInvites.add(ChatUI(R.drawable.ic_chat_icon_3, contact, event.invite.message, event.id)) _listOfInvitesStateFlow.update { listOfInvites.toList() } listOfMessages.add(MessageUI(contact, event.invite.message, System.currentTimeMillis(), contact)) _listOfMessagesStateFlow.value = listOfMessages.toList() } + fun acceptInvitation(chatUI: ChatUI) { + chatUI.id?.let { id -> + + ChatClient.accept(Chat.Params.Accept(id), onSuccess = { threadTopic -> + + if (currentInvite != null) { + + val currentAccountId = currentInvite?.account?.value + + currentAccountId?.let { accountId -> + if (currentAccountId != SELF_ACCOUNT) { + Log.e(tag(this), "currentAccountId != SELF_ACCOUNT") + listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, accountId, currentInvite!!.message, null)) + _listOfThreadsStateFlow.value = listOfThreads.toList() + userNameToTopicMap.put(accountId, threadTopic) + } else { + Log.e(tag(this), "ens == SELF_ENS") + + listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, whoWasInvitedContact!!, currentInvite!!.message, null)) + _listOfThreadsStateFlow.value = listOfThreads.toList() + userNameToTopicMap.put(whoWasInvitedContact!!, threadTopic) + } + } + } else Log.e(tag(this), "Unable to find currentInvite or invited contact") + + }, { error -> Log.e(tag(this), error.throwable.stackTraceToString()) }) + + listOfInvites.removeIf { it.username == chatUI.username } + _listOfInvitesStateFlow.value = listOfInvites.toList() + + } ?: Log.e(tag(this), "Unable to find id on accpet invitation: $chatUI") + } + + fun sendMessage(message: String, peerName: String) { + Log.e(tag(this), "sendMessage: $peerName") + + val (userName, topic) = userNameToTopicMap.entries.single { entry -> entry.key == peerName } + + listOfMessages.add(MessageUI(userName, message, System.currentTimeMillis(), SELF_ACCOUNT)) + _listOfMessagesStateFlow.value = listOfMessages.toList() + ChatClient.message(Chat.Params.Message(topic, Chat.Model.AccountId(SELF_ACCOUNT), message)) { error -> + Log.e(tag(this), error.throwable.stackTraceToString()) + } + } + private fun onJoined(event: ChatSharedEvents.OnJoined) { Log.d(tag(this), "Joined: ${event.topic}") if (currentInvite != null) { - accountIdToEnsMap[currentInvite?.account?.value]?.let { ens -> - if (ens != SELF_ENS) { - Log.e(tag(this), "ens != SELF_ENS") - listOfThreads.add(ChatUI(ensToIconMap[ens] ?: R.drawable.ic_chat_icon_3, ens, currentInvite!!.message, null)) + val currentAccountId = currentInvite?.account?.value + currentAccountId?.let { accountId -> + if (currentAccountId != SELF_ACCOUNT) { + Log.e(tag(this), "currentAccountId != SELF_ACCOUNT") + listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, accountId, currentInvite!!.message, null)) _listOfThreadsStateFlow.value = listOfThreads.toList() - - userNameToTopicMap.put(ens, event.topic) + userNameToTopicMap.put(accountId, event.topic) } else { Log.e(tag(this), "ens == SELF_ENS") - listOfThreads.add( - ChatUI( - ensToIconMap[whoWasInvitedContact] ?: R.drawable.ic_chat_icon_3, - whoWasInvitedContact!!, - currentInvite!!.message, - null - ) - ) + listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, whoWasInvitedContact!!, currentInvite!!.message, null)) _listOfThreadsStateFlow.value = listOfThreads.toList() userNameToTopicMap.put(whoWasInvitedContact!!, event.topic) } - } - } else Log.e(tag(this), "Unable to find currentInvite: $event") + } else Log.e(tag(this), "Unable to find currentInvite or invited contact") } private fun onMessage(event: ChatSharedEvents.OnMessage) { @@ -93,59 +129,14 @@ class ChatSharedViewModel : ViewModel() { userNameToTopicMap.entries.find { it.value == event.topic }?.let { (_, topic) -> listOfThreads.find { topic == event.topic }?.let { - accountIdToEnsMap[event.message.authorAccount.value]?.let { authorEns -> - listOfMessages.add(MessageUI(authorEns, event.message.message, event.message.timestamp, authorEns)) - _listOfMessagesStateFlow.value = listOfMessages.toList() - } + val author = event.message.authorAccount.value + listOfMessages.add(MessageUI(author, event.message.message, event.message.timestamp, author)) + _listOfMessagesStateFlow.value = listOfMessages.toList() + } ?: Log.e(tag(this), "Unable to find topic: ${event.topic}") } } - private fun onReject(event: ChatSharedEvents.OnReject) { - - Log.e("Kobe", "ON REJECT VM") - - } - - fun acceptInvitation(chatUI: ChatUI) { - chatUI.id?.let { id -> - ChatClient.accept(Chat.Params.Accept(id), onSuccess = { threadTopic -> - - if (currentInvite != null) { - accountIdToEnsMap[currentInvite?.account?.value]?.let { ens -> - if (ens != SELF_ENS) { - Log.e(tag(this), "ens != SELF_ENS") - - listOfThreads.add(ChatUI(ensToIconMap[ens] ?: R.drawable.ic_chat_icon_3, ens, currentInvite!!.message, null)) - _listOfThreadsStateFlow.value = listOfThreads.toList() - - userNameToTopicMap.put(ens, threadTopic) - } else { - Log.e(tag(this), "ens == SELF_ENS") - - listOfThreads.add( - ChatUI( - ensToIconMap[whoWasInvitedContact] ?: R.drawable.ic_chat_icon_3, - whoWasInvitedContact!!, - currentInvite!!.message, - null - ) - ) - _listOfThreadsStateFlow.value = listOfThreads.toList() - userNameToTopicMap.put(whoWasInvitedContact!!, threadTopic) - } - - } - } else Log.e(tag(this), "Unable to find currentInvite") - - }, { error -> Log.e(tag(this), error.throwable.stackTraceToString()) }) - - listOfInvites.removeIf { it.username == chatUI.username } - _listOfInvitesStateFlow.value = listOfInvites.toList() - - } ?: Log.e(tag(this), "Unable to find id on accpet invitation: $chatUI") - } - fun rejectInvitation(id: Long?) { id?.let { val reject = Chat.Params.Reject(it) @@ -156,41 +147,14 @@ class ChatSharedViewModel : ViewModel() { } ?: Log.e(tag(this), "Unable to find id on reject invitation: $id") } - fun sendMessage(message: String, peername: String) { - Log.e(tag(this), "sendMessage: $peername") - - val (ens, topic) = userNameToTopicMap.entries.single { it.key == peername } - listOfMessages.add(MessageUI(ens, message, System.currentTimeMillis(), SELF_ENS)) - _listOfMessagesStateFlow.value = listOfMessages.toList() - -// if (ensToAccountIdMap[ens] != null) { - - //todo: fix state - ChatClient.message( - Chat.Params.Message( - topic, - Chat.Model.AccountId(ensToAccountIdMap[SELF_ENS] ?: "eip155:4:0xab16a96d359ec26a11e2c2b3d8f8b89488888888"), - message - ) - ) { error -> - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) - } - } -// } else { -// Log.e(tag(this), "Unable to find contact: $ens") -// } - } - fun register(listener: Chat.Listeners.Register) { ChatClient.register(Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)), listener) } fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { - val accountId = ensToAccountIdMap[contact] ?: contact - ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(accountId)), object : Chat.Listeners.Resolve { + ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(contact)), object : Chat.Listeners.Resolve { override fun onError(error: Chat.Model.Error) { runBlocking(Dispatchers.Main) { Log.e(tag(this), error.throwable.stackTraceToString()) @@ -198,21 +162,21 @@ class ChatSharedViewModel : ViewModel() { } override fun onSuccess(publicKey: String) { - ChatClient.addContact(Chat.Params.AddContact(Chat.Model.AccountId(accountId), publicKey)) { error -> + ChatClient.addContact(Chat.Params.AddContact(Chat.Model.AccountId(contact), publicKey)) { error -> runBlocking(Dispatchers.Main) { Log.e(tag(this), error.throwable.stackTraceToString()) } } val inviteModel = Chat.Model.Invite(Chat.Model.AccountId(SELF_ACCOUNT), openingMessage) - Chat.Params.Invite(Chat.Model.AccountId(accountId), inviteModel).also { invite -> + Chat.Params.Invite(Chat.Model.AccountId(contact), inviteModel).also { invite -> ChatClient.invite(invite) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } } runBlocking(Dispatchers.Main) { currentInvite = inviteModel whoWasInvitedContact = contact Log.e(tag(this), "invite: $currentInvite") - listOfMessages.add(MessageUI(contact, inviteModel.message, System.currentTimeMillis(), SELF_ENS)) + listOfMessages.add(MessageUI(contact, inviteModel.message, System.currentTimeMillis(), contact)) _listOfMessagesStateFlow.value = listOfMessages.toList() afterInviteSent() } @@ -221,36 +185,8 @@ class ChatSharedViewModel : ViewModel() { } companion object { - private const val SWIFT_ENS = "Swift.eth" - private const val SWIFT_ACCOUNT_ID = "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - private const val KOTLIN_ENS = "Kotlin.eth" private const val KOTLIN_ACCOUNT_ID = "eip155:2:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - private const val JS_ENS = "Js.eth" - private const val JS_ACCOUNT_ID = "eip155:3:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - - private const val TEST_ENS = "mom.eth" - private const val TEST_ACCOUNT_ID = "eip155:4:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - - - private const val isPrimary = true - val SELF_ACCOUNT = - if (isPrimary) KOTLIN_ACCOUNT_ID else TEST_ACCOUNT_ID //SWIFT_ACCOUNT_ID - val SELF_ENS = if (isPrimary) KOTLIN_ENS else TEST_ENS //SWIFT_ENS - - val ensToAccountIdMap = mapOf( - SWIFT_ENS to SWIFT_ACCOUNT_ID, - KOTLIN_ENS to KOTLIN_ACCOUNT_ID, - JS_ENS to JS_ACCOUNT_ID, - TEST_ENS to TEST_ACCOUNT_ID - ) - - val accountIdToEnsMap = ensToAccountIdMap.map { it.value to it.key }.toMap() - - val ensToIconMap = mapOf( - SWIFT_ENS to R.drawable.ic_chat_icon_2, - KOTLIN_ENS to R.drawable.ic_chat_icon_1, - JS_ENS to R.drawable.ic_chat_icon_3, - TEST_ENS to R.drawable.ic_chat_icon_3 - ) + private const val SWIFT_ACCOUNT_ID = "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" + val SELF_ACCOUNT = SWIFT_ACCOUNT_ID// KOTLIN_ACCOUNT_ID } } \ No newline at end of file diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt index 5ebd9752f0..dc394cfdde 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt @@ -31,60 +31,58 @@ class ThreadsFragment : Fragment(R.layout.fragment_threads) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.rvChatLists.adapter = threadsAdapter - binding.rvChatLists.itemAnimator = null + with(binding) { + rvChatLists.adapter = threadsAdapter + rvChatLists.itemAnimator = null + flChatRequests.setOnClickListener { findNavController().navigate(R.id.action_threadsFragment_to_invitesFragment) } + btnInvite.setOnClickListener { findNavController().navigate(R.id.action_threadsFragment_to_threadInviteDialogFragment) } - binding.flChatRequests.setOnClickListener { - findNavController().navigate(R.id.action_threadsFragment_to_invitesFragment) - } - - binding.btnInvite.setOnClickListener { - findNavController().navigate(R.id.action_threadsFragment_to_threadInviteDialogFragment) - } - - viewModel.emittedEvents - .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) - .onEach { event -> - when (event) { - is ChatSharedEvents.OnMessage -> { - Snackbar.make(binding.root, - "New message from: ${viewModel.userNameToTopicMap.entries.single { it.value == event.topic }.key}", - Snackbar.LENGTH_LONG).show() + viewModel.emittedEvents + .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) + .onEach { event -> + when (event) { + is ChatSharedEvents.OnMessage -> { + Snackbar.make( + binding.root, "New message from: ${viewModel.userNameToTopicMap.entries.single { it.value == event.topic }.key}", + Snackbar.LENGTH_LONG + ).show() + } + else -> Unit } - else -> Unit - } - }.launchIn(lifecycleScope) + }.launchIn(lifecycleScope) - viewModel - .listOfMessagesStateFlow - .flowWithLifecycle(viewLifecycleOwner.lifecycle) - .onEach { threadsAdapter.submitList(viewModel.listOfThreads.toList()) } - .launchIn(viewLifecycleOwner.lifecycleScope) + viewModel + .listOfMessagesStateFlow + .flowWithLifecycle(viewLifecycleOwner.lifecycle) + .onEach { threadsAdapter.submitList(viewModel.listOfThreads.toList()) } + .launchIn(viewLifecycleOwner.lifecycleScope) - viewModel - .listOfThreadsStateFlow - .flowWithLifecycle(viewLifecycleOwner.lifecycle) - .onEach { threadsAdapter.submitList(it.toList()) } - .launchIn(viewLifecycleOwner.lifecycleScope) + viewModel + .listOfThreadsStateFlow + .flowWithLifecycle(viewLifecycleOwner.lifecycle) + .onEach { threadsAdapter.submitList(it.toList()) } + .launchIn(viewLifecycleOwner.lifecycleScope) - viewModel - .listOfInvitesStateFlow - .flowWithLifecycle(viewLifecycleOwner.lifecycle) - .onEach { binding.flChatRequests.findViewById(R.id.tvChatRequestsCount).text = it.size.toString() } - .launchIn(viewLifecycleOwner.lifecycleScope) + viewModel + .listOfInvitesStateFlow + .flowWithLifecycle(viewLifecycleOwner.lifecycle) + .onEach { flChatRequests.findViewById(R.id.tvChatRequestsCount).text = it.size.toString() } + .launchIn(viewLifecycleOwner.lifecycleScope) - viewModel.register(object : Chat.Listeners.Register { - override fun onError(error: Chat.Model.Error) { - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) + viewModel.register(object : Chat.Listeners.Register { + override fun onError(error: Chat.Model.Error) { + runBlocking(Dispatchers.Main) { + Log.e(tag(this), error.throwable.stackTraceToString()) + } } - } - override fun onSuccess(publicKey: String) { - runBlocking(Dispatchers.Main) { - Log.d(tag(this), "Registered successfully") + override fun onSuccess(publicKey: String) { + runBlocking(Dispatchers.Main) { + Log.d(tag(this), "Registered successfully") + } } - } - }) + }) + } + } } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 666e107842..822698817c 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -209,12 +209,7 @@ internal class ChatEngine( val threadTopic = keyManagementRepository.getTopicFromKey(threadSymmetricKey) // Topic T keyManagementRepository.setKey(threadSymmetricKey, threadTopic.value) jsonRpcInteractor.subscribe(threadTopic) - onSuccess(threadTopic.value) - -// scope.launch { -// _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) -// } } catch (error: Exception) { onFailure(error) } From 1548d9b859a9a7f3ded38d9f5af7c12005b60053 Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 27 Oct 2022 15:26:22 +0200 Subject: [PATCH 19/30] Add mapper for contacts dao --- .../chatsample/domain/ChatDelegate.kt | 7 +- .../ui/shared/ChatSharedViewModel.kt | 171 +++++------- .../com/walletconnect/chat/client/Chat.kt | 8 +- .../chat/client/ChatInterface.kt | 1 + .../walletconnect/chat/client/ChatProtocol.kt | 3 + .../chat/client/mapper/ClientMapper.kt | 4 + .../chat/common/exceptions/ChatExceptions.kt | 5 + .../chat/common/model/Contact.kt | 9 + .../exceptions/client/ClientExceptions.kt | 0 .../crypto/KeyManagementRepository.kt | 0 .../chat/copiedFromSign/di/NetworkModule.kt | 0 .../json_rpc/domain/RelayerInteractor.kt | 0 .../lifecycle/ManualConnectionLifecycle.kt | 0 .../chat/engine/domain/ChatEngine.kt | 246 +++++++++--------- .../chat/engine/model/EngineDO.kt | 5 +- .../chat/storage/ChatStorageRepository.kt | 19 +- .../sign/engine/model/EngineDO.kt | 6 - 17 files changed, 234 insertions(+), 250 deletions(-) create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/ChatExceptions.kt create mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Contact.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/client/ClientExceptions.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyManagementRepository.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/NetworkModule.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/domain/RelayerInteractor.kt delete mode 100644 chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/lifecycle/ManualConnectionLifecycle.kt diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt index 355e2cedb5..1cb06c1332 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt @@ -46,7 +46,12 @@ object ChatDelegate : ChatClient.ChatDelegate { } override fun onLeft(onLeft: Chat.Model.Events.OnLeft) { - TODO("Not yet implemented") + //todo: implement me + Log.e("ChatDelegate", "On thread left") + } + + override fun onConnectionStateChange(state: Chat.Model.ConnectionState) { + Log.e("ChatDelegate", "On connection changed:$state") } @OptIn(ExperimentalCoroutinesApi::class) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index 2c78b6d32d..ea9bb007a9 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -42,58 +42,60 @@ class ChatSharedViewModel : ViewModel() { } }.shareIn(viewModelScope, SharingStarted.WhileSubscribed()) + fun register(listener: Chat.Listeners.Register) { + ChatClient.register(Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)), listener) + } - private fun onInvite(event: ChatSharedEvents.OnInvite) { - Log.d(tag(this), "Invited: ${event.invite.message}") - - val contact = event.invite.account.value - currentInvite = event.invite + fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { + ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(contact)), object : Chat.Listeners.Resolve { + override fun onError(error: Chat.Model.Error) { + runBlocking(Dispatchers.Main) { + Log.e(tag(this), error.throwable.stackTraceToString()) + } + } - listOfInvites.add(ChatUI(R.drawable.ic_chat_icon_3, contact, event.invite.message, event.id)) - _listOfInvitesStateFlow.update { listOfInvites.toList() } + override fun onSuccess(publicKey: String) { + ChatClient.addContact(Chat.Params.AddContact(Chat.Model.AccountId(contact), publicKey)) { error -> + Log.e(tag(this), error.throwable.stackTraceToString()) + } - listOfMessages.add(MessageUI(contact, event.invite.message, System.currentTimeMillis(), contact)) - _listOfMessagesStateFlow.value = listOfMessages.toList() + val inviteModel = Chat.Model.Invite(Chat.Model.AccountId(SELF_ACCOUNT), openingMessage) + Chat.Params.Invite(Chat.Model.AccountId(contact), inviteModel).also { invite -> + ChatClient.invite(invite) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } + } + runBlocking(Dispatchers.Main) { + currentInvite = inviteModel + whoWasInvitedContact = contact + Log.e(tag(this), "invite: $currentInvite") + listOfMessages.add(MessageUI(contact, inviteModel.message, System.currentTimeMillis(), contact)) + _listOfMessagesStateFlow.value = listOfMessages.toList() + afterInviteSent() + } + } + }) } fun acceptInvitation(chatUI: ChatUI) { chatUI.id?.let { id -> - - ChatClient.accept(Chat.Params.Accept(id), onSuccess = { threadTopic -> - - if (currentInvite != null) { - - val currentAccountId = currentInvite?.account?.value - - currentAccountId?.let { accountId -> - if (currentAccountId != SELF_ACCOUNT) { - Log.e(tag(this), "currentAccountId != SELF_ACCOUNT") - listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, accountId, currentInvite!!.message, null)) - _listOfThreadsStateFlow.value = listOfThreads.toList() - userNameToTopicMap.put(accountId, threadTopic) - } else { - Log.e(tag(this), "ens == SELF_ENS") - - listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, whoWasInvitedContact!!, currentInvite!!.message, null)) - _listOfThreadsStateFlow.value = listOfThreads.toList() - userNameToTopicMap.put(whoWasInvitedContact!!, threadTopic) - } - } - } else Log.e(tag(this), "Unable to find currentInvite or invited contact") - - }, { error -> Log.e(tag(this), error.throwable.stackTraceToString()) }) - - listOfInvites.removeIf { it.username == chatUI.username } - _listOfInvitesStateFlow.value = listOfInvites.toList() - + ChatClient.accept(Chat.Params.Accept(id), onSuccess = { threadTopic -> updateThread(threadTopic) }, { error -> + Log.e(tag(this), error.throwable.stackTraceToString()) + }) + updateInvites(chatUI.id) } ?: Log.e(tag(this), "Unable to find id on accpet invitation: $chatUI") } + fun rejectInvitation(id: Long?) { + id?.let { + val reject = Chat.Params.Reject(it) + ChatClient.reject(reject) { error -> Log.e(tag(this), "Unable to find reject invitation: $error") } + updateInvites(id) + } ?: Log.e(tag(this), "Unable to find id on reject invitation: $id") + } + fun sendMessage(message: String, peerName: String) { Log.e(tag(this), "sendMessage: $peerName") val (userName, topic) = userNameToTopicMap.entries.single { entry -> entry.key == peerName } - listOfMessages.add(MessageUI(userName, message, System.currentTimeMillis(), SELF_ACCOUNT)) _listOfMessagesStateFlow.value = listOfMessages.toList() ChatClient.message(Chat.Params.Message(topic, Chat.Model.AccountId(SELF_ACCOUNT), message)) { error -> @@ -101,27 +103,21 @@ class ChatSharedViewModel : ViewModel() { } } - private fun onJoined(event: ChatSharedEvents.OnJoined) { - Log.d(tag(this), "Joined: ${event.topic}") + private fun onInvite(event: ChatSharedEvents.OnInvite) { + Log.d(tag(this), "Invited: ${event.invite.message}") + val contact = event.invite.account.value + currentInvite = event.invite - if (currentInvite != null) { + listOfInvites.add(ChatUI(R.drawable.ic_chat_icon_3, contact, event.invite.message, event.id)) + _listOfInvitesStateFlow.update { listOfInvites.toList() } - val currentAccountId = currentInvite?.account?.value - currentAccountId?.let { accountId -> - if (currentAccountId != SELF_ACCOUNT) { - Log.e(tag(this), "currentAccountId != SELF_ACCOUNT") - listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, accountId, currentInvite!!.message, null)) - _listOfThreadsStateFlow.value = listOfThreads.toList() - userNameToTopicMap.put(accountId, event.topic) - } else { - Log.e(tag(this), "ens == SELF_ENS") + listOfMessages.add(MessageUI(contact, event.invite.message, System.currentTimeMillis(), contact)) + _listOfMessagesStateFlow.value = listOfMessages.toList() + } - listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, whoWasInvitedContact!!, currentInvite!!.message, null)) - _listOfThreadsStateFlow.value = listOfThreads.toList() - userNameToTopicMap.put(whoWasInvitedContact!!, event.topic) - } - } - } else Log.e(tag(this), "Unable to find currentInvite or invited contact") + private fun onJoined(event: ChatSharedEvents.OnJoined) { + Log.d(tag(this), "Joined: ${event.topic}") + updateThread(event.topic) } private fun onMessage(event: ChatSharedEvents.OnMessage) { @@ -132,61 +128,36 @@ class ChatSharedViewModel : ViewModel() { val author = event.message.authorAccount.value listOfMessages.add(MessageUI(author, event.message.message, event.message.timestamp, author)) _listOfMessagesStateFlow.value = listOfMessages.toList() - } ?: Log.e(tag(this), "Unable to find topic: ${event.topic}") } } - fun rejectInvitation(id: Long?) { - id?.let { - val reject = Chat.Params.Reject(it) - ChatClient.reject(reject) { error -> Log.e(tag(this), "Unable to find reject invitation: $error") } - - listOfInvites.removeIf { invite -> invite.id == id } - _listOfInvitesStateFlow.value = listOfInvites.toList() - } ?: Log.e(tag(this), "Unable to find id on reject invitation: $id") - } - - fun register(listener: Chat.Listeners.Register) { - ChatClient.register(Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)), listener) - } - - fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { - - - ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(contact)), object : Chat.Listeners.Resolve { - override fun onError(error: Chat.Model.Error) { - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) + private fun updateThread(threadTopic: String) { + if (currentInvite != null) { + val currentAccountId = currentInvite?.account?.value + currentAccountId?.let { accountId -> + if (currentAccountId != SELF_ACCOUNT) { + listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, accountId, currentInvite!!.message, null)) + _listOfThreadsStateFlow.value = listOfThreads.toList() + userNameToTopicMap.put(accountId, threadTopic) + } else { + listOfThreads.add(ChatUI(R.drawable.ic_chat_icon_3, whoWasInvitedContact!!, currentInvite!!.message, null)) + _listOfThreadsStateFlow.value = listOfThreads.toList() + userNameToTopicMap.put(whoWasInvitedContact!!, threadTopic) } } + } else Log.e(tag(this), "Unable to find currentInvite or invited contact") + } - override fun onSuccess(publicKey: String) { - ChatClient.addContact(Chat.Params.AddContact(Chat.Model.AccountId(contact), publicKey)) { error -> - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) - } - } - - val inviteModel = Chat.Model.Invite(Chat.Model.AccountId(SELF_ACCOUNT), openingMessage) - Chat.Params.Invite(Chat.Model.AccountId(contact), inviteModel).also { invite -> - ChatClient.invite(invite) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } - } - runBlocking(Dispatchers.Main) { - currentInvite = inviteModel - whoWasInvitedContact = contact - Log.e(tag(this), "invite: $currentInvite") - listOfMessages.add(MessageUI(contact, inviteModel.message, System.currentTimeMillis(), contact)) - _listOfMessagesStateFlow.value = listOfMessages.toList() - afterInviteSent() - } - } - }) + private fun updateInvites(id: Long?) { + listOfInvites.removeIf { invite -> invite.id == id } + _listOfInvitesStateFlow.value = listOfInvites.toList() } companion object { private const val KOTLIN_ACCOUNT_ID = "eip155:2:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" private const val SWIFT_ACCOUNT_ID = "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - val SELF_ACCOUNT = SWIFT_ACCOUNT_ID// KOTLIN_ACCOUNT_ID + private const val JS_ACCOUNT_ID = "eip155:3:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" + val SELF_ACCOUNT = KOTLIN_ACCOUNT_ID } } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt index 0d214c43c7..c625927e01 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt @@ -17,12 +17,12 @@ object Chat { sealed class Model { - data class Error(val throwable: Throwable) : Model() // TODO: Should this be extracted to core for easier error handling? + data class Error(val throwable: Throwable) : Model() + + data class ConnectionState(val isAvailable: Boolean) : Model() @JvmInline - value class AccountId(val value: String) { - fun isValid() = com.walletconnect.chat.common.model.AccountId(value).isValid() - } + value class AccountId(val value: String) data class Invite( val account: AccountId, diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt index 97597f4298..b8c8af9454 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt @@ -8,6 +8,7 @@ interface ChatInterface { fun onReject(onReject: Chat.Model.Events.OnReject) fun onMessage(onMessage: Chat.Model.Events.OnMessage) fun onLeft(onLeft: Chat.Model.Events.OnLeft) + fun onConnectionStateChange(state: Chat.Model.ConnectionState) } fun setChatDelegate(delegate: ChatDelegate) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index 81ed2bdac2..be7c1e9d14 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -1,5 +1,6 @@ package com.walletconnect.chat.client +import com.walletconnect.android.impl.common.model.ConnectionState import com.walletconnect.android.impl.di.cryptoModule import com.walletconnect.android.impl.utils.Logger import com.walletconnect.android.internal.common.scope @@ -40,6 +41,7 @@ internal class ChatProtocol : ChatInterface { } chatEngine = wcKoinApp.koin.get() + chatEngine.handleInitializationErrors { error -> onError(Chat.Model.Error(error)) } } override fun setChatDelegate(delegate: ChatInterface.ChatDelegate) { @@ -53,6 +55,7 @@ internal class ChatProtocol : ChatInterface { is EngineDO.Events.OnReject -> delegate.onReject(event.toClient()) is EngineDO.Events.OnMessage -> delegate.onMessage(event.toClient()) is EngineDO.Events.OnLeft -> delegate.onLeft(event.toClient()) + is ConnectionState -> delegate.onConnectionStateChange(event.toClient()) } } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt index d369047946..169978b4cc 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt @@ -2,6 +2,7 @@ package com.walletconnect.chat.client.mapper +import com.walletconnect.android.impl.common.model.ConnectionState import com.walletconnect.chat.client.Chat import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.Media @@ -73,3 +74,6 @@ internal fun EngineDO.Message.toClient(): Chat.Model.Message { return Chat.Model.Message(message, authorAccountId.toClient(), timestamp, media?.toClient()) } +@JvmSynthetic +internal fun ConnectionState.toClient(): Chat.Model.ConnectionState = + Chat.Model.ConnectionState(isAvailable) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/ChatExceptions.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/ChatExceptions.kt new file mode 100644 index 0000000000..e126e9202e --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/exceptions/ChatExceptions.kt @@ -0,0 +1,5 @@ +package com.walletconnect.chat.common.exceptions + +import com.walletconnect.android.internal.common.exception.WalletConnectException + +class InvalidAccountIdException(override val message: String?) : WalletConnectException(message) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Contact.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Contact.kt new file mode 100644 index 0000000000..b3de66359b --- /dev/null +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/common/model/Contact.kt @@ -0,0 +1,9 @@ +package com.walletconnect.chat.common.model + +import com.walletconnect.foundation.common.model.PublicKey + +internal data class Contact( + val accountId: AccountId, + val publicKey: PublicKey, + val displayName: String +) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/client/ClientExceptions.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/core/exceptions/client/ClientExceptions.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyManagementRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/crypto/KeyManagementRepository.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/NetworkModule.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/di/NetworkModule.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/domain/RelayerInteractor.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/json_rpc/domain/RelayerInteractor.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/lifecycle/ManualConnectionLifecycle.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/copiedFromSign/network/connection/lifecycle/ManualConnectionLifecycle.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 822698817c..3683db66a1 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -2,6 +2,8 @@ package com.walletconnect.chat.engine.domain +import com.walletconnect.android.impl.common.model.ConnectionState +import com.walletconnect.android.impl.common.model.type.EngineEvent import com.walletconnect.android.impl.utils.DAY_IN_SECONDS import com.walletconnect.android.impl.utils.Logger import com.walletconnect.android.impl.utils.SELF_INVITE_PUBLIC_KEY_CONTEXT @@ -9,8 +11,10 @@ import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT import com.walletconnect.android.internal.common.JsonRpcResponse import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.internal.common.exception.GenericException +import com.walletconnect.android.internal.common.exception.WalletConnectException import com.walletconnect.android.internal.common.model.* import com.walletconnect.android.internal.common.scope +import com.walletconnect.chat.common.exceptions.InvalidAccountIdException import com.walletconnect.chat.common.exceptions.PeerError import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey @@ -37,41 +41,18 @@ internal class ChatEngine( private val jsonRpcInteractor: JsonRpcInteractorInterface, private val chatStorage: ChatStorageRepository, ) { - private val _events: MutableSharedFlow = MutableSharedFlow() - val events: SharedFlow = _events.asSharedFlow() + private val _events: MutableSharedFlow = MutableSharedFlow() + val events: SharedFlow = _events.asSharedFlow() private val inviteRequestMap: MutableMap = mutableMapOf() init { collectJsonRpcRequests() collectPeerResponses() - - jsonRpcInteractor.initializationErrorsFlow.onEach { error -> Logger.error(error) }.launchIn(scope) - jsonRpcInteractor.isConnectionAvailable - .onEach { isAvailable -> -// _events.emit(EngineDO.ConnectionState(isAvailable)) todo add connection state callbacks - } - .filter { isAvailable: Boolean -> isAvailable } - .onEach { - coroutineScope { - launch(Dispatchers.IO) { trySubscribeToInviteTopic() } - } - } - .launchIn(scope) - + resubscribeToInviteTopic() } - internal fun resolveAccount(accountId: AccountId, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { - //todo: add CAIP25 compatibility check - - //tod check if there's pubKey under given accountId if yes use it if not register - scope.launch { - supervisorScope { - resolveAccountUseCase(accountId).fold( - onSuccess = { accountIdWithPublicKeyVO -> onSuccess(accountIdWithPublicKeyVO.publicKey.keyAsHex) }, - onFailure = { error -> onFailure(error) } - ) - } - } + fun handleInitializationErrors(onError: (WalletConnectException) -> Unit) { + jsonRpcInteractor.initializationErrorsFlow.onEach { walletConnectException -> onError(walletConnectException) }.launchIn(scope) } internal fun registerAccount( @@ -88,45 +69,50 @@ internal class ChatEngine( onSuccess(publicKey.keyAsHex) } - val publicKey = keyManagementRepository.generateKeyPair() - if (!private) { + if (accountId.isValid()) { + val publicKey = keyManagementRepository.generateKeyPair() + if (!private) { + scope.launch { + supervisorScope { + registerAccountUseCase(AccountIdWithPublicKey(accountId, publicKey)).fold( + onSuccess = { onSuccess(publicKey) }, + onFailure = { error -> onFailure(error) } + ) + } + } + } else { + onSuccess(publicKey) + } + } else { + onFailure(InvalidAccountIdException("AccountId is not CAIP-10 complaint")) + } + } + + internal fun resolveAccount(accountId: AccountId, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { + if (accountId.isValid()) { + //todo: check if there's pubKey under given accountId if yes use it if not register scope.launch { supervisorScope { - registerAccountUseCase(AccountIdWithPublicKey(accountId, publicKey)).fold( - onSuccess = { onSuccess(publicKey) }, + resolveAccountUseCase(accountId).fold( + onSuccess = { accountIdWithPublicKeyVO -> onSuccess(accountIdWithPublicKeyVO.publicKey.keyAsHex) }, onFailure = { error -> onFailure(error) } ) } } } else { - onSuccess(publicKey) - } - } - - private fun trySubscribeToInviteTopic() { - try { - val publicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT) - val topic = keyManagementRepository.getTopicFromKey(publicKey) - jsonRpcInteractor.subscribe(topic) - Logger.log("Listening for invite on: $topic, pubKey X:$publicKey") - } catch (error: Exception) { - Logger.log(error) // It will log if run before registerAccount() - //TODO: Create exception if there is no key created + onFailure(InvalidAccountIdException("AccountId is not CAIP-10 complaint")) } } internal fun invite(peerAccount: AccountId, invite: EngineDO.Invite, onFailure: (Throwable) -> Unit) = try { - val senderPublicKey = keyManagementRepository.generateKeyPair() // KeyPair Y + val senderPublicKey = keyManagementRepository.generateKeyPair() val contact = chatStorage.getContact(peerAccount) - val publicKeyString = contact.public_key // TODO: What about camelCase? - val receiverPublicKey = PublicKey(publicKeyString) // KeyPair X + val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(senderPublicKey, contact.publicKey) + val inviteTopic = keyManagementRepository.getTopicFromKey(contact.publicKey) + keyManagementRepository.setKeyAgreement(inviteTopic, senderPublicKey, contact.publicKey) - val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(senderPublicKey, receiverPublicKey) // SymKey I - val inviteTopic = keyManagementRepository.getTopicFromKey(receiverPublicKey) // Topic I - keyManagementRepository.setKeyAgreement(inviteTopic, senderPublicKey, receiverPublicKey) - - val participants = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = receiverPublicKey) + val participants = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = contact.publicKey) val inviteParams = ChatParams.InviteParams(invite.message, invite.accountId.value, senderPublicKey.keyAsHex, invite.signature) val payload = ChatRpc.ChatInvite(id = generateId(), params = inviteParams) val acceptTopic = keyManagementRepository.getTopicFromKey(symmetricKey) @@ -147,66 +133,38 @@ internal class ChatEngine( onFailure(error) } - private fun onInviteResponse(wcResponse: WCResponse) { - when (val response = wcResponse.response) { - is JsonRpcResponse.JsonRpcError -> { - Logger.log("Chat invite was rejected") - scope.launch { - _events.emit(EngineDO.Events.OnReject(wcResponse.topic.value)) - } - } - is JsonRpcResponse.JsonRpcResult -> { - Logger.log("Chat invite was accepted") - val acceptParams = response.result as ChatParams.AcceptanceParams - val pubKeyZ = PublicKey(acceptParams.publicKey) // PubKey Z - val (selfPubKey, _) = keyManagementRepository.getKeyAgreement(wcResponse.topic) - val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(selfPubKey, pubKeyZ) // SymKey T - val threadTopic = keyManagementRepository.getTopicFromKey(symmetricKey) - //todo: add thread to storage - keyManagementRepository.setKey(symmetricKey, threadTopic.value) - jsonRpcInteractor.subscribe(threadTopic) - scope.launch { - _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) - } - } - } - } - - private fun onInviteRequest(wcRequest: WCRequest, params: ChatParams.InviteParams) { - - inviteRequestMap[wcRequest.id] = wcRequest // todo when to remove it? - scope.launch { - _events.emit( - EngineDO.Events.OnInvite( - wcRequest.id, - EngineDO.Invite(AccountId(params.account), params.message, params.signature) - ) + internal fun addContact(accountIdWithPublicKeyVO: AccountIdWithPublicKey, onFailure: (Throwable) -> Unit) = try { + if (chatStorage.doesContactNotExists(accountIdWithPublicKeyVO.accountId)) { + chatStorage.createContact(EngineDO.Contact(accountIdWithPublicKeyVO, accountIdWithPublicKeyVO.accountId.value)) + } else { + chatStorage.updateContact( + accountIdWithPublicKeyVO.accountId, + accountIdWithPublicKeyVO.publicKey, + accountIdWithPublicKeyVO.accountId.value ) } - - //TODO: Add adding invites to storage. For MVP we will use only emitted event. + } catch (error: Exception) { + onFailure(error) } - internal fun accept(inviteId: Long, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) = try { val request = inviteRequestMap[inviteId] ?: throw GenericException("No request for inviteId") - val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) // PubKey Y + val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) inviteRequestMap.remove(inviteId) - val invitePublicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT)// PubKey X - val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) // SymKey I - val acceptTopic = keyManagementRepository.getTopicFromKey(symmetricKey) // Topic T + val invitePublicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT) + val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) + val acceptTopic = keyManagementRepository.getTopicFromKey(symmetricKey) keyManagementRepository.setKey(symmetricKey, acceptTopic.value) - val publicKey = keyManagementRepository.generateKeyPair() // KeyPair Z - + val publicKey = keyManagementRepository.generateKeyPair() val acceptanceParams = ChatParams.AcceptanceParams(publicKey.keyAsHex) val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(DAY_IN_SECONDS)) jsonRpcInteractor.respondWithParams(request.copy(topic = acceptTopic), acceptanceParams, irnParams, EnvelopeType.ZERO) - val threadSymmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(publicKey, senderPublicKey) // SymKey T - val threadTopic = keyManagementRepository.getTopicFromKey(threadSymmetricKey) // Topic T + val threadSymmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(publicKey, senderPublicKey) + val threadTopic = keyManagementRepository.getTopicFromKey(threadSymmetricKey) keyManagementRepository.setKey(threadSymmetricKey, threadTopic.value) jsonRpcInteractor.subscribe(threadTopic) onSuccess(threadTopic.value) @@ -216,12 +174,12 @@ internal class ChatEngine( internal fun reject(inviteId: Long, onFailure: (Throwable) -> Unit) { val request = inviteRequestMap[inviteId] ?: throw GenericException("No request for inviteId") - val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) // PubKey Y + val senderPublicKey = PublicKey((request.params as ChatParams.InviteParams).publicKey) inviteRequestMap.remove(inviteId) - val invitePublicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT)// PubKey X - val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) // SymKey I - val rejectTopic = keyManagementRepository.getTopicFromKey(symmetricKey) // Topic T + val invitePublicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT) + val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(invitePublicKey, senderPublicKey) + val rejectTopic = keyManagementRepository.getTopicFromKey(symmetricKey) keyManagementRepository.setKey(symmetricKey, rejectTopic.value) val irnParams = IrnParams(Tags.CHAT_INVITE_RESPONSE, Ttl(DAY_IN_SECONDS)) @@ -229,14 +187,12 @@ internal class ChatEngine( request.copy(topic = rejectTopic), PeerError.UserRejectedInvitation("Invitation rejected by a user"), irnParams - ) - { throwable -> onFailure(throwable) } + ) { throwable -> onFailure(throwable) } } internal fun message(topic: String, sendMessage: EngineDO.SendMessage, onFailure: (Throwable) -> Unit) { //todo resolve AUTHOR_ACCOUNT from thread storage by topic - val messageParams = - ChatParams.MessageParams(sendMessage.message, sendMessage.author.value, System.currentTimeMillis(), sendMessage.media) + val messageParams = ChatParams.MessageParams(sendMessage.message, sendMessage.author.value, System.currentTimeMillis(), sendMessage.media) val payload = ChatRpc.ChatMessage(id = generateId(), params = messageParams) val irnParams = IrnParams(Tags.CHAT_MESSAGE, Ttl(DAY_IN_SECONDS), true) @@ -248,19 +204,6 @@ internal class ChatEngine( }) } - private fun onMessage(wcRequest: WCRequest, params: ChatParams.MessageParams) { - scope.launch { - _events.emit( - EngineDO.Events.OnMessage( - wcRequest.topic.value, - EngineDO.Message(params.message, AccountId(params.authorAccount), params.timestamp, params.media) - ) - ) - } - - //TODO: Add adding messages to storage. For MVP we will use only emitted event. - } - internal fun leave(topic: String, onFailure: (Throwable) -> Unit) { //todo: correct define params val leaveParams = ChatParams.LeaveParams() @@ -290,6 +233,23 @@ internal class ChatEngine( } } + private fun onInviteRequest(wcRequest: WCRequest, params: ChatParams.InviteParams) { + inviteRequestMap[wcRequest.id] = wcRequest + scope.launch { + val invite = EngineDO.Invite(AccountId(params.account), params.message, params.signature) + _events.emit(EngineDO.Events.OnInvite(wcRequest.id, invite)) + } + //TODO: Add adding invites to storage. For MVP we will use only emitted event. + } + + private fun onMessage(wcRequest: WCRequest, params: ChatParams.MessageParams) { + scope.launch { + val message = EngineDO.Message(params.message, AccountId(params.authorAccount), params.timestamp, params.media) + _events.emit(EngineDO.Events.OnMessage(wcRequest.topic.value, message)) + } + //TODO: Add adding messages to storage. For MVP we will use only emitted event. + } + private fun collectPeerResponses() { scope.launch { jsonRpcInteractor.peerResponse.collect { response -> @@ -300,17 +260,43 @@ internal class ChatEngine( } } - internal fun addContact(accountIdWithPublicKeyVO: AccountIdWithPublicKey, onFailure: (Throwable) -> Unit) = try { - if (chatStorage.doesContactNotExists(accountIdWithPublicKeyVO.accountId)) { - chatStorage.createContact(EngineDO.Contact(accountIdWithPublicKeyVO, accountIdWithPublicKeyVO.accountId.value)) - } else { - chatStorage.updateContact( - accountIdWithPublicKeyVO.accountId, - accountIdWithPublicKeyVO.publicKey, - accountIdWithPublicKeyVO.accountId.value - ) + private fun onInviteResponse(wcResponse: WCResponse) { + when (val response = wcResponse.response) { + is JsonRpcResponse.JsonRpcError -> { + Logger.log("Chat invite was rejected") + scope.launch { _events.emit(EngineDO.Events.OnReject(wcResponse.topic.value)) } + } + is JsonRpcResponse.JsonRpcResult -> { + Logger.log("Chat invite was accepted") + val acceptParams = response.result as ChatParams.AcceptanceParams + val pubKeyZ = PublicKey(acceptParams.publicKey) + val (selfPubKey, _) = keyManagementRepository.getKeyAgreement(wcResponse.topic) + val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(selfPubKey, pubKeyZ) + val threadTopic = keyManagementRepository.getTopicFromKey(symmetricKey) + keyManagementRepository.setKey(symmetricKey, threadTopic.value) + jsonRpcInteractor.subscribe(threadTopic) + scope.launch { _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) } + } + } + } + + private fun resubscribeToInviteTopic() { + jsonRpcInteractor.isConnectionAvailable + .onEach { isAvailable -> _events.emit(ConnectionState(isAvailable)) } + .filter { isAvailable: Boolean -> isAvailable } + .onEach { coroutineScope { launch(Dispatchers.IO) { trySubscribeToInviteTopic() } } } + .launchIn(scope) + } + + private fun trySubscribeToInviteTopic() { + try { + val publicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT) + val topic = keyManagementRepository.getTopicFromKey(publicKey) + jsonRpcInteractor.subscribe(topic) + Logger.log("Listening for invite on: $topic, pubKey X:$publicKey") + } catch (error: Exception) { + Logger.log(error) // It will log if run before registerAccount() + //TODO: Create exception if there is no key created } - } catch (error: Exception) { - onFailure(error) } } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt index 1af4765335..75ad1a718d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt @@ -2,12 +2,13 @@ package com.walletconnect.chat.engine.model +import com.walletconnect.android.impl.common.model.type.EngineEvent import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.common.model.Media internal sealed class EngineDO { - data class Error(val throwable: Throwable) : EngineDO() // TODO: Should this be extracted to core for easier error handling? + data class Error(val throwable: Throwable) : EngineDO() data class Invite( val accountId: AccountId, @@ -39,7 +40,7 @@ internal sealed class EngineDO { val media: Media?, ) : EngineDO() - sealed class Events : EngineDO() { + sealed class Events : EngineDO(), EngineEvent { data class OnInvite(val id: Long, val invite: Invite) : Events() data class OnJoined(val topic: String) : Events() data class OnReject(val topic: String) : Events() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt index 1aaf7f394c..f52f9e0762 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt @@ -3,8 +3,8 @@ package com.walletconnect.chat.storage import com.walletconnect.chat.common.model.AccountId +import com.walletconnect.chat.common.model.Contact import com.walletconnect.chat.engine.model.EngineDO -import com.walletconnect.chat.storage.data.dao.Contacts import com.walletconnect.chat.storage.data.dao.ContactsQueries import com.walletconnect.foundation.common.model.PublicKey @@ -15,18 +15,23 @@ internal class ChatStorageRepository(private val contactsQueries: ContactsQuerie contactsQueries.doesContactNotExists(accountIdVO.value).executeAsOne() @JvmSynthetic - internal fun createContact(contact: EngineDO.Contact) = contactsQueries.insertOrAbortContact( - contact.accountIdWithPublicKey.accountId.value, - contact.accountIdWithPublicKey.publicKey.keyAsHex, - contact.displayName - ) + internal fun createContact(contact: EngineDO.Contact) = + contactsQueries.insertOrAbortContact( + contact.accountIdWithPublicKey.accountId.value, + contact.accountIdWithPublicKey.publicKey.keyAsHex, + contact.displayName + ) @JvmSynthetic - internal fun getContact(accountId: AccountId): Contacts = contactsQueries.getContact(accountId.value).executeAsOne() + internal fun getContact(accountId: AccountId): Contact = + contactsQueries.getContact(accountId.value, mapper = ::mapContactDaoToContact).executeAsOne() @JvmSynthetic internal fun updateContact(accountId: AccountId, publicKey: PublicKey, displayName: String) { contactsQueries.updateContactPublicKey(publicKey.keyAsHex, accountId.value) contactsQueries.updateContactDisplayName(displayName, accountId.value) } + + private fun mapContactDaoToContact(account_id: String, public_key: String, display_name: String): Contact = + Contact(AccountId(account_id), PublicKey(public_key), display_name) } \ No newline at end of file diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/model/EngineDO.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/model/EngineDO.kt index dd240a2258..34999b7977 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/model/EngineDO.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/model/EngineDO.kt @@ -93,12 +93,6 @@ internal sealed class EngineDO { data class Error(val errorMessage: String) : SettledSessionResponse() } - //todo: remove - internal sealed class SessionUpdateAccountsResponse : EngineDO(), EngineEvent { - data class Result(val topic: Topic, val accounts: List) : SessionUpdateAccountsResponse() - data class Error(val errorMessage: String) : SessionUpdateAccountsResponse() - } - internal sealed class SessionUpdateNamespacesResponse : EngineDO(), EngineEvent { data class Result(val topic: Topic, val namespaces: Map) : SessionUpdateNamespacesResponse() data class Error(val errorMessage: String) : SessionUpdateNamespacesResponse() From c53c21f2f52725b3de5db5ea443bea70e28666ed Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 27 Oct 2022 16:48:42 +0200 Subject: [PATCH 20/30] Add ping and chat leave methods --- .../chat/client/ChatInterface.kt | 2 +- .../walletconnect/chat/client/ChatProtocol.kt | 4 +- .../chat/engine/domain/ChatEngine.kt | 92 +++++++++++++++---- .../chat/storage/ChatStorageRepository.kt | 2 +- .../sign/engine/domain/SignEngine.kt | 51 +++++----- 5 files changed, 105 insertions(+), 46 deletions(-) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt index b8c8af9454..c8610716f7 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt @@ -20,7 +20,7 @@ interface ChatInterface { fun accept(accept: Chat.Params.Accept, onSuccess: (String) -> Unit, onError: (Chat.Model.Error) -> Unit) fun reject(reject: Chat.Params.Reject, onError: (Chat.Model.Error) -> Unit) fun message(message: Chat.Params.Message, onError: (Chat.Model.Error) -> Unit) - fun ping(ping: Chat.Params.Ping, onError: (Chat.Model.Error) -> Unit) + fun ping(ping: Chat.Params.Ping, onSuccess: (String) -> Unit, onError: (Chat.Model.Error) -> Unit) fun leave(leave: Chat.Params.Leave, onError: (Chat.Model.Error) -> Unit) fun addContact(addContact: Chat.Params.AddContact, onError: (Chat.Model.Error) -> Unit) fun getInvites(getInvites: Chat.Params.GetInvites): Map diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index be7c1e9d14..b4aa31e1c7 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -113,10 +113,10 @@ internal class ChatProtocol : ChatInterface { } @Throws(IllegalStateException::class) - override fun ping(ping: Chat.Params.Ping, onError: (Chat.Model.Error) -> Unit) { + override fun ping(ping: Chat.Params.Ping, onSuccess: (String) -> Unit, onError: (Chat.Model.Error) -> Unit) { checkEngineInitialization() - chatEngine.ping(ping.topic) { error -> onError(Chat.Model.Error(error)) } + chatEngine.ping(ping.topic, onSuccess = { topic -> onSuccess(topic) }, { error -> onError(Chat.Model.Error(error)) }) } @Throws(IllegalStateException::class) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 3683db66a1..243dbedaef 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -4,10 +4,7 @@ package com.walletconnect.chat.engine.domain import com.walletconnect.android.impl.common.model.ConnectionState import com.walletconnect.android.impl.common.model.type.EngineEvent -import com.walletconnect.android.impl.utils.DAY_IN_SECONDS -import com.walletconnect.android.impl.utils.Logger -import com.walletconnect.android.impl.utils.SELF_INVITE_PUBLIC_KEY_CONTEXT -import com.walletconnect.android.impl.utils.SELF_PARTICIPANT_CONTEXT +import com.walletconnect.android.impl.utils.* import com.walletconnect.android.internal.common.JsonRpcResponse import com.walletconnect.android.internal.common.crypto.KeyManagementRepository import com.walletconnect.android.internal.common.exception.GenericException @@ -28,11 +25,8 @@ import com.walletconnect.foundation.common.model.PublicKey import com.walletconnect.foundation.common.model.Topic import com.walletconnect.foundation.common.model.Ttl import com.walletconnect.util.generateId -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import kotlinx.coroutines.supervisorScope internal class ChatEngine( private val registerAccountUseCase: RegisterAccountUseCase, @@ -205,21 +199,56 @@ internal class ChatEngine( } internal fun leave(topic: String, onFailure: (Throwable) -> Unit) { - //todo: correct define params - val leaveParams = ChatParams.LeaveParams() - val payload = ChatRpc.ChatLeave(id = generateId(), params = leaveParams) + val payload = ChatRpc.ChatLeave(id = generateId(), params = ChatParams.LeaveParams()) val irnParams = IrnParams(Tags.CHAT_LEAVE, Ttl(DAY_IN_SECONDS), true) jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, payload, EnvelopeType.ZERO, - onSuccess = { Logger.log("Chat message sent successfully") }, + onSuccess = { Logger.log("Chat leave sent successfully") }, onFailure = { throwable -> - Logger.log("Chat message error: $throwable") + Logger.log("Chat leave error: $throwable") onFailure(throwable) }) } - internal fun ping(topic: String, onFailure: (Throwable) -> Unit) { - //TODO + internal fun ping(topic: String, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { + val pingPayload = ChatRpc.ChatPing(id = generateId(), params = ChatParams.PingParams()) + val irnParams = IrnParams(Tags.CHAT_PING, Ttl(THIRTY_SECONDS)) + + jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, pingPayload, + onSuccess = { pingSuccess(pingPayload, onSuccess, topic, onFailure) }, + onFailure = { error -> + Logger.log("Ping sent error: $error") + onFailure(error) + }) + } + + private fun pingSuccess( + pingPayload: ChatRpc.ChatPing, + onSuccess: (String) -> Unit, + topic: String, + onFailure: (Throwable) -> Unit + ) { + Logger.log("Ping sent successfully") + scope.launch { + try { + withTimeout(THIRTY_SECONDS_TIMEOUT) { + collectResponse(pingPayload.id) { result -> + cancel() + result.fold( + onSuccess = { + Logger.log("Ping peer response success") + onSuccess(topic) + }, + onFailure = { error -> + Logger.log("Ping peer response error: $error") + onFailure(error) + }) + } + } + } catch (e: TimeoutCancellationException) { + onFailure(e) + } + } } private fun collectJsonRpcRequests() { @@ -228,6 +257,8 @@ internal class ChatEngine( when (val params = request.params) { is ChatParams.InviteParams -> onInviteRequest(request, params) is ChatParams.MessageParams -> onMessage(request, params) + is ChatParams.LeaveParams -> onLeft(request) + is ChatParams.PingParams -> onPong(request) } } } @@ -239,7 +270,7 @@ internal class ChatEngine( val invite = EngineDO.Invite(AccountId(params.account), params.message, params.signature) _events.emit(EngineDO.Events.OnInvite(wcRequest.id, invite)) } - //TODO: Add adding invites to storage. For MVP we will use only emitted event. + //TODO: Add adding invites to storage. For Alpha we will use only emitted event. } private fun onMessage(wcRequest: WCRequest, params: ChatParams.MessageParams) { @@ -247,7 +278,18 @@ internal class ChatEngine( val message = EngineDO.Message(params.message, AccountId(params.authorAccount), params.timestamp, params.media) _events.emit(EngineDO.Events.OnMessage(wcRequest.topic.value, message)) } - //TODO: Add adding messages to storage. For MVP we will use only emitted event. + //TODO: Add adding messages to storage. For Alpha we will use only emitted event. + } + + private fun onLeft(request: WCRequest) { + scope.launch { + _events.emit(EngineDO.Events.OnLeft(request.topic.value)) + } + //TODO: Add removing threads from storage. For Alpha we will use only emitted event. + } + + private fun onPong(request: WCRequest) { + jsonRpcInteractor.respondWithSuccess(request, IrnParams(Tags.SESSION_PING_RESPONSE, Ttl(THIRTY_SECONDS))) } private fun collectPeerResponses() { @@ -275,6 +317,7 @@ internal class ChatEngine( val threadTopic = keyManagementRepository.getTopicFromKey(symmetricKey) keyManagementRepository.setKey(symmetricKey, threadTopic.value) jsonRpcInteractor.subscribe(threadTopic) + //TODO: Add adding thread to storage. For Alpha we will use only emitted event. scope.launch { _events.emit(EngineDO.Events.OnJoined(threadTopic.value)) } } } @@ -299,4 +342,19 @@ internal class ChatEngine( //TODO: Create exception if there is no key created } } + + private suspend fun collectResponse(id: Long, onResponse: (Result) -> Unit = {}) { + jsonRpcInteractor.peerResponse + .filter { response -> response.response.id == id } + .collect { response -> + when (val result = response.response) { + is JsonRpcResponse.JsonRpcResult -> onResponse(Result.success(result)) + is JsonRpcResponse.JsonRpcError -> onResponse(Result.failure(Throwable(result.errorMessage))) + } + } + } + + companion object { + const val THIRTY_SECONDS_TIMEOUT: Long = 30000L + } } \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt index f52f9e0762..3fa49f7524 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/storage/ChatStorageRepository.kt @@ -24,7 +24,7 @@ internal class ChatStorageRepository(private val contactsQueries: ContactsQuerie @JvmSynthetic internal fun getContact(accountId: AccountId): Contact = - contactsQueries.getContact(accountId.value, mapper = ::mapContactDaoToContact).executeAsOne() + contactsQueries.getContact(accountId.value, mapper = ::mapContactDaoToContact).executeAsOne() @JvmSynthetic internal fun updateContact(accountId: AccountId, publicKey: PublicKey, displayName: String) { diff --git a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt index 4f65e8236b..b54bb74bc0 100644 --- a/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt +++ b/sign/sdk/src/main/kotlin/com/walletconnect/sign/engine/domain/SignEngine.kt @@ -301,33 +301,32 @@ internal class SignEngine( val irnParams = IrnParams(Tags.SESSION_PING, Ttl(THIRTY_SECONDS)) jsonRpcInteractor.publishJsonRpcRequest(Topic(topic), irnParams, pingPayload, - onSuccess = { - Logger.log("Ping sent successfully") - scope.launch { - try { - withTimeout(THIRTY_SECONDS_TIMEOUT) { - collectResponse(pingPayload.id) { result -> - cancel() - result.fold( - onSuccess = { - Logger.log("Ping peer response success") - onSuccess(topic) - }, - onFailure = { error -> - Logger.log("Ping peer response error: $error") - onFailure(error) - }) + onSuccess = { + Logger.log("Ping sent successfully") + scope.launch { + try { + withTimeout(THIRTY_SECONDS_TIMEOUT) { + collectResponse(pingPayload.id) { result -> + cancel() + result.fold( + onSuccess = { + Logger.log("Ping peer response success") + onSuccess(topic) + }, + onFailure = { error -> + Logger.log("Ping peer response error: $error") + onFailure(error) + }) + } } + } catch (e: TimeoutCancellationException) { + onFailure(e) } - } catch (e: TimeoutCancellationException) { - onFailure(e) } - } - }, - onFailure = { error -> - - Logger.log("Ping sent error: $error") -onFailure(error) + }, + onFailure = { error -> + Logger.log("Ping sent error: $error") + onFailure(error) }) } else { pairingInterface.ping(Core.Params.Ping(topic), object : Core.Listeners.PairingPing { @@ -576,7 +575,9 @@ onFailure(error) return } - val (sessionNamespaces: Map, sessionPeerAppMetaData: AppMetaData?) = sessionStorageRepository.getSessionWithoutMetadataByTopic(request.topic).run { + val (sessionNamespaces: Map, sessionPeerAppMetaData: AppMetaData?) = sessionStorageRepository.getSessionWithoutMetadataByTopic( + request.topic + ).run { val peerAppMetaData = metadataStorageRepository.getByTopicAndType(this.topic, AppMetaDataType.PEER) this.namespaces to peerAppMetaData } From ca20a71e41eab5819e09ecda58e5838cbc24fed1 Mon Sep 17 00:00:00 2001 From: kubel Date: Thu, 27 Oct 2022 17:06:30 +0200 Subject: [PATCH 21/30] Address PR comments --- .../chatsample/domain/ChatDelegate.kt | 5 +++++ .../walletconnect/chat/client/ChatInterface.kt | 1 + .../walletconnect/chat/client/ChatProtocol.kt | 3 +++ .../chat/client/mapper/ClientMapper.kt | 4 ++++ .../chat/engine/domain/ChatEngine.kt | 17 +++++++++++++---- .../walletconnect/chat/engine/model/EngineDO.kt | 3 ++- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt index b96feceb6b..54d1c8af1e 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt @@ -1,5 +1,6 @@ package com.walletconnect.chatsample.domain +import android.util.Log import com.walletconnect.chat.client.Chat import com.walletconnect.chat.client.ChatClient import kotlinx.coroutines.* @@ -39,6 +40,10 @@ object ChatDelegate : ChatClient.ChatDelegate { TODO("Not yet implemented") } + override fun onError(error: Chat.Model.Error) { + Log.e("ChatDelegate", "Internal error: $error") + } + @OptIn(ExperimentalCoroutinesApi::class) private fun clearCache() { _wcEventModels.resetReplayCache() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt index e313252940..7863e0aff0 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatInterface.kt @@ -7,6 +7,7 @@ interface ChatInterface { fun onJoined(onJoined: Chat.Model.Events.OnJoined) fun onMessage(onMessage: Chat.Model.Events.OnMessage) fun onLeft(onLeft: Chat.Model.Events.OnLeft) + fun onError(error: Chat.Model.Error) } fun setChatDelegate(delegate: ChatDelegate) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index fa5857791d..bb4ffa7101 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -1,10 +1,12 @@ package com.walletconnect.chat.client +import com.walletconnect.android.impl.common.SDKError import com.walletconnect.android.impl.di.cryptoModule import com.walletconnect.android.impl.utils.Logger import com.walletconnect.android.internal.common.scope import com.walletconnect.android.internal.common.wcKoinApp import com.walletconnect.chat.client.mapper.toClient +import com.walletconnect.chat.client.mapper.toClientError import com.walletconnect.chat.client.mapper.toEngineDO import com.walletconnect.chat.client.mapper.toCommon import com.walletconnect.chat.common.model.AccountId @@ -52,6 +54,7 @@ internal class ChatProtocol : ChatInterface { is EngineDO.Events.OnJoined -> delegate.onJoined(event.toClient()) is EngineDO.Events.OnMessage -> delegate.onMessage(event.toClient()) is EngineDO.Events.OnLeft -> Unit + is SDKError -> delegate.onError(event.toClientError()) } } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt index de3dda4468..100fb051ae 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt @@ -2,6 +2,7 @@ package com.walletconnect.chat.client.mapper +import com.walletconnect.android.impl.common.SDKError import com.walletconnect.chat.client.Chat import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.Media @@ -63,3 +64,6 @@ internal fun EngineDO.Message.toClient(): Chat.Model.Message { return Chat.Model.Message(message, authorAccountId.toClient(), timestamp, media?.toClient()) } +@JvmSynthetic +internal fun SDKError.toClientError(): Chat.Model.Error = + Chat.Model.Error(this.exception) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index dd0750aba7..763719c9ed 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -2,6 +2,8 @@ package com.walletconnect.chat.engine.domain +import com.walletconnect.android.impl.common.SDKError +import com.walletconnect.android.impl.common.model.type.EngineEvent import com.walletconnect.android.impl.utils.DAY_IN_SECONDS import com.walletconnect.android.impl.utils.Logger import com.walletconnect.android.impl.utils.SELF_INVITE_PUBLIC_KEY_CONTEXT @@ -36,8 +38,8 @@ internal class ChatEngine( private val jsonRpcInteractor: JsonRpcInteractorInterface, private val chatStorage: ChatStorageRepository ) { - private val _events: MutableSharedFlow = MutableSharedFlow() - val events: SharedFlow = _events.asSharedFlow() + private val _events: MutableSharedFlow = MutableSharedFlow() + val events: SharedFlow = _events.asSharedFlow() private val inviteRequestMap: MutableMap = mutableMapOf() init { @@ -56,7 +58,13 @@ internal class ChatEngine( } } .launchIn(scope) + collectInternalErrors() + } + private fun collectInternalErrors() { + jsonRpcInteractor.internalErrors + .onEach { exception -> _events.emit(SDKError(exception)) } + .launchIn(scope) } internal fun resolveAccount(accountId: AccountId, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { @@ -106,8 +114,9 @@ internal class ChatEngine( jsonRpcInteractor.subscribe(topic) Logger.log("Listening for invite on: $topic, pubKey X:$publicKey") } catch (error: Exception) { - Logger.log(error) // It will log if run before registerAccount() - //TODO: Create exception if there is no key created + scope.launch { + _events.emit(SDKError(InternalError(error))) + } } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt index 097bb9aea5..99b507bdc9 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt @@ -2,6 +2,7 @@ package com.walletconnect.chat.engine.model +import com.walletconnect.android.impl.common.model.type.EngineEvent import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey import com.walletconnect.chat.common.model.Media @@ -39,7 +40,7 @@ internal sealed class EngineDO { val media: Media?, ) : EngineDO() - sealed class Events : EngineDO() { + sealed class Events : EngineDO(), EngineEvent { data class OnInvite(val id: Long, val invite: Invite) : Events() data class OnJoined(val topic: String) : Events() From a9a2d6642d9290019a1c95e733ac6990dd542217 Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 08:58:58 +0200 Subject: [PATCH 22/30] Update chat ReadMe.md --- ReadMe.md | 4 ++-- chat/ReadMe.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 chat/ReadMe.md diff --git a/ReadMe.md b/ReadMe.md index 8025350855..c170d45f92 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -10,7 +10,7 @@ WalletConnect v2 protocols for Android applications. * [Core SDK](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/androidCore) * [Sign SDK](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/sign) * [Auth SDK](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/auth) -* [Chat SDK] TBD +* [Chat SDK](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/chat) ## License -WalletConnect v2 is released under the Apache 2.0 license. [See LICENSE](https://github.com/WalletConnect/WalletConnectKotlinV2/blob/feature/develop/LICENSE) for details. +WalletConnect v2 is released under the Apache 2.0 license. [See LICENSE](https://github.com/WalletConnect/WalletConnectKotlinV2/blob/feature/develop/LICENSE) for details. \ No newline at end of file diff --git a/chat/ReadMe.md b/chat/ReadMe.md new file mode 100644 index 0000000000..6eafc9b04e --- /dev/null +++ b/chat/ReadMe.md @@ -0,0 +1,42 @@ +# **WalletConnect Chat - Kotlin** + +Kotlin implementation of WalletConnect v2 Chat protocol for Android applications. + +![Maven Central](https://img.shields.io/maven-central/v/com.walletconnect/chat) + +## Requirements + +* Android min SDK 23 +* Java 11 + +## Documentation and usage + +* [Installation guide](https://docs.walletconnect.com/2.0/kotlin/chat/installation) +* [Usage](https://docs.walletconnect.com/2.0/kotlin/chat/usage) +* [Protocol specification](https://docs.walletconnect.com/2.0/specs/chat/) + +  + +## Installation + +root/build.gradle.kts: + +```gradle +allprojects { + repositories { + mavenCentral() + } +} +``` + +app/build.gradle.kts + +```gradle +implementation("com.walletconnect:chat:release_version") +``` + +  + +## Sample apps + +* For sample app run `chat sample module` \ No newline at end of file From bed6d94f5cdd08206b5a4cadb4a16acb050f2293 Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 09:01:46 +0200 Subject: [PATCH 23/30] Clean up --- .../android/impl/json_rpc/domain/JsonRpcInteractor.kt | 2 -- .../kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt | 1 - 2 files changed, 3 deletions(-) diff --git a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt index b8075ca589..034b84bd4f 100644 --- a/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt +++ b/androidCore/impl/src/main/kotlin/com/walletconnect/android/impl/json_rpc/domain/JsonRpcInteractor.kt @@ -193,8 +193,6 @@ internal class JsonRpcInteractor( val topic = Topic(relayRequest.subscriptionTopic) val message = chaChaPolyCodec.decrypt(topic, relayRequest.message) - Logger.error("Peer message: $message") - Pair(message, topic) }.collect { (decryptedMessage, topic) -> manageSubscriptions(decryptedMessage, topic) } } diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt index 521a0eecb5..777ed2b06a 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/domain/ChatDelegate.kt @@ -25,7 +25,6 @@ object ChatDelegate : ChatClient.ChatDelegate { override fun onJoined(onJoined: Chat.Model.Events.OnJoined) { scope.launch { - Log.e("kobe", "onJoined DELEGATE") _wcEventModels.emit(onJoined) clearCache() } From 6ebd54b4a6369a38ed0b4fc42125fb46999a39b7 Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 12:25:00 +0200 Subject: [PATCH 24/30] Improve register to create a pubKey only when empty key store --- .../chatsample/ChatSampleApplication.kt | 2 +- .../ui/shared/ChatSharedViewModel.kt | 57 ++++++++------- .../chatsample/ui/threads/ThreadsFragment.kt | 14 +--- .../com/walletconnect/chat/client/Chat.kt | 3 +- .../walletconnect/chat/client/ChatProtocol.kt | 21 +++--- .../chat/client/mapper/ClientMapper.kt | 5 +- .../chat/engine/domain/ChatEngine.kt | 73 +++++++++++-------- .../chat/engine/model/EngineDO.kt | 1 + 8 files changed, 91 insertions(+), 85 deletions(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt index 1ecb654b54..17a42019f2 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ChatSampleApplication.kt @@ -25,7 +25,7 @@ class ChatSampleApplication : Application() { val serverUri = "wss://$WALLET_CONNECT_PROD_RELAY_URL?projectId=${BuildConfig.PROJECT_ID}" CoreClient.initialize(relayServerUrl = serverUri, connectionType = ConnectionType.AUTOMATIC, application = this, metaData = metadata) - ChatClient.initialize(Chat.Params.Init(CoreClient, "https://keys.walletconnect.com")) { error -> + ChatClient.initialize(Chat.Params.Init(CoreClient)) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } } diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index ea9bb007a9..d26474b932 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -32,7 +32,7 @@ class ChatSharedViewModel : ViewModel() { fun getLastMessage(peerName: String) = listOfMessages.last { it.peerName == peerName } val emittedEvents: Flow = ChatDelegate.wcEventModels.map { walletEvent: Chat.Model.Events -> - Log.d(tag(this), walletEvent.toString()) + Log.d(TAG, walletEvent.toString()) when (walletEvent) { is Chat.Model.Events.OnInvite -> walletEvent.toChatSharedEvents().also { onInvite(it) } is Chat.Model.Events.OnJoined -> walletEvent.toChatSharedEvents().also { onJoined(it) } @@ -42,31 +42,34 @@ class ChatSharedViewModel : ViewModel() { } }.shareIn(viewModelScope, SharingStarted.WhileSubscribed()) - fun register(listener: Chat.Listeners.Register) { - ChatClient.register(Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)), listener) + fun register() { + val register = Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)) + ChatClient.register(register, object : Chat.Listeners.Register { + override fun onError(error: Chat.Model.Error) { + Log.e(TAG, "Register error: ${error.throwable.stackTraceToString()}") + } + + override fun onSuccess(publicKey: String) { + Log.d(TAG, "Registered successfully") + } + }) } fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { ChatClient.resolve(Chat.Params.Resolve(Chat.Model.AccountId(contact)), object : Chat.Listeners.Resolve { override fun onError(error: Chat.Model.Error) { - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) - } + Log.e(TAG, error.throwable.stackTraceToString()) } override fun onSuccess(publicKey: String) { - ChatClient.addContact(Chat.Params.AddContact(Chat.Model.AccountId(contact), publicKey)) { error -> - Log.e(tag(this), error.throwable.stackTraceToString()) - } + val inviteModel = Chat.Model.Invite(Chat.Model.AccountId(SELF_ACCOUNT), openingMessage, publicKey) + val invite = Chat.Params.Invite(Chat.Model.AccountId(contact), inviteModel) + ChatClient.invite(invite) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } - val inviteModel = Chat.Model.Invite(Chat.Model.AccountId(SELF_ACCOUNT), openingMessage) - Chat.Params.Invite(Chat.Model.AccountId(contact), inviteModel).also { invite -> - ChatClient.invite(invite) { error -> Log.e(tag(this), error.throwable.stackTraceToString()) } - } runBlocking(Dispatchers.Main) { currentInvite = inviteModel whoWasInvitedContact = contact - Log.e(tag(this), "invite: $currentInvite") + Log.e(TAG, "invite: $currentInvite") listOfMessages.add(MessageUI(contact, inviteModel.message, System.currentTimeMillis(), contact)) _listOfMessagesStateFlow.value = listOfMessages.toList() afterInviteSent() @@ -78,33 +81,34 @@ class ChatSharedViewModel : ViewModel() { fun acceptInvitation(chatUI: ChatUI) { chatUI.id?.let { id -> ChatClient.accept(Chat.Params.Accept(id), onSuccess = { threadTopic -> updateThread(threadTopic) }, { error -> - Log.e(tag(this), error.throwable.stackTraceToString()) + Log.e(TAG, error.throwable.stackTraceToString()) }) updateInvites(chatUI.id) - } ?: Log.e(tag(this), "Unable to find id on accpet invitation: $chatUI") + } ?: Log.e(TAG, "Unable to find id on accpet invitation: $chatUI") } fun rejectInvitation(id: Long?) { id?.let { val reject = Chat.Params.Reject(it) - ChatClient.reject(reject) { error -> Log.e(tag(this), "Unable to find reject invitation: $error") } + ChatClient.reject(reject) { error -> Log.e(TAG, "Unable to find reject invitation: $error") } updateInvites(id) - } ?: Log.e(tag(this), "Unable to find id on reject invitation: $id") + } ?: Log.e(TAG, "Unable to find id on reject invitation: $id") } fun sendMessage(message: String, peerName: String) { - Log.e(tag(this), "sendMessage: $peerName") + Log.e(TAG, "sendMessage: $peerName") val (userName, topic) = userNameToTopicMap.entries.single { entry -> entry.key == peerName } listOfMessages.add(MessageUI(userName, message, System.currentTimeMillis(), SELF_ACCOUNT)) _listOfMessagesStateFlow.value = listOfMessages.toList() + ChatClient.message(Chat.Params.Message(topic, Chat.Model.AccountId(SELF_ACCOUNT), message)) { error -> - Log.e(tag(this), error.throwable.stackTraceToString()) + Log.e(TAG, error.throwable.stackTraceToString()) } } private fun onInvite(event: ChatSharedEvents.OnInvite) { - Log.d(tag(this), "Invited: ${event.invite.message}") + Log.d(TAG, "Invited: ${event.invite.message}") val contact = event.invite.account.value currentInvite = event.invite @@ -116,19 +120,19 @@ class ChatSharedViewModel : ViewModel() { } private fun onJoined(event: ChatSharedEvents.OnJoined) { - Log.d(tag(this), "Joined: ${event.topic}") + Log.d(TAG, "Joined: ${event.topic}") updateThread(event.topic) } private fun onMessage(event: ChatSharedEvents.OnMessage) { - Log.d(tag(this), "Message: ${event.message.message}") + Log.d(TAG, "Message: ${event.message.message}") userNameToTopicMap.entries.find { it.value == event.topic }?.let { (_, topic) -> listOfThreads.find { topic == event.topic }?.let { val author = event.message.authorAccount.value listOfMessages.add(MessageUI(author, event.message.message, event.message.timestamp, author)) _listOfMessagesStateFlow.value = listOfMessages.toList() - } ?: Log.e(tag(this), "Unable to find topic: ${event.topic}") + } ?: Log.e(TAG, "Unable to find topic: ${event.topic}") } } @@ -146,7 +150,7 @@ class ChatSharedViewModel : ViewModel() { userNameToTopicMap.put(whoWasInvitedContact!!, threadTopic) } } - } else Log.e(tag(this), "Unable to find currentInvite or invited contact") + } else Log.e(TAG, "Unable to find currentInvite or invited contact") } private fun updateInvites(id: Long?) { @@ -155,9 +159,8 @@ class ChatSharedViewModel : ViewModel() { } companion object { + private const val TAG = "ChatSharedViewModel" private const val KOTLIN_ACCOUNT_ID = "eip155:2:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - private const val SWIFT_ACCOUNT_ID = "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - private const val JS_ACCOUNT_ID = "eip155:3:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" val SELF_ACCOUNT = KOTLIN_ACCOUNT_ID } } \ No newline at end of file diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt index dc394cfdde..ae6e2aac00 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/threads/ThreadsFragment.kt @@ -69,19 +69,7 @@ class ThreadsFragment : Fragment(R.layout.fragment_threads) { .onEach { flChatRequests.findViewById(R.id.tvChatRequestsCount).text = it.size.toString() } .launchIn(viewLifecycleOwner.lifecycleScope) - viewModel.register(object : Chat.Listeners.Register { - override fun onError(error: Chat.Model.Error) { - runBlocking(Dispatchers.Main) { - Log.e(tag(this), error.throwable.stackTraceToString()) - } - } - - override fun onSuccess(publicKey: String) { - runBlocking(Dispatchers.Main) { - Log.d(tag(this), "Registered successfully") - } - } - }) + viewModel.register() } } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt index c625927e01..aebb993348 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/Chat.kt @@ -27,6 +27,7 @@ object Chat { data class Invite( val account: AccountId, val message: String, + val publicKey: String, val signature: String? = null, ) : Model() @@ -62,7 +63,7 @@ object Chat { } sealed class Params { - data class Init(val core: CoreClient, val keyServerUrl: String) : Params() + data class Init(val core: CoreClient) : Params() data class Register(val account: Model.AccountId, val private: Boolean? = false) : Params() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt index baacbc7bc9..bf56ab070f 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/ChatProtocol.kt @@ -19,6 +19,7 @@ import com.walletconnect.foundation.common.model.PublicKey import kotlinx.coroutines.launch internal class ChatProtocol : ChatInterface { + private val keyServerUrl = "https://keys.walletconnect.com" private lateinit var chatEngine: ChatEngine companion object { @@ -29,17 +30,15 @@ internal class ChatProtocol : ChatInterface { @Throws(IllegalStateException::class) override fun initialize(init: Chat.Params.Init, onError: (Chat.Model.Error) -> Unit) { Logger.init() - with(init) { - wcKoinApp.run { - modules( - commonModule(), - cryptoModule(), - keyServerModule(keyServerUrl), - jsonRpcModule(), - storageModule(storageSuffix), - engineModule() - ) - } + wcKoinApp.run { + modules( + commonModule(), + cryptoModule(), + keyServerModule(keyServerUrl), + jsonRpcModule(), + storageModule(storageSuffix), + engineModule() + ) } chatEngine = wcKoinApp.koin.get() diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt index 954dde3f74..dcff341b07 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/client/mapper/ClientMapper.kt @@ -12,7 +12,7 @@ import com.walletconnect.chat.engine.model.EngineDO //TODO: Figure out what to do with models separation @JvmSynthetic internal fun Chat.Params.Invite.toEngineDO(): EngineDO.Invite { - return EngineDO.Invite(invite.account.toCommon(), invite.message, invite.signature) + return EngineDO.Invite(invite.account.toCommon(), invite.message, invite.publicKey, invite.signature) } @JvmSynthetic @@ -37,7 +37,7 @@ internal fun EngineDO.Events.OnInvite.toClient(): Chat.Model.Events.OnInvite { @JvmSynthetic internal fun EngineDO.Invite.toClient(): Chat.Model.Invite { - return Chat.Model.Invite(accountId.toClient(), message, signature) + return Chat.Model.Invite(accountId.toClient(), message, publicKey, signature) } @JvmSynthetic @@ -78,6 +78,7 @@ internal fun EngineDO.Message.toClient(): Chat.Model.Message { @JvmSynthetic internal fun SDKError.toClientError(): Chat.Model.Error = Chat.Model.Error(this.exception) + @JvmSynthetic internal fun ConnectionState.toClient(): Chat.Model.ConnectionState = Chat.Model.ConnectionState(isAvailable) \ No newline at end of file diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 0300576397..d2a311b739 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -2,6 +2,8 @@ package com.walletconnect.chat.engine.domain +import android.util.Log +import com.walletconnect.android.impl.common.MissingKeyException import com.walletconnect.android.impl.common.SDKError import com.walletconnect.android.impl.common.model.ConnectionState import com.walletconnect.android.impl.common.model.type.EngineEvent @@ -12,6 +14,8 @@ import com.walletconnect.android.internal.common.exception.GenericException import com.walletconnect.android.internal.common.exception.WalletConnectException import com.walletconnect.android.internal.common.model.* import com.walletconnect.android.internal.common.scope +import com.walletconnect.chat.client.Chat +import com.walletconnect.chat.client.ChatClient import com.walletconnect.chat.common.exceptions.InvalidAccountIdException import com.walletconnect.chat.common.exceptions.PeerError import com.walletconnect.chat.common.model.AccountId @@ -28,6 +32,7 @@ import com.walletconnect.foundation.common.model.Ttl import com.walletconnect.util.generateId import kotlinx.coroutines.* import kotlinx.coroutines.flow.* +import kotlin.Error internal class ChatEngine( private val registerAccountUseCase: RegisterAccountUseCase, @@ -61,23 +66,29 @@ internal class ChatEngine( val topic = keyManagementRepository.getTopicFromKey(publicKey) keyManagementRepository.setKey(publicKey, SELF_INVITE_PUBLIC_KEY_CONTEXT) keyManagementRepository.setKey(publicKey, "$SELF_PARTICIPANT_CONTEXT${topic.value}") - trySubscribeToInviteTopic() + Logger.error("Kobe; Return: $publicKey") onSuccess(publicKey.keyAsHex) } if (accountId.isValid()) { - val publicKey = keyManagementRepository.generateKeyPair() - if (!private) { - scope.launch { - supervisorScope { - registerAccountUseCase(AccountIdWithPublicKey(accountId, publicKey)).fold( - onSuccess = { onSuccess(publicKey) }, - onFailure = { error -> onFailure(error) } - ) + try { + val storedPublicKey = keyManagementRepository.getPublicKey(SELF_INVITE_PUBLIC_KEY_CONTEXT) + onSuccess(storedPublicKey.keyAsHex) + } catch (e: MissingKeyException) { + val publicKey = keyManagementRepository.generateKeyPair() + + if (!private) { + scope.launch { + supervisorScope { + registerAccountUseCase(AccountIdWithPublicKey(accountId, publicKey)).fold( + onSuccess = { onSuccess(publicKey) }, + onFailure = { error -> onFailure(error) } + ) + } } + } else { + onSuccess(publicKey) } - } else { - onSuccess(publicKey) } } else { onFailure(InvalidAccountIdException("AccountId is not CAIP-10 complaint")) @@ -86,7 +97,6 @@ internal class ChatEngine( internal fun resolveAccount(accountId: AccountId, onSuccess: (String) -> Unit, onFailure: (Throwable) -> Unit) { if (accountId.isValid()) { - //todo: check if there's pubKey under given accountId if yes use it if not register scope.launch { supervisorScope { resolveAccountUseCase(accountId).fold( @@ -101,15 +111,18 @@ internal class ChatEngine( } internal fun invite(peerAccount: AccountId, invite: EngineDO.Invite, onFailure: (Throwable) -> Unit) = try { + addContact(AccountIdWithPublicKey(peerAccount, PublicKey(invite.publicKey))) { error -> + Logger.error("Error while adding new account: $error") + } val senderPublicKey = keyManagementRepository.generateKeyPair() + val peerPublicKey = PublicKey(invite.publicKey) + val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(senderPublicKey, peerPublicKey) + val inviteTopic = keyManagementRepository.getTopicFromKey(peerPublicKey) + keyManagementRepository.setKeyAgreement(inviteTopic, senderPublicKey, peerPublicKey) - val contact = chatStorage.getContact(peerAccount) - val symmetricKey = keyManagementRepository.generateSymmetricKeyFromKeyAgreement(senderPublicKey, contact.publicKey) - val inviteTopic = keyManagementRepository.getTopicFromKey(contact.publicKey) - keyManagementRepository.setKeyAgreement(inviteTopic, senderPublicKey, contact.publicKey) - - val participants = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = contact.publicKey) + val participants = Participants(senderPublicKey = senderPublicKey, receiverPublicKey = peerPublicKey) val inviteParams = ChatParams.InviteParams(invite.message, invite.accountId.value, senderPublicKey.keyAsHex, invite.signature) + val payload = ChatRpc.ChatInvite(id = generateId(), params = inviteParams) val acceptTopic = keyManagementRepository.getTopicFromKey(symmetricKey) @@ -269,7 +282,7 @@ internal class ChatEngine( private fun onInviteRequest(wcRequest: WCRequest, params: ChatParams.InviteParams) { inviteRequestMap[wcRequest.id] = wcRequest scope.launch { - val invite = EngineDO.Invite(AccountId(params.account), params.message, params.signature) + val invite = EngineDO.Invite(AccountId(params.account), params.message, params.publicKey, params.signature) _events.emit(EngineDO.Events.OnInvite(wcRequest.id, invite)) } //TODO: Add adding invites to storage. For Alpha we will use only emitted event. @@ -325,6 +338,17 @@ internal class ChatEngine( } } + private suspend fun collectResponse(id: Long, onResponse: (Result) -> Unit = {}) { + jsonRpcInteractor.peerResponse + .filter { response -> response.response.id == id } + .collect { response -> + when (val result = response.response) { + is JsonRpcResponse.JsonRpcResult -> onResponse(Result.success(result)) + is JsonRpcResponse.JsonRpcError -> onResponse(Result.failure(Throwable(result.errorMessage))) + } + } + } + private fun resubscribeToInviteTopic() { jsonRpcInteractor.isConnectionAvailable .onEach { isAvailable -> _events.emit(ConnectionState(isAvailable)) } @@ -344,17 +368,6 @@ internal class ChatEngine( } } - private suspend fun collectResponse(id: Long, onResponse: (Result) -> Unit = {}) { - jsonRpcInteractor.peerResponse - .filter { response -> response.response.id == id } - .collect { response -> - when (val result = response.response) { - is JsonRpcResponse.JsonRpcResult -> onResponse(Result.success(result)) - is JsonRpcResponse.JsonRpcError -> onResponse(Result.failure(Throwable(result.errorMessage))) - } - } - } - private fun collectInternalErrors() { jsonRpcInteractor.internalErrors .onEach { exception -> _events.emit(SDKError(exception)) } diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt index 75ad1a718d..2ee8d150d1 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/model/EngineDO.kt @@ -13,6 +13,7 @@ internal sealed class EngineDO { data class Invite( val accountId: AccountId, val message: String, + val publicKey: String, val signature: String? = null, ) : EngineDO() From a0e05d01051c93578f7e4c0ee15815ec2750709e Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 12:26:42 +0200 Subject: [PATCH 25/30] Clean up --- .../kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index d2a311b739..1f3fe58c91 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -66,7 +66,6 @@ internal class ChatEngine( val topic = keyManagementRepository.getTopicFromKey(publicKey) keyManagementRepository.setKey(publicKey, SELF_INVITE_PUBLIC_KEY_CONTEXT) keyManagementRepository.setKey(publicKey, "$SELF_PARTICIPANT_CONTEXT${topic.value}") - Logger.error("Kobe; Return: $publicKey") onSuccess(publicKey.keyAsHex) } From 79451c3dc4dab85b4158bff6e6f26170963547d9 Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 14:59:44 +0200 Subject: [PATCH 26/30] Add dynamic generation of register address --- chat/sample/build.gradle.kts | 1 + .../chatsample/ui/host/ChatSampleActivity.kt | 3 + .../ui/shared/ChatSharedViewModel.kt | 60 +++++++++++++++---- chat/sdk/build.gradle.kts | 5 ++ .../chat/engine/domain/ChatEngine.kt | 8 +-- 5 files changed, 58 insertions(+), 19 deletions(-) diff --git a/chat/sample/build.gradle.kts b/chat/sample/build.gradle.kts index 4590534297..030a1708ed 100644 --- a/chat/sample/build.gradle.kts +++ b/chat/sample/build.gradle.kts @@ -20,6 +20,7 @@ android { buildTypes { release { isMinifyEnabled = false + signingConfig = signingConfigs.getByName("debug") proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt index 7a9003d129..40e0013c57 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt @@ -7,6 +7,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContentProviderCompat.requireContext import androidx.core.os.bundleOf import androidx.lifecycle.Lifecycle +import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController @@ -29,6 +30,8 @@ class ChatSampleActivity : AppCompatActivity() { supportFragmentManager.findFragmentById(R.id.fcvHost) as NavHostFragment } +// val viewModelProvider = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application)) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index d26474b932..10954e013e 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -1,7 +1,10 @@ package com.walletconnect.chatsample.ui.shared +import android.app.Application +import android.content.Context +import android.content.SharedPreferences import android.util.Log -import androidx.lifecycle.ViewModel +import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.walletconnect.chat.client.Chat import com.walletconnect.chat.client.ChatClient @@ -11,8 +14,10 @@ import com.walletconnect.chatsample.utils.tag import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking +import java.security.SecureRandom -class ChatSharedViewModel : ViewModel() { +class ChatSharedViewModel(application: Application) : AndroidViewModel(application) { + private val sharedPreferences: SharedPreferences = application.getSharedPreferences("Chat_Shared_Prefs", Context.MODE_PRIVATE) var currentInvite: Chat.Model.Invite? = null var whoWasInvitedContact: String? = null val userNameToTopicMap: MutableMap = mutableMapOf() @@ -43,16 +48,24 @@ class ChatSharedViewModel : ViewModel() { }.shareIn(viewModelScope, SharingStarted.WhileSubscribed()) fun register() { - val register = Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)) - ChatClient.register(register, object : Chat.Listeners.Register { - override fun onError(error: Chat.Model.Error) { - Log.e(TAG, "Register error: ${error.throwable.stackTraceToString()}") - } + val accountId = sharedPreferences.getString(ACCOUNT_TAG, null) + if (accountId == null) { + SELF_ACCOUNT = "eip155:1:0x${randomBytes(24).bytesToHex()}" + sharedPreferences.edit().putString(ACCOUNT_TAG, SELF_ACCOUNT).apply() + val register = Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)) + + ChatClient.register(register, object : Chat.Listeners.Register { + override fun onError(error: Chat.Model.Error) { + Log.e(TAG, "Register error: ${error.throwable.stackTraceToString()}") + } - override fun onSuccess(publicKey: String) { - Log.d(TAG, "Registered successfully") - } - }) + override fun onSuccess(publicKey: String) { + Log.d(TAG, "Registered successfully") + } + }) + } else { + SELF_ACCOUNT = accountId + } } fun invite(contact: String, openingMessage: String, afterInviteSent: () -> Unit) { @@ -158,9 +171,30 @@ class ChatSharedViewModel : ViewModel() { _listOfInvitesStateFlow.value = listOfInvites.toList() } + private fun randomBytes(size: Int): ByteArray = ByteArray(size).apply { + SecureRandom().nextBytes(this) + } + + private fun ByteArray.bytesToHex(): String { + val hexString = StringBuilder(2 * this.size) + + this.indices.forEach { i -> + val hex = Integer.toHexString(0xff and this[i].toInt()) + + if (hex.length == 1) { + hexString.append('0') + } + + hexString.append(hex) + } + + return hexString.toString() + } + + companion object { private const val TAG = "ChatSharedViewModel" - private const val KOTLIN_ACCOUNT_ID = "eip155:2:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" - val SELF_ACCOUNT = KOTLIN_ACCOUNT_ID + const val ACCOUNT_TAG = "self_account_tag" + var SELF_ACCOUNT = "" } } \ No newline at end of file diff --git a/chat/sdk/build.gradle.kts b/chat/sdk/build.gradle.kts index 00464d1719..87fddc2024 100644 --- a/chat/sdk/build.gradle.kts +++ b/chat/sdk/build.gradle.kts @@ -36,6 +36,11 @@ android { kotlinOptions { jvmTarget = jvmVersion.toString() } + + testOptions.unitTests { + isIncludeAndroidResources = true + isReturnDefaultValues = true + } } sqldelight { diff --git a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt index 1f3fe58c91..dd225d409d 100644 --- a/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt +++ b/chat/sdk/src/main/kotlin/com/walletconnect/chat/engine/domain/ChatEngine.kt @@ -2,7 +2,6 @@ package com.walletconnect.chat.engine.domain -import android.util.Log import com.walletconnect.android.impl.common.MissingKeyException import com.walletconnect.android.impl.common.SDKError import com.walletconnect.android.impl.common.model.ConnectionState @@ -14,14 +13,12 @@ import com.walletconnect.android.internal.common.exception.GenericException import com.walletconnect.android.internal.common.exception.WalletConnectException import com.walletconnect.android.internal.common.model.* import com.walletconnect.android.internal.common.scope -import com.walletconnect.chat.client.Chat -import com.walletconnect.chat.client.ChatClient import com.walletconnect.chat.common.exceptions.InvalidAccountIdException import com.walletconnect.chat.common.exceptions.PeerError +import com.walletconnect.chat.common.json_rpc.ChatParams +import com.walletconnect.chat.common.json_rpc.ChatRpc import com.walletconnect.chat.common.model.AccountId import com.walletconnect.chat.common.model.AccountIdWithPublicKey -import com.walletconnect.chat.common.json_rpc.ChatRpc -import com.walletconnect.chat.common.json_rpc.ChatParams import com.walletconnect.chat.discovery.keyserver.domain.use_case.RegisterAccountUseCase import com.walletconnect.chat.discovery.keyserver.domain.use_case.ResolveAccountUseCase import com.walletconnect.chat.engine.model.EngineDO @@ -32,7 +29,6 @@ import com.walletconnect.foundation.common.model.Ttl import com.walletconnect.util.generateId import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlin.Error internal class ChatEngine( private val registerAccountUseCase: RegisterAccountUseCase, From 5c89a878e598080aa159c57668d234197d659cd1 Mon Sep 17 00:00:00 2001 From: szymon Date: Fri, 28 Oct 2022 14:28:59 +0100 Subject: [PATCH 27/30] feat: Account id logging --- .../walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index 10954e013e..ff87fdbbfd 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -60,11 +60,12 @@ class ChatSharedViewModel(application: Application) : AndroidViewModel(applicati } override fun onSuccess(publicKey: String) { - Log.d(TAG, "Registered successfully") + Log.d(TAG, "Registered successfully, $SELF_ACCOUNT") } }) } else { SELF_ACCOUNT = accountId + Log.d(TAG, "Registered successfully, $SELF_ACCOUNT") } } From d43354cbc688c3dc88f689e00709393b00c1ba13 Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 15:54:30 +0200 Subject: [PATCH 28/30] Clean up --- .../walletconnect/chatsample/ui/host/ChatSampleActivity.kt | 2 -- .../walletconnect/chatsample/ui/invites/InvitesFragment.kt | 4 +--- .../walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt | 3 --- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt index 40e0013c57..33a048f085 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/host/ChatSampleActivity.kt @@ -30,8 +30,6 @@ class ChatSampleActivity : AppCompatActivity() { supportFragmentManager.findFragmentById(R.id.fcvHost) as NavHostFragment } -// val viewModelProvider = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application)) - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt index 2817af3bd7..f36e1bdb26 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/invites/InvitesFragment.kt @@ -17,9 +17,7 @@ import kotlinx.coroutines.flow.onEach class InvitesFragment : Fragment(R.layout.fragment_invites) { private val binding by viewBinding(FragmentInvitesBinding::bind) private val viewModel: ChatSharedViewModel by activityViewModels() - private val invitesAdapter by lazy { - InvitesAdapter(onAccept = { chatUI -> viewModel.acceptInvitation(chatUI) }, onReject = { id -> viewModel.rejectInvitation(id) }) - } + private val invitesAdapter by lazy { InvitesAdapter(onAccept = { viewModel::acceptInvitation }, onReject = { viewModel::rejectInvitation }) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index 10954e013e..13fe3b94bd 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -180,14 +180,11 @@ class ChatSharedViewModel(application: Application) : AndroidViewModel(applicati this.indices.forEach { i -> val hex = Integer.toHexString(0xff and this[i].toInt()) - if (hex.length == 1) { hexString.append('0') } - hexString.append(hex) } - return hexString.toString() } From b4bcdb77d32e86d445a57f41b5357c40fc9e46c1 Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 15:58:00 +0200 Subject: [PATCH 29/30] Add get ethereum account --- .../walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt index fe2edbe905..6516c0e654 100644 --- a/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt +++ b/chat/sample/src/main/kotlin/com/walletconnect/chatsample/ui/shared/ChatSharedViewModel.kt @@ -50,7 +50,7 @@ class ChatSharedViewModel(application: Application) : AndroidViewModel(applicati fun register() { val accountId = sharedPreferences.getString(ACCOUNT_TAG, null) if (accountId == null) { - SELF_ACCOUNT = "eip155:1:0x${randomBytes(24).bytesToHex()}" + SELF_ACCOUNT = generateEthereumAccount() sharedPreferences.edit().putString(ACCOUNT_TAG, SELF_ACCOUNT).apply() val register = Chat.Params.Register(Chat.Model.AccountId(SELF_ACCOUNT)) @@ -189,6 +189,7 @@ class ChatSharedViewModel(application: Application) : AndroidViewModel(applicati return hexString.toString() } + private fun generateEthereumAccount() = "eip155:1:0x${randomBytes(24).bytesToHex()}" companion object { private const val TAG = "ChatSharedViewModel" From 071fea95d30e34d49d361a9e36f23a386893e9c9 Mon Sep 17 00:00:00 2001 From: kubel Date: Fri, 28 Oct 2022 16:30:39 +0200 Subject: [PATCH 30/30] Versions update --- androidCore/impl/build.gradle.kts | 4 ++-- androidCore/sdk/build.gradle.kts | 2 +- auth/requester/build.gradle.kts | 4 ++-- auth/responder/build.gradle.kts | 4 ++-- auth/sdk/build.gradle.kts | 4 ++-- chat/sample/build.gradle.kts | 7 +++++-- chat/sdk/build.gradle.kts | 2 +- sign/dapp/build.gradle.kts | 4 ++-- sign/sdk/build.gradle.kts | 4 ++-- sign/wallet/build.gradle.kts | 4 ++-- 10 files changed, 21 insertions(+), 18 deletions(-) diff --git a/androidCore/impl/build.gradle.kts b/androidCore/impl/build.gradle.kts index 9fae41dde0..47cfdb3c6c 100644 --- a/androidCore/impl/build.gradle.kts +++ b/androidCore/impl/build.gradle.kts @@ -8,7 +8,7 @@ plugins { project.apply { extra[KEY_PUBLISH_ARTIFACT_ID] = "android-core-impl" - extra[KEY_PUBLISH_VERSION] = "1.1.0" + extra[KEY_PUBLISH_VERSION] = "1.2.0" extra[KEY_SDK_NAME] = "Android Core Impl" } @@ -51,7 +51,7 @@ sqldelight { dependencies { debugApi(project(":androidCore:sdk")) - releaseApi("com.walletconnect:android-core:1.1.0") + releaseApi("com.walletconnect:android-core:1.2.0") bouncyCastle() coroutines() diff --git a/androidCore/sdk/build.gradle.kts b/androidCore/sdk/build.gradle.kts index 6a1cd609f3..7ddb890e1b 100644 --- a/androidCore/sdk/build.gradle.kts +++ b/androidCore/sdk/build.gradle.kts @@ -7,7 +7,7 @@ plugins { project.apply { extra[KEY_PUBLISH_ARTIFACT_ID] = "android-core" - extra[KEY_PUBLISH_VERSION] = "1.1.0" + extra[KEY_PUBLISH_VERSION] = "1.2.0" extra[KEY_SDK_NAME] = "Android Core" } diff --git a/auth/requester/build.gradle.kts b/auth/requester/build.gradle.kts index 30af62bf13..4ad2aebddd 100644 --- a/auth/requester/build.gradle.kts +++ b/auth/requester/build.gradle.kts @@ -40,10 +40,10 @@ dependencies { implementation(project(":sign:samples_common")) //todo: Move samples common module out of signSDK debugImplementation(project(":auth:sdk")) - releaseImplementation("com.walletconnect:auth:1.0.0") + releaseImplementation("com.walletconnect:auth:1.1.0") debugImplementation(project(":androidCore:sdk")) - releaseImplementation("com.walletconnect:android-core:1.1.0") + releaseImplementation("com.walletconnect:android-core:1.2.0") glide_N_kapt() implementation("com.github.alexzhirkevich:custom-qr-generator:1.4.1") diff --git a/auth/responder/build.gradle.kts b/auth/responder/build.gradle.kts index 7db447e065..4565904840 100644 --- a/auth/responder/build.gradle.kts +++ b/auth/responder/build.gradle.kts @@ -40,10 +40,10 @@ dependencies { implementation(project(":sign:samples_common")) //todo: Move samples common module out of signSDK debugImplementation(project(":auth:sdk")) - releaseImplementation("com.walletconnect:auth:1.0.0") + releaseImplementation("com.walletconnect:auth:1.1.0") debugImplementation(project(":androidCore:sdk")) - releaseImplementation("com.walletconnect:android-core:1.1.0") + releaseImplementation("com.walletconnect:android-core:1.2.0") glide_N_kapt() scanner() diff --git a/auth/sdk/build.gradle.kts b/auth/sdk/build.gradle.kts index 425b9a7d97..81899d3ac6 100644 --- a/auth/sdk/build.gradle.kts +++ b/auth/sdk/build.gradle.kts @@ -9,7 +9,7 @@ plugins { project.apply { extra[KEY_PUBLISH_ARTIFACT_ID] = "auth" - extra[KEY_PUBLISH_VERSION] = "1.0.0" + extra[KEY_PUBLISH_VERSION] = "1.1.0" extra[KEY_SDK_NAME] = "Auth" } @@ -51,7 +51,7 @@ sqldelight { dependencies { debugImplementation(project(":androidCore:impl")) - releaseImplementation("com.walletconnect:android-core-impl:1.1.0") + releaseImplementation("com.walletconnect:android-core-impl:1.2.0") okhttp() timber() diff --git a/chat/sample/build.gradle.kts b/chat/sample/build.gradle.kts index 030a1708ed..549a605114 100644 --- a/chat/sample/build.gradle.kts +++ b/chat/sample/build.gradle.kts @@ -37,8 +37,11 @@ android { } dependencies { - implementation(project(":chat:sdk")) - implementation(project(":androidCore:sdk")) + debugImplementation(project(":chat:sdk")) + releaseImplementation("com.walletconnect:chat:1.0.0-alpha01") + + debugImplementation(project(":androidCore:sdk")) + releaseImplementation("com.walletconnect:android-core:1.2.0") lifecycle() implementation("com.google.android.material:material:1.6.1") diff --git a/chat/sdk/build.gradle.kts b/chat/sdk/build.gradle.kts index 87fddc2024..e0abc22ff7 100644 --- a/chat/sdk/build.gradle.kts +++ b/chat/sdk/build.gradle.kts @@ -53,7 +53,7 @@ sqldelight { dependencies { debugImplementation(project(":androidCore:impl")) - releaseImplementation("com.walletconnect:android-core-impl:1.1.0") + releaseImplementation("com.walletconnect:android-core-impl:1.2.0") retrofit() navigationComponent() diff --git a/sign/dapp/build.gradle.kts b/sign/dapp/build.gradle.kts index 22c6cd77e9..4379583a7b 100644 --- a/sign/dapp/build.gradle.kts +++ b/sign/dapp/build.gradle.kts @@ -43,10 +43,10 @@ dependencies { implementation(project(":sign:samples_common")) debugImplementation(project(":sign:sdk")) - releaseImplementation("com.walletconnect:sign:2.0.0") + releaseImplementation("com.walletconnect:sign:2.1.0") debugImplementation(project(":androidCore:sdk")) - releaseImplementation("com.walletconnect:android-core:1.1.0") + releaseImplementation("com.walletconnect:android-core:1.2.0") glide_N_kapt() implementation("com.github.kenglxn.QRGen:android:2.6.0") diff --git a/sign/sdk/build.gradle.kts b/sign/sdk/build.gradle.kts index a862c19def..58fba04841 100644 --- a/sign/sdk/build.gradle.kts +++ b/sign/sdk/build.gradle.kts @@ -8,7 +8,7 @@ plugins { project.apply { extra[KEY_PUBLISH_ARTIFACT_ID] = "sign" - extra[KEY_PUBLISH_VERSION] = "2.0.0" + extra[KEY_PUBLISH_VERSION] = "2.1.0" extra[KEY_SDK_NAME] = "Sign" } @@ -63,7 +63,7 @@ sqldelight { dependencies { debugImplementation(project(":androidCore:impl")) - releaseImplementation("com.walletconnect:android-core-impl:1.1.0") + releaseImplementation("com.walletconnect:android-core-impl:1.2.0") moshiKsp() androidXTest() diff --git a/sign/wallet/build.gradle.kts b/sign/wallet/build.gradle.kts index a62bb108cc..eaaf6241b8 100644 --- a/sign/wallet/build.gradle.kts +++ b/sign/wallet/build.gradle.kts @@ -43,10 +43,10 @@ dependencies { implementation(project(":sign:samples_common")) debugImplementation(project(":sign:sdk")) - releaseImplementation("com.walletconnect:sign:2.0.0") + releaseImplementation("com.walletconnect:sign:2.1.0") debugImplementation(project(":androidCore:sdk")) - releaseImplementation("com.walletconnect:android-core:1.1.0") + releaseImplementation("com.walletconnect:android-core:1.2.0") scanner() glide_N_kapt()