From 07bc6c49df938a63d47ee41e3e4bf0039ed6688c Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 20 May 2024 21:42:31 +0300 Subject: [PATCH] feat(dapps) attempt to fix the wallet connect abstraction Spent too much time figuring out the puzzle of service->module->view->QML just to call a status-go function. Keeping this attempt for later while moving to a simplified Controller/Provider approach. I will come back to the abstraction when we add tests to use it. Updates: #14615 --- src/app/boot/app_controller.nim | 3 ++- src/app/modules/main/module.nim | 7 +++++-- .../modules/main/wallet_section/module.nim | 19 +++++++++++------ src/app/modules/main/wallet_section/view.nim | 21 +++++++++++-------- .../wallet_connect/controller.nim | 9 ++++---- .../wallet_connect/io_interface.nim | 2 ++ .../shared_modules/wallet_connect/module.nim | 8 ++++--- .../shared_modules/wallet_connect/view.nim | 10 ++++++++- .../service/wallet_connect/service.nim | 7 +++++-- src/backend/wallet_connect.nim | 20 ++++++++++++++++++ storybook/pages/DAppsWorkflowPage.qml | 5 ++++- .../services/dapps/WalletConnectService.qml | 13 ++++++++++-- ui/app/AppLayouts/Wallet/stores/RootStore.qml | 1 + ui/app/mainui/AppMain.qml | 3 ++- ui/imports/shared/stores/DAppsStore.qml | 8 ++++++- 15 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 src/backend/wallet_connect.nim diff --git a/src/app/boot/app_controller.nim b/src/app/boot/app_controller.nim index 2b0bad37c9..f9473a80dc 100644 --- a/src/app/boot/app_controller.nim +++ b/src/app/boot/app_controller.nim @@ -290,7 +290,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController = result.generalService, result.keycardService, result.networkConnectionService, - result.sharedUrlsService + result.sharedUrlsService, + statusFoundation.threadpool ) # Do connections diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index b64b44a83d..b5544c5b8c 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -77,6 +77,8 @@ import ../../core/custom_urls/urls_manager export io_interface +import app/core/tasks/threadpool + const TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS = 5000 # 5 seconds const STATUS_URL_ENS_RESOLVE_REASON = "StatusUrl" @@ -165,7 +167,8 @@ proc newModule*[T]( generalService: general_service.Service, keycardService: keycard_service.Service, networkConnectionService: network_connection_service.Service, - sharedUrlsService: urls_service.Service + sharedUrlsService: urls_service.Service, + threadpool: ThreadPool ): Module[T] = result = Module[T]() result.delegate = delegate @@ -212,7 +215,7 @@ proc newModule*[T]( transactionService, walletAccountService, settingsService, savedAddressService, networkService, accountsService, keycardService, nodeService, networkConnectionService, devicesService, - communityTokensService + communityTokensService, threadpool ) result.browserSectionModule = browser_section_module.newModule( result, events, bookmarkService, settingsService, networkService, diff --git a/src/app/modules/main/wallet_section/module.nim b/src/app/modules/main/wallet_section/module.nim index cfede2f9f0..ee3ffa336b 100644 --- a/src/app/modules/main/wallet_section/module.nim +++ b/src/app/modules/main/wallet_section/module.nim @@ -16,7 +16,6 @@ import ./send/module as send_module import ./activity/controller as activityc import ./activity/details_controller as activity_detailsc -import ./poc_wallet_connect/controller as wcc import app/modules/shared_modules/collectible_details/controller as collectible_detailsc @@ -24,6 +23,7 @@ import app/global/global_singleton import app/core/eventemitter import app/modules/shared_modules/add_account/module as add_account_module import app/modules/shared_modules/keypair_import/module as keypair_import_module +import app/modules/shared_modules/wallet_connect/module as wc_module import app_service/service/keycard/service as keycard_service import app_service/service/token/service as token_service import app_service/service/collectible/service as collectible_service @@ -38,9 +38,12 @@ import app_service/service/node/service as node_service import app_service/service/network_connection/service as network_connection_service import app_service/service/devices/service as devices_service import app_service/service/community_tokens/service as community_tokens_service +import app_service/service/wallet_connect/service as wc_service import backend/collectibles as backend_collectibles +import app/core/tasks/threadpool + logScope: topics = "wallet-section-module" @@ -58,6 +61,7 @@ type # shared modules addAccountModule: add_account_module.AccessInterface keypairImportModule: keypair_import_module.AccessInterface + walletConnectModule: wc_module.AccessInterface # modules accountsModule: accounts_module.AccessInterface allTokensModule: all_tokens_module.AccessInterface @@ -75,6 +79,7 @@ type walletAccountService: wallet_account_service.Service savedAddressService: saved_address_service.Service devicesService: devices_service.Service + walletConnectService: wc_service.Service activityController: activityc.Controller collectibleDetailsController: collectible_detailsc.Controller @@ -85,7 +90,7 @@ type tmpActivityControllers: ActivityControllerArray activityDetailsController: activity_detailsc.Controller - wcController: wcc.Controller + threadpool: ThreadPool ## Forward declaration proc onUpdatedKeypairsOperability*(self: Module, updatedKeypairs: seq[KeypairDto]) @@ -107,7 +112,8 @@ proc newModule*( nodeService: node_service.Service, networkConnectionService: network_connection_service.Service, devicesService: devices_service.Service, - communityTokensService: community_tokens_service.Service + communityTokensService: community_tokens_service.Service, + threadpool: ThreadPool ): Module = result = Module() result.delegate = delegate @@ -119,6 +125,7 @@ proc newModule*( result.devicesService = devicesService result.moduleLoaded = false result.controller = newController(result, settingsService, walletAccountService, currencyService, networkService) + result.threadpool = threadpool result.accountsModule = accounts_module.newModule(result, events, walletAccountService, networkService, currencyService) result.allTokensModule = all_tokens_module.newModule(result, events, tokenService, walletAccountService, settingsService, communityTokensService) @@ -160,9 +167,10 @@ proc newModule*( result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events) result.filter = initFilter(result.controller) - result.wcController = wcc.newController(events, walletAccountService) + result.walletConnectService = wc_service.newService(result.events, result.threadpool) + result.walletConnectModule = wc_module.newModule(result, result.events, result.walletAccountService, result.walletConnectService) - result.view = newView(result, result.activityController, result.tmpActivityControllers, result.activityDetailsController, result.collectibleDetailsController, result.wcController) + result.view = newView(result, result.activityController, result.tmpActivityControllers, result.activityDetailsController, result.collectibleDetailsController, result.walletConnectModule) method delete*(self: Module) = self.accountsModule.delete @@ -179,7 +187,6 @@ method delete*(self: Module) = self.tmpActivityControllers[i].delete self.activityDetailsController.delete self.collectibleDetailsController.delete - self.wcController.delete if not self.addAccountModule.isNil: self.addAccountModule.delete diff --git a/src/app/modules/main/wallet_section/view.nim b/src/app/modules/main/wallet_section/view.nim index 65b36865af..b33bf01633 100644 --- a/src/app/modules/main/wallet_section/view.nim +++ b/src/app/modules/main/wallet_section/view.nim @@ -4,8 +4,8 @@ import ./activity/controller as activityc import ./activity/details_controller as activity_detailsc import app/modules/shared_modules/collectible_details/controller as collectible_detailsc import ./io_interface -import ../../shared_models/currency_amount -import ./poc_wallet_connect/controller as wcc +import app/modules/shared_models/currency_amount +import app/modules/shared_modules/wallet_connect/io_interface as wc_module type ActivityControllerArray* = array[2, activityc.Controller] @@ -25,7 +25,7 @@ QtObject: collectibleDetailsController: collectible_detailsc.Controller isNonArchivalNode: bool keypairOperabilityForObservedAccount: string - wcController: wcc.Controller + wcModule: wc_module.AccessInterface walletReady: bool addressFilters: string currentCurrency: string @@ -41,14 +41,14 @@ QtObject: tmpActivityControllers: ActivityControllerArray, activityDetailsController: activity_detailsc.Controller, collectibleDetailsController: collectible_detailsc.Controller, - wcController: wcc.Controller): View = + wcModule: wc_module.AccessInterface): View = new(result, delete) result.delegate = delegate result.activityController = activityController result.tmpActivityControllers = tmpActivityControllers result.activityDetailsController = activityDetailsController result.collectibleDetailsController = collectibleDetailsController - result.wcController = wcController + result.wcModule = wcModule result.setup() @@ -236,10 +236,13 @@ QtObject: proc emitDestroyKeypairImportPopup*(self: View) = self.destroyKeypairImportPopup() - proc getWalletConnectController(self: View): QVariant {.slot.} = - return newQVariant(self.wcController) - QtProperty[QVariant] walletConnectController: - read = getWalletConnectController + proc getWalletConnectModule(self: View): QVariant {.slot.} = + if self.wcModule == nil: + return newQVariant() + return self.wcModule.getModuleAsVariant() + + QtProperty[QVariant] walletConnectModule: + read = getWalletConnectModule proc walletReadyChanged*(self: View) {.signal.} diff --git a/src/app/modules/shared_modules/wallet_connect/controller.nim b/src/app/modules/shared_modules/wallet_connect/controller.nim index 68285316aa..2124e6b51f 100644 --- a/src/app/modules/shared_modules/wallet_connect/controller.nim +++ b/src/app/modules/shared_modules/wallet_connect/controller.nim @@ -25,8 +25,9 @@ proc newController*(delegate: io_interface.AccessInterface, result.walletAccountService = walletAccountService result.walletConnectService = walletConnectService -proc delete*(self: Controller) = - self.disconnectAll() - proc init*(self: Controller) = - discard \ No newline at end of file + discard + +proc addWalletConnectSession*(self: Controller, session_json: string): bool = + echo "@ddd Controller.addWalletConnectSession", session_json.len + return self.walletConnectService.addSession(session_json) \ No newline at end of file diff --git a/src/app/modules/shared_modules/wallet_connect/io_interface.nim b/src/app/modules/shared_modules/wallet_connect/io_interface.nim index 9d6679ac3c..45ebc5126b 100644 --- a/src/app/modules/shared_modules/wallet_connect/io_interface.nim +++ b/src/app/modules/shared_modules/wallet_connect/io_interface.nim @@ -9,6 +9,8 @@ method delete*(self: AccessInterface) {.base.} = method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} = raise newException(ValueError, "No implementation available") +method addWalletConnectSession*(self: AccessInterface, session_json: string): bool {.base.} = + raise newException(ValueError, "No implementation available") type DelegateInterface* = concept c diff --git a/src/app/modules/shared_modules/wallet_connect/module.nim b/src/app/modules/shared_modules/wallet_connect/module.nim index c8c51e7532..d17f095884 100644 --- a/src/app/modules/shared_modules/wallet_connect/module.nim +++ b/src/app/modules/shared_modules/wallet_connect/module.nim @@ -21,7 +21,6 @@ type controller: Controller proc newModule*[T](delegate: T, - uniqueIdentifier: string, events: EventEmitter, walletAccountService: wallet_account_service.Service, walletConnectService: wallet_connect_service.Service): @@ -30,14 +29,17 @@ proc newModule*[T](delegate: T, result.delegate = delegate result.view = view.newView(result) result.viewVariant = newQVariant(result.view) - result.controller = controller.newController(result, walletAccountService, walletConnectService) + result.controller = controller.newController(result, events, walletAccountService, walletConnectService) + +proc addWalletConnectSession*[T](self: Module[T], session_json: string): bool = + echo "@dd Module.addWalletConnectSession: ", session_json + return self.controller.addWalletConnectSession(session_json) {.push warning[Deprecated]: off.} method delete*[T](self: Module[T]) = self.view.delete self.viewVariant.delete - self.controller.delete proc init[T](self: Module[T], fullConnect = true) = self.controller.init() diff --git a/src/app/modules/shared_modules/wallet_connect/view.nim b/src/app/modules/shared_modules/wallet_connect/view.nim index 1b1e8044e3..ce1b8062e4 100644 --- a/src/app/modules/shared_modules/wallet_connect/view.nim +++ b/src/app/modules/shared_modules/wallet_connect/view.nim @@ -12,4 +12,12 @@ QtObject: proc newView*(delegate: io_interface.AccessInterface): View = new(result, delete) result.QObject.setup - result.delegate = delegate \ No newline at end of file + result.delegate = delegate + + proc addWalletConnectSession*(self: View, session_json: string): bool {.slot.} = + echo "@dd Vew.addWalletConnectSession: ", session_json, "; self.delegate.isNil: ", self.delegate.isNil + try: + return self.delegate.addWalletConnectSession(session_json) + except Exception as e: + echo "@dd Error in View.addWalletConnectSession: ", e.msg + return false \ No newline at end of file diff --git a/src/app_service/service/wallet_connect/service.nim b/src/app_service/service/wallet_connect/service.nim index f539eedcf3..1dfda85155 100644 --- a/src/app_service/service/wallet_connect/service.nim +++ b/src/app_service/service/wallet_connect/service.nim @@ -1,6 +1,6 @@ import NimQml, chronicles -# import backend/wallet_connect as status_go_wallet_connect +import backend/wallet_connect as status_go import app/global/global_singleton @@ -31,4 +31,7 @@ QtObject: result.threadpool = threadpool proc init*(self: Service) = - discard \ No newline at end of file + discard + + proc addSession*(self: Service, session_json: string): bool = + return status_go.addSession(session_json) \ No newline at end of file diff --git a/src/backend/wallet_connect.nim b/src/backend/wallet_connect.nim new file mode 100644 index 0000000000..1d4a3ab4c5 --- /dev/null +++ b/src/backend/wallet_connect.nim @@ -0,0 +1,20 @@ +import options, logging +import json +import core, response_type + +from gen import rpc +import backend + +rpc(addWalletConnectSession, "wallet"): + sessionJson: string + +proc isErrorResponse(rpcResponse: RpcResponse[JsonNode]): bool = + return not rpcResponse.error.isNil + +proc addSession*(sessionJson: string): bool = + try: + let rpcRes = addWalletConnectSession(sessionJson) + return isErrorResponse(rpcRes): + except Exception as e: + warn "AddWalletConnectSession failed: ", "msg", e.msg + return false diff --git a/storybook/pages/DAppsWorkflowPage.qml b/storybook/pages/DAppsWorkflowPage.qml index 8561821057..08c71a7df0 100644 --- a/storybook/pages/DAppsWorkflowPage.qml +++ b/storybook/pages/DAppsWorkflowPage.qml @@ -172,7 +172,10 @@ Item { projectId: projectIdText.projectId } - dappsStore: DAppsStore { + store: DAppsStore { + function addWalletConnectSession(sessionJson) { + console.info("Persist Session", sessionJson) + } } walletStore: WalletStore { diff --git a/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml b/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml index e6c89ef9bb..d380580eb9 100644 --- a/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml +++ b/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml @@ -14,7 +14,7 @@ QtObject { id: root required property WalletConnectSDK wcSDK - required property DAppsStore dappsStore + required property DAppsStore store required property WalletStore walletStore readonly property var validAccounts: SortFilterProxyModel { @@ -75,10 +75,19 @@ QtObject { } function onApproveSessionResult(session, err) { + // Notify client + root.approveSessionResult(session, err) + + if (err) { + return + } + // TODO #14754: implement custom dApp notification let app_url = _d.currentSessionProposal ? _d.currentSessionProposal.params.proposer.metadata.url : "-" Global.displayToastMessage(qsTr("Connected to %1 via WalletConnect").arg(app_url), "", "checkmark-circle", false, Constants.ephemeralNotificationType.success, "") - root.approveSessionResult(session, err) + + // Persist session + store.addWalletConnectSession(JSON.stringify(session)) } function onRejectSessionResult(err) { diff --git a/ui/app/AppLayouts/Wallet/stores/RootStore.qml b/ui/app/AppLayouts/Wallet/stores/RootStore.qml index bb70114d0c..7450d316b8 100644 --- a/ui/app/AppLayouts/Wallet/stores/RootStore.qml +++ b/ui/app/AppLayouts/Wallet/stores/RootStore.qml @@ -56,6 +56,7 @@ QtObject { property var activityDetailsController: walletSectionInst.activityDetailsController property string signingPhrase: walletSectionInst.signingPhrase property string mnemonicBackedUp: walletSectionInst.isMnemonicBackedUp + property var walletConnectModule: walletSectionInst.walletConnectModule property CollectiblesStore collectiblesStore: CollectiblesStore {} diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index 023e6b3d9c..87895ec733 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -2043,7 +2043,8 @@ Item { projectId: WalletStore.RootStore.appSettings.walletConnectProjectID } - dappsStore: DAppsStore { + store: DAppsStore { + module: WalletStore.RootStore.walletConnectModule } walletStore: appMain.rootStore.profileSectionStore.walletStore diff --git a/ui/imports/shared/stores/DAppsStore.qml b/ui/imports/shared/stores/DAppsStore.qml index d05087f6fe..ded2ca0c60 100644 --- a/ui/imports/shared/stores/DAppsStore.qml +++ b/ui/imports/shared/stores/DAppsStore.qml @@ -1,3 +1,9 @@ import QtQuick 2.15 -QtObject {} \ No newline at end of file +QtObject { + required property var module + + function addWalletConnectSession(sessionJson) { + module.addWalletConnectSession(sessionJson) + } +} \ No newline at end of file