diff --git a/.gitignore b/.gitignore index 349fc816ab..50703848bf 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,7 @@ status-react-translations/ /.update.timestamp notarization.log status-desktop.log +<<<<<<< HEAD +======= +nim_status_client.log +>>>>>>> bcc756eb3... refactor(@wallet): saved address from wallet2 diff --git a/src/app/boot/app_controller.nim b/src/app/boot/app_controller.nim index 6fff428b51..f0d03ed80f 100644 --- a/src/app/boot/app_controller.nim +++ b/src/app/boot/app_controller.nim @@ -28,6 +28,7 @@ import ../../app_service/service/about/service as about_service import ../../app_service/service/node_configuration/service as node_configuration_service import ../../app_service/service/network/service as network_service import ../../app_service/service/activity_center/service as activity_center_service +import ../../app_service/service/saved_address/service as saved_address_service import ../modules/startup/module as startup_module import ../modules/main/module as main_module @@ -95,6 +96,7 @@ type mnemonicService: mnemonic_service.Service privacyService: privacy_service.Service nodeConfigurationService: node_configuration_service.Service + savedAddressService: saved_address_service.Service # Modules startupModule: startup_module.AccessInterface @@ -169,6 +171,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController = result.privacyService = privacy_service.newService() result.ensService = ens_service.newService() result.providerService = provider_service.newService(result.dappPermissionsService, result.settingsService, result.ensService) + result.savedAddressService = saved_address_service.newService() # Modules result.startupModule = startup_module.newModule[AppController]( @@ -178,10 +181,10 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController = result.accountsService ) result.mainModule = main_module.newModule[AppController]( - result, + result, statusFoundation.status.events, result.keychainService, - result.accountsService, + result.accountsService, result.chatService, result.communityService, result.messageService, @@ -200,7 +203,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController = result.privacyService, result.providerService, result.stickersService, - result.activityCenterService + result.activityCenterService, + result.savedAddressService ) # Do connections @@ -237,6 +241,7 @@ proc delete*(self: AppController) = self.nodeConfigurationService.delete self.settingsService.delete self.stickersService.delete + self.savedAddressService.delete proc startupDidLoad*(self: AppController) = singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant) @@ -276,6 +281,7 @@ proc load(self: AppController) = self.stickersService.init() self.networkService.init() self.activityCenterService.init() + self.savedAddressService.init() let pubKey = self.settingsService.getPublicKey() singletonInstance.localAccountSensitiveSettings.setFileName(pubKey) diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index e5b0efd0b6..f3adfd0016 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -33,6 +33,7 @@ import ../../../app_service/service/mnemonic/service as mnemonic_service import ../../../app_service/service/privacy/service as privacy_service import ../../../app_service/service/stickers/service as stickers_service import ../../../app_service/service/activity_center/service as activity_center_service +import ../../../app_service/service/saved_address/service as saved_address_service import eventemitter @@ -66,7 +67,7 @@ proc newModule*[T]( transactionService: transaction_service.Service, collectibleService: collectible_service.Service, walletAccountService: wallet_account_service.Service, - bookmarkService: bookmark_service.ServiceInterface, + bookmarkService: bookmark_service.ServiceInterface, profileService: profile_service.ServiceInterface, settingsService: settings_service.ServiceInterface, contactsService: contacts_service.Service, @@ -77,22 +78,27 @@ proc newModule*[T]( privacyService: privacy_service.ServiceInterface, providerService: provider_service.ServiceInterface, stickersService: stickers_service.Service, - activityCenterService: activity_center_service.Service - ): Module[T] = + activityCenterService: activity_center_service.Service, + savedAddressService: saved_address_service.ServiceInterface +): Module[T] = result = Module[T]() result.delegate = delegate result.view = view.newView(result) result.viewVariant = newQVariant(result.view) - result.controller = controller.newController(result, events, settingsService, keychainService, accountsService, - chatService, communityService) + result.controller = controller.newController( + result, events, settingsService, keychainService, accountsService, chatService, communityService + ) result.moduleLoaded = false # Submodules result.chatSectionModule = chat_section_module.newModule(result, events, conf.CHAT_SECTION_ID, false, contactsService, chatService, communityService, messageService) result.communitySectionsModule = initOrderedTable[string, chat_section_module.AccessInterface]() - result.walletSectionModule = wallet_section_module.newModule[Module[T]](result, events, tokenService, - transactionService, collectible_service, walletAccountService, settingsService) + result.walletSectionModule = wallet_section_module.newModule[Module[T]]( + result, events, tokenService, + transactionService, collectible_service, walletAccountService, + settingsService, savedAddressService + ) result.browserSectionModule = browser_section_module.newModule(result, bookmarkService, settingsService, dappPermissionsService, providerService) result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService, @@ -139,7 +145,7 @@ method load*[T]( c.id, true, contactsService, - chatService, + chatService, communityService, messageService ) @@ -349,4 +355,4 @@ method onActiveChatChange*[T](self: Module[T], sectionId: string, chatId: string self.appSearchModule.onActiveChatChange(sectionId, chatId) method getAppSearchModule*[T](self: Module[T]): QVariant = - self.appSearchModule.getModuleAsVariant() \ No newline at end of file + self.appSearchModule.getModuleAsVariant() diff --git a/src/app/modules/main/wallet_section/io_interface.nim b/src/app/modules/main/wallet_section/io_interface.nim index cd9e169d08..7d081fa43c 100644 --- a/src/app/modules/main/wallet_section/io_interface.nim +++ b/src/app/modules/main/wallet_section/io_interface.nim @@ -45,6 +45,9 @@ method currentAccountModuleDidLoad*(self: AccessInterface) {.base.} = method transactionsModuleDidLoad*(self: AccessInterface) {.base.} = raise newException(ValueError, "No implementation available") +method savedAddressesModuleDidLoad*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + type ## Abstract class (concept) which must be implemented by object/s used in this ## module. diff --git a/src/app/modules/main/wallet_section/module.nim b/src/app/modules/main/wallet_section/module.nim index a1ee556b34..3c6020623f 100644 --- a/src/app/modules/main/wallet_section/module.nim +++ b/src/app/modules/main/wallet_section/module.nim @@ -11,6 +11,7 @@ import ./all_tokens/module as all_tokens_module import ./collectibles/module as collectibles_module import ./current_account/module as current_account_module import ./transactions/module as transactions_module +import ./saved_addresses/module as saved_addresses_module import ../../../../app_service/service/token/service as token_service @@ -18,6 +19,7 @@ import ../../../../app_service/service/transaction/service as transaction_servic import ../../../../app_service/service/collectible/service as collectible_service import ../../../../app_service/service/wallet_account/service as wallet_account_service import ../../../../app_service/service/settings/service_interface as settings_service +import ../../../../app_service/service/saved_address/service_interface as saved_address_service import io_interface export io_interface @@ -36,6 +38,7 @@ type collectiblesModule: collectibles_module.AccessInterface currentAccountModule: current_account_module.AccessInterface transactionsModule: transactions_module.AccessInterface + savedAddressesModule: saved_addresses_module.AccessInterface proc newModule*[T]( delegate: T, @@ -44,7 +47,8 @@ proc newModule*[T]( transactionService: transaction_service.Service, collectibleService: collectible_service.ServiceInterface, walletAccountService: wallet_account_service.ServiceInterface, - settingsService: settings_service.ServiceInterface + settingsService: settings_service.ServiceInterface, + savedAddressService: saved_address_service.ServiceInterface, ): Module[T] = result = Module[T]() result.delegate = delegate @@ -59,6 +63,7 @@ proc newModule*[T]( result.collectiblesModule = collectibles_module.newModule(result, events, collectibleService, walletAccountService) result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService) result.transactionsModule = transactions_module.newModule(result, events, transactionService, walletAccountService) + result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService) method delete*[T](self: Module[T]) = self.accountTokensModule.delete @@ -67,6 +72,7 @@ method delete*[T](self: Module[T]) = self.collectiblesModule.delete self.currentAccountModule.delete self.transactionsModule.delete + self.savedAddressesModule.delete self.controller.delete self.view.delete @@ -102,6 +108,7 @@ method load*[T](self: Module[T]) = self.collectiblesModule.load() self.currentAccountModule.load() self.transactionsModule.load() + self.savedAddressesModule.load() method isLoaded*[T](self: Module[T]): bool = return self.moduleLoaded @@ -125,6 +132,9 @@ proc checkIfModuleDidLoad[T](self: Module[T]) = if(not self.transactionsModule.isLoaded()): return + if(not self.savedAddressesModule.isLoaded()): + return + self.switchAccount(0) let currency = self.controller.getCurrency() let signingPhrase = self.controller.getSigningPhrase() @@ -155,3 +165,6 @@ method currentAccountModuleDidLoad*[T](self: Module[T]) = method transactionsModuleDidLoad*[T](self: Module[T]) = self.checkIfModuleDidLoad() + +method savedAddressesModuleDidLoad*[T](self: Module[T]) = + self.checkIfModuleDidLoad() diff --git a/src/app/modules/main/wallet_section/saved_addresses/controller.nim b/src/app/modules/main/wallet_section/saved_addresses/controller.nim new file mode 100644 index 0000000000..1161e721e1 --- /dev/null +++ b/src/app/modules/main/wallet_section/saved_addresses/controller.nim @@ -0,0 +1,33 @@ +import ./controller_interface +import io_interface +import ../../../../../app_service/service/saved_address/service as saved_address_service + +export controller_interface + +type + Controller* = ref object of controller_interface.AccessInterface + delegate: io_interface.AccessInterface + savedAddressService: saved_address_service.ServiceInterface + +proc newController*( + delegate: io_interface.AccessInterface, + savedAddressService: saved_address_service.ServiceInterface +): Controller = + result = Controller() + result.delegate = delegate + result.savedAddressService = savedAddressService + +method delete*(self: Controller) = + discard + +method init*(self: Controller) = + discard + +method getSavedAddresses*(self: Controller): seq[saved_address_service.SavedAddressDto] = + return self.savedAddressService.getSavedAddresses() + +method addSavedAddress*(self: Controller, name, address: string) = + self.savedAddressService.addSavedAddress(name, address) + +method deleteSavedAddress*(self: Controller, address: string) = + self.savedAddressService.deleteSavedAddress(address) diff --git a/src/app/modules/main/wallet_section/saved_addresses/controller_interface.nim b/src/app/modules/main/wallet_section/saved_addresses/controller_interface.nim new file mode 100644 index 0000000000..b067020da9 --- /dev/null +++ b/src/app/modules/main/wallet_section/saved_addresses/controller_interface.nim @@ -0,0 +1,26 @@ +import ../../../../../app_service/service/saved_address/service_interface as saved_address_service + +type + AccessInterface* {.pure inheritable.} = ref object of RootObj + ## Abstract class for any input/interaction with this module. + +method delete*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method init*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method getSavedAddresses*(self: AccessInterface): seq[saved_address_service.SavedAddressDto] {.base.} = + raise newException(ValueError, "No implementation available") + +method addSavedAddresses*(self: AccessInterface, name, address: string) {.base.} = + raise newException(ValueError, "No implementation available") + +method deleteSavedAddresses*(self: AccessInterface, address: string) {.base.} = + raise newException(ValueError, "No implementation available") + +type + ## Abstract class (concept) which must be implemented by object/s used in this + ## module. + DelegateInterface* = concept c + diff --git a/src/app/modules/main/wallet_section/saved_addresses/io_interface.nim b/src/app/modules/main/wallet_section/saved_addresses/io_interface.nim new file mode 100644 index 0000000000..56e95a33da --- /dev/null +++ b/src/app/modules/main/wallet_section/saved_addresses/io_interface.nim @@ -0,0 +1,20 @@ +type + AccessInterface* {.pure inheritable.} = ref object of RootObj + ## Abstract class for any input/interaction with this module. + +method delete*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method load*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method isLoaded*(self: AccessInterface): bool {.base.} = + raise newException(ValueError, "No implementation available") + +method viewDidLoad*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +type + ## Abstract class (concept) which must be implemented by object/s used in this + ## module. + DelegateInterface* = concept c diff --git a/src/app/modules/main/wallet_section/saved_addresses/item.nim b/src/app/modules/main/wallet_section/saved_addresses/item.nim new file mode 100644 index 0000000000..9b44189576 --- /dev/null +++ b/src/app/modules/main/wallet_section/saved_addresses/item.nim @@ -0,0 +1,25 @@ +import strformat + +type + Item* = object + name: string + address: string + +proc initItem*( + name: string, + address: string, +): Item = + result.name = name + result.address = address + +proc `$`*(self: Item): string = + result = fmt"""AllTokensItem( + name: {self.name}, + address: {self.address}, + ]""" + +proc getName*(self: Item): string = + return self.name + +proc getAddress*(self: Item): string = + return self.address diff --git a/src/app/modules/main/wallet_section/saved_addresses/model.nim b/src/app/modules/main/wallet_section/saved_addresses/model.nim new file mode 100644 index 0000000000..28d764cb78 --- /dev/null +++ b/src/app/modules/main/wallet_section/saved_addresses/model.nim @@ -0,0 +1,76 @@ +import NimQml, Tables, strutils, strformat + +import ./item + +type + ModelRole {.pure.} = enum + Name = UserRole + 1, + Address + +QtObject: + type + Model* = ref object of QAbstractListModel + items: seq[Item] + + proc delete(self: Model) = + self.items = @[] + self.QAbstractListModel.delete + + proc setup(self: Model) = + self.QAbstractListModel.setup + + proc newModel*(): Model = + new(result, delete) + result.setup + + proc `$`*(self: Model): string = + for i in 0 ..< self.items.len: + result &= fmt"""[{i}]:({$self.items[i]})""" + + proc countChanged(self: Model) {.signal.} + + proc getCount*(self: Model): int {.slot.} = + self.items.len + + QtProperty[int] count: + read = getCount + notify = countChanged + + method rowCount(self: Model, index: QModelIndex = nil): int = + return self.items.len + + method roleNames(self: Model): Table[int, string] = + { + ModelRole.Name.int:"name", + ModelRole.Address.int:"address", + }.toTable + + method data(self: Model, index: QModelIndex, role: int): QVariant = + if (not index.isValid): + return + + if (index.row < 0 or index.row >= self.items.len): + return + + let item = self.items[index.row] + let enumRole = role.ModelRole + + case enumRole: + of ModelRole.Name: + result = newQVariant(item.getName()) + of ModelRole.Address: + result = newQVariant(item.getAddress()) + + proc rowData(self: Model, index: int, column: string): string {.slot.} = + if (index >= self.items.len): + return + let item = self.items[index] + case column: + of "name": result = $item.getName() + of "address": result = $item.getAddress() + + proc setItems*(self: Model, items: seq[Item]) = + self.beginResetModel() + self.items = items + self.endResetModel() + self.countChanged() diff --git a/src/app/modules/main/wallet_section/saved_addresses/module.nim b/src/app/modules/main/wallet_section/saved_addresses/module.nim new file mode 100644 index 0000000000..954e91c87a --- /dev/null +++ b/src/app/modules/main/wallet_section/saved_addresses/module.nim @@ -0,0 +1,53 @@ +import NimQml, sugar, sequtils +import eventemitter +import ../io_interface as delegate_interface +import ../../../../global/global_singleton +import ../../../../../app_service/service/saved_address/service as saved_address_service + +import ./io_interface, ./view, ./controller, ./item + +export io_interface + +type + Module* = ref object of io_interface.AccessInterface + delegate: delegate_interface.AccessInterface + events: EventEmitter + view: View + moduleLoaded: bool + controller: controller.AccessInterface + +proc newModule*( + delegate: delegate_interface.AccessInterface, + events: EventEmitter, + savedAddressService: saved_address_service.ServiceInterface, +): Module = + result = Module() + result.delegate = delegate + result.events = events + result.view = newView(result) + result.controller = newController(result, savedAddressService) + result.moduleLoaded = false + +method delete*(self: Module) = + self.view.delete + +method load*(self: Module) = + singletonInstance.engine.setRootContextProperty("walletSectionSavedAddresses", newQVariant(self.view)) + + let savedAddresses = self.controller.getSavedAddresses() + self.view.setItems( + savedAddresses.map(s => initItem( + s.name, + s.address, + )) + ) + + self.controller.init() + self.view.load() + +method isLoaded*(self: Module): bool = + return self.moduleLoaded + +method viewDidLoad*(self: Module) = + self.moduleLoaded = true + self.delegate.savedAddressesModuleDidLoad() diff --git a/src/app/modules/main/wallet_section/saved_addresses/view.nim b/src/app/modules/main/wallet_section/saved_addresses/view.nim new file mode 100644 index 0000000000..1d34b64ba2 --- /dev/null +++ b/src/app/modules/main/wallet_section/saved_addresses/view.nim @@ -0,0 +1,38 @@ +import NimQml + +import ./model, ./item +import ./io_interface + +QtObject: + type + View* = ref object of QObject + delegate: io_interface.AccessInterface + model: Model + modelVariant: QVariant + + proc delete*(self: View) = + self.model.delete + self.modelVariant.delete + self.QObject.delete + + proc newView*(delegate: io_interface.AccessInterface): View = + new(result, delete) + result.QObject.setup + result.delegate = delegate + result.model = newModel() + result.modelVariant = newQVariant(result.model) + + proc load*(self: View) = + self.delegate.viewDidLoad() + + proc modelChanged*(self: View) {.signal.} + + proc getModel(self: View): QVariant {.slot.} = + return self.modelVariant + + QtProperty[QVariant] model: + read = getModel + notify = modelChanged + + proc setItems*(self: View, items: seq[Item]) = + self.model.setItems(items) diff --git a/src/app/modules/main/wallet_section/view.nim b/src/app/modules/main/wallet_section/view.nim index 75e1e64699..2a08fb5140 100644 --- a/src/app/modules/main/wallet_section/view.nim +++ b/src/app/modules/main/wallet_section/view.nim @@ -71,4 +71,4 @@ QtObject: self.currentCurrency = currency self.signingPhrase = signingPhrase self.isMnemonicBackedUp = mnemonicBackedUp - self.currentCurrencyChanged() \ No newline at end of file + self.currentCurrencyChanged() diff --git a/src/app_service/service/saved_address/dto.nim b/src/app_service/service/saved_address/dto.nim new file mode 100644 index 0000000000..4c85365e0c --- /dev/null +++ b/src/app_service/service/saved_address/dto.nim @@ -0,0 +1,22 @@ +import json, sequtils, sugar + +include ../../common/json_utils + +type + SavedAddressDto* = ref object of RootObj + name*: string + address*: string + +proc newSavedAddressDto*( + name: string, + address: string, +): SavedAddressDto = + return SavedAddressDto( + name: name, + address: address, + ) + +proc toSavedAddressDto*(jsonObj: JsonNode): SavedAddressDto = + result = SavedAddressDto() + discard jsonObj.getProp("name", result.name) + discard jsonObj.getProp("address", result.address) diff --git a/src/app_service/service/saved_address/service.nim b/src/app_service/service/saved_address/service.nim new file mode 100644 index 0000000000..5ee4696462 --- /dev/null +++ b/src/app_service/service/saved_address/service.nim @@ -0,0 +1,49 @@ +import chronicles, sequtils, json + +import ./service_interface, ./dto + +import status/statusgo_backend_new/saved_addresses as backend + +export service_interface + +logScope: + topics = "saved-address-service" + +type + Service* = ref object of service_interface.ServiceInterface + savedAddresses: seq[SavedAddressDto] + +method delete*(self: Service) = + discard + +proc newService*(): Service = + result = Service() + +method init*(self: Service) = + try: + let response = backend.getSavedAddresses() + + self.savedAddresses = map( + response.result.getElems(), + proc(x: JsonNode): SavedAddressDto = toSavedAddressDto(x) + ) + + except Exception as e: + error "error: ", methodName="init", errName = e.name, errDesription = e.msg + +method getSavedAddresses(self: Service): seq[SavedAddressDto] = + return self.savedAddresses + +method addSavedAddress(self: Service, name, address: string) = + try: + discard backend.addSavedAddress(name, address) + except Exception as e: + let errDesription = e.msg + error "error: ", errDesription + return + +method deleteSavedAddress(self: Service, address: string) = + try: + discard backend.deleteSavedAddress(address) + except Exception as e: + let errDesription = e.msg diff --git a/src/app_service/service/saved_address/service_interface.nim b/src/app_service/service/saved_address/service_interface.nim new file mode 100644 index 0000000000..971ee642a7 --- /dev/null +++ b/src/app_service/service/saved_address/service_interface.nim @@ -0,0 +1,22 @@ +import dto + +export dto + +type + ServiceInterface* {.pure inheritable.} = ref object of RootObj + ## Abstract class for this service access. + +method delete*(self: ServiceInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method init*(self: ServiceInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method getSavedAddresses*(self: ServiceInterface): seq[SavedAddressDto] {.base.} = + raise newException(ValueError, "No implementation available") + +method addSavedAddress*(self: ServiceInterface, name: string, address: string) {.base.} = + raise newException(ValueError, "No implementation available") + +method deleteSavedAddress*(self: ServiceInterface, address: string) {.base.} = + raise newException(ValueError, "No implementation available")