add mnemonic module

This commit is contained in:
Iuri Matias 2021-10-21 18:31:41 -04:00
parent 4b10d26865
commit 7c8f3f5923
21 changed files with 282 additions and 21 deletions

View File

@ -13,6 +13,7 @@ import ../../app_service/service/wallet_account/service as wallet_account_servic
import ../../app_service/service/setting/service as setting_service
import ../../app_service/service/bookmarks/service as bookmark_service
import ../../app_service/service/dapp_permissions/service as dapp_permissions_service
import ../../app_service/service/mnemonic/service as mnemonic_service
import ../core/local_account_settings
import ../../app_service/service/profile/service as profile_service
@ -77,6 +78,7 @@ type
settingsService: settings_service.Service
aboutService: about_service.Service
languageService: language_service.Service
mnemonicService: mnemonic_service.Service
# Core
localAppSettingsVariant: QVariant
@ -136,6 +138,7 @@ proc newAppController*(appService: AppService): AppController =
result.aboutService = about_service.newService()
result.dappPermissionsService = dapp_permissions_service.newService()
result.languageService = language_service.newService()
result.mnemonicService = mnemonic_service.newService()
# Core
result.localAppSettingsVariant = newQVariant(singletonInstance.localAppSettings)
@ -167,7 +170,8 @@ proc newAppController*(appService: AppService): AppController =
result.contactsService,
result.aboutService,
result.dappPermissionsService,
result.languageService
result.languageService,
result.mnemonicService
)
#################################################

View File

@ -27,6 +27,7 @@ import ../../../app_service/service/settings/service as settings_service
import ../../../app_service/service/contacts/service as contacts_service
import ../../../app_service/service/about/service as about_service
import ../../../app_service/service/language/service as language_service
import ../../../app_service/service/mnemonic/service as mnemonic_service
export io_interface
@ -71,7 +72,8 @@ proc newModule*[T](
contactsService: contacts_service.ServiceInterface,
aboutService: about_service.ServiceInterface,
dappPermissionsService: dapp_permissions_service.ServiceInterface,
languageService: language_service.ServiceInterface
languageService: language_service.ServiceInterface,
mnemonicService: mnemonic_service.ServiceInterface
): Module[T] =
result = Module[T]()
result.delegate = delegate
@ -102,7 +104,7 @@ proc newModule*[T](
)
result.browserSectionModule = browser_section_module.newModule(result, bookmarkService, settingsService, dappPermissionsService)
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService, profileService, contactsService, aboutService, languageService)
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService, profileService, contactsService, aboutService, languageService, mnemonicService)
method delete*[T](self: Module[T]) =
self.chatSectionModule.delete

View File

@ -6,6 +6,7 @@ import ../../../../app_service/service/profile/service as profile_service
import ../../../../app_service/service/accounts/service as accounts_service
import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/language/service as language_service
import ../../../../app_service/service/mnemonic/service as mnemonic_service
export controller_interface
@ -17,14 +18,16 @@ type
settingsService: settings_service.ServiceInterface
accountsService: accounts_service.ServiceInterface
languageService: language_service.ServiceInterface
mnemonicService: mnemonic_service.ServiceInterface
proc newController*[T](delegate: T, accountsService: accounts_service.ServiceInterface, settingsService: settings_service.ServiceInterface, profileService: profile_service.ServiceInterface, languageService: language_service.ServiceInterface): Controller[T] =
proc newController*[T](delegate: T, accountsService: accounts_service.ServiceInterface, settingsService: settings_service.ServiceInterface, profileService: profile_service.ServiceInterface, languageService: language_service.ServiceInterface, mnemonicService: mnemonic_service.ServiceInterface): Controller[T] =
result = Controller[T]()
result.delegate = delegate
result.profileService = profileService
result.settingsService = settingsService
result.accountsService = accountsService
result.languageService = languageService
result.mnemonicService = mnemonicService
method delete*[T](self: Controller[T]) =
discard

View File

@ -0,0 +1,32 @@
import ./controller_interface
import ../../../../../app_service/service/mnemonic/service as mnemonic_service
export controller_interface
type
Controller*[T: controller_interface.DelegateInterface] = ref object of controller_interface.AccessInterface
delegate: T
mnemonicService: mnemonic_service.ServiceInterface
proc newController*[T](delegate: T, mnemonicService: mnemonic_service.ServiceInterface): Controller[T] =
result = Controller[T]()
result.delegate = delegate
result.mnemonicService = mnemonicService
method delete*[T](self: Controller[T]) =
discard
method init*[T](self: Controller[T]) =
discard
method isBackedUp*[T](self: Controller[T]): bool =
return self.mnemonicService.isBackedUp()
method getMnemonic*[T](self: Controller[T]): string =
return self.mnemonicService.getMnemonic()
method remove*[T](self: Controller[T]) =
self.mnemonicService.remove()
method getWord*[T](self: Controller[T], index: int): string =
return self.mnemonicService.getWord(index)

View File

@ -0,0 +1,27 @@
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 isBackedUp*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getMnemonic*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method remove*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getWord*(self: AccessInterface, index: int): 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

View File

@ -0,0 +1,29 @@
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 isBackedUp*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getMnemonic*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method remove*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getWord*(self: AccessInterface, index: int): 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

View File

@ -0,0 +1,47 @@
import NimQml, Tables
import ./io_interface, ./view, ./controller
import ../../../../core/global_singleton
import ../../../../../app_service/service/mnemonic/service as mnemonic_service
export io_interface
type
Module*[T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface
delegate: T
controller: controller.AccessInterface
view: View
viewVariant: QVariant
moduleLoaded: bool
proc newModule*[T](delegate: T, mnemonicService: mnemonic_service.ServiceInterface): Module[T] =
result = Module[T]()
result.delegate = delegate
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController[Module[T]](result, mnemonicService)
result.moduleLoaded = false
singletonInstance.engine.setRootContextProperty("mnemonicModule", result.viewVariant)
method delete*[T](self: Module[T]) =
self.view.delete
method load*[T](self: Module[T]) =
self.moduleLoaded = true
method isLoaded*[T](self: Module[T]): bool =
return self.moduleLoaded
method isBackedUp*[T](self: Module[T]): bool =
return self.controller.isBackedup()
method getMnemonic*[T](self: Module[T]): string =
return self.controller.getMnemonic()
method remove*[T](self: Module[T]) =
self.controller.remove()
method getWord*[T](self: Module[T], index: int): string =
return self.controller.getWord(index)

View File

@ -0,0 +1,39 @@
import NimQml
import ./io_interface
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
proc delete*(self: View) =
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete)
result.QObject.setup
result.delegate = delegate
proc isBackedUp*(self: View): bool {.slot.} =
return self.delegate.isBackedup()
proc seedPhraseRemoved*(self: View) {.signal.}
QtProperty[bool] isBackedUp:
read = isBackedUp
notify = seedPhraseRemoved
proc getMnemonic*(self: View): QVariant {.slot.} =
return newQVariant(self.delegate.getMnemonic())
QtProperty[QVariant] get:
read = getMnemonic
notify = seedPhraseRemoved
proc remove*(self: View) {.slot.} =
self.delegate.remove()
self.seedPhraseRemoved()
proc getWord*(self: View, index: int): string {.slot.} =
return self.delegate.getWord(index)

View File

@ -8,10 +8,12 @@ import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/contacts/service as contacts_service
import ../../../../app_service/service/about/service as about_service
import ../../../../app_service/service/language/service as language_service
import ../../../../app_service/service/mnemonic/service as mnemonic_service
import ./profile/module as profile_module
import ./contacts/module as contacts_module
import ./language/module as language_module
import ./mnemonic/module as mnemonic_module
import ./about/module as about_module
import eventemitter
@ -29,6 +31,7 @@ type
profileModule: profile_module.AccessInterface
languageModule: language_module.AccessInterface
contactsModule: contacts_module.AccessInterface
mnemonicModule: mnemonic_module.AccessInterface
aboutModule: about_module.AccessInterface
proc newModule*[T](delegate: T,
@ -38,20 +41,21 @@ proc newModule*[T](delegate: T,
profileService: profile_service.ServiceInterface,
contactsService: contacts_service.ServiceInterface,
aboutService: about_service.ServiceInterface,
languageService: language_service.ServiceInterface
languageService: language_service.ServiceInterface,
mnemonicService: mnemonic_service.ServiceInterface
):
Module[T] =
result = Module[T]()
result.delegate = delegate
result.view = view.newView()
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController[Module[T]](result, accountsService, settingsService, profileService, languageService)
result.controller = controller.newController[Module[T]](result, accountsService, settingsService, profileService, languageService, mnemonicService)
result.moduleLoaded = false
result.profileModule = profile_module.newModule(result, accountsService, settingsService, profileService)
result.contactsModule = contacts_module.newModule(result, events, contactsService, accountsService)
result.languageModule = language_module.newModule(result, languageService)
result.mnemonicModule = mnemonic_module.newModule(result, mnemonicService)
result.aboutModule = about_module.newModule(result, aboutService)
singletonInstance.engine.setRootContextProperty("profileSectionModule", result.viewVariant)
@ -60,6 +64,7 @@ method delete*[T](self: Module[T]) =
self.profileModule.delete
self.contactsModule.delete
self.languageModule.delete
self.mnemonicModule.delete
self.aboutModule.delete
self.view.delete
@ -70,6 +75,7 @@ method load*[T](self: Module[T]) =
self.profileModule.load()
self.contactsModule.load()
self.languageModule.load()
self.mnemonicModule.load()
self.aboutModule.load()
self.moduleLoaded = true

View File

@ -50,5 +50,3 @@ QtObject:
proc getWord*(self: MnemonicView, idx: int): string {.slot.} =
let mnemonics = self.status.settings.getSetting[:string](Setting.Mnemonic, "").split(" ")
return mnemonics[idx]

View File

View File

@ -0,0 +1,49 @@
import json, json_serialization, sequtils, chronicles, strutils
import options
import status/statusgo_backend/settings as status_go_settings
import status/statusgo_backend/accounts as status_accounts
from status/types/setting import Setting
import ./service_interface, ./dto
export service_interface
logScope:
topics = "settings-service"
type
Service* = ref object of ServiceInterface
isMnemonicBackedUp: Option[bool]
method delete*(self: Service) =
discard
proc newService*(): Service =
result = Service()
method init*(self: Service) =
try:
echo "init"
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
return
method isBackedUp*(self: Service): bool =
if self.isMnemonicBackedUp.isNone:
self.isMnemonicBackedUp = some(status_go_settings.getSetting[string](Setting.Mnemonic, "") == "")
self.isMnemonicBackedUp.get()
method getMnemonic*(self: Service): string =
let mnemonic = status_go_settings.getSetting[string](Setting.Mnemonic, "")
return mnemonic
method remove*(self: Service) =
discard status_go_settings.saveSetting(Setting.Mnemonic, "")
self.isMnemonicBackedUp = some(true)
method getWord*(self: Service, index: int): string =
let mnemonics = status_go_settings.getSetting[string](Setting.Mnemonic, "").split(" ")
return mnemonics[index]

View File

@ -0,0 +1,25 @@
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 isBackedUp*(self: ServiceInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getMnemonic*(self: ServiceInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method remove*(self: ServiceInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getWord*(self: ServiceInterface, index: int): string {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -42,7 +42,7 @@ Column {
selected: root.selectedMenuItem === model.menu_id
onClicked: root.menuItemClicked(model)
visible: model.ifEnabled !== "browser" || root.browserMenuItemEnabled
badge.value: (!profileModel.mnemonic.isBackedUp && (settingsMenuDelegate.title ===
badge.value: (!mnemonicModule.isBackedUp && (settingsMenuDelegate.title ===
settingsMenuItems.itemAt(0).text)) ? 1 : 0
}
}

View File

@ -74,7 +74,7 @@ ModalPopup {
Repeater {
id: mnemonicRepeater
model: profileModel.mnemonic.get.split(" ")
model: mnemonicModule.get.split(" ")
Rectangle {
id: word
height: 40
@ -208,7 +208,7 @@ ModalPopup {
//% "You will not be able to see the whole seed phrase again"
confirmationText: qsTrId("are-you-sure-description")
onConfirmButtonClicked: {
profileModel.mnemonic.remove()
mnemonicModule.remove()
popup.close();
confirmPopup.close();
}
@ -261,7 +261,7 @@ ModalPopup {
seedWord1Idx = Math.floor(Math.random() * 12);
} else {
if(seedWord2Idx == -1){
if(profileModel.mnemonic.getWord(seedWord1Idx) !== txtFieldWord.text){
if(mnemonicModule.getWord(seedWord1Idx) !== txtFieldWord.text){
//% "Wrong word"
validationError = qsTrId("wrong-word");
return;
@ -274,7 +274,7 @@ ModalPopup {
seedWord2Idx = Math.floor(Math.random() * 12);
} while(seedWord2Idx == seedWord1Idx);
} else {
if(profileModel.mnemonic.getWord(seedWord2Idx) !== txtFieldWord.text){
if(mnemonicModule.getWord(seedWord2Idx) !== txtFieldWord.text){
//% "Wrong word"
validationError = qsTrId("wrong-word");
return;

View File

@ -10,6 +10,7 @@ QtObject {
property var contactsModuleInst: contactsModule
property var aboutModuleInst: aboutModule
property var languageModuleInst: languageModule
property var mnemonicModuleInst: mnemonicModule
property var chatsModelInst: chatsModel
property var utilsModelInst: utilsModel
@ -45,7 +46,7 @@ QtObject {
property bool automaticMailserverSelection: profileModelInst.mailservers.automaticSelection
property bool isWakuV2LightClient: nodeModelInst.WakuV2LightClient
property bool devicesSetup: profileModelInst.devices.isSetup
property bool mnemonicBackedUp: profileModelInst.mnemonic.isBackedUp
property bool mnemonicBackedUp: mnemonicModuleInst.isBackedUp
property bool messagesFromContactsOnly: profile.messagesFromContactsOnly
property int profile_id: 0

View File

@ -46,7 +46,7 @@ Item {
anchors.rightMargin: -Style.current.padding
//% "Backup Seed Phrase"
title: qsTrId("backup-seed-phrase")
enabled: !root.store.profileModelInst.mnemonic.isBackedUp
enabled: !root.store.mnemonicBackedUp
implicitHeight: 52
components: [
StatusBadge {

View File

@ -21,7 +21,7 @@ QtObject {
property string signingPhrase: walletModel.utilsView.signingPhrase
property bool mnemonicBackedUp: profileModel.mnemonic.isBackedUp
property bool mnemonicBackedUp: mnemonicModule.isBackedUp
property var collectiblesList: walletModel.collectiblesView.collectiblesLists

View File

@ -44,7 +44,7 @@ Item {
id: seedPhraseWarning
width: parent.width
anchors.top: parent.top
visible: !walletView.store.profileModelInst.mnemonic.isBackedUp
visible: !mnemonicModule.isBackedUp
}
StatusAppTwoPanelLayout {

View File

@ -35,7 +35,7 @@ Item {
primaryText: qsTr("Back up seed phrase")
secondaryText: qsTr("Back up your seed phrase now to secure this account")
button.text: qsTr("Back up seed phrase")
button.enabled: !root.store.profileModelInst.mnemonic.isBackedUp
button.enabled: !mnemonicModule.isBackedUp
button.onClicked: backupSeedModal.open()
}

View File

@ -27,7 +27,6 @@ import StatusQ.Layout 0.1
import StatusQ.Popups 0.1
import StatusQ.Core 0.1
Item {
id: appMain
anchors.fill: parent
@ -593,7 +592,7 @@ Item {
ignoreUnknownSignals: true
enabled: removeMnemonicAfterLogin
onInitialized: {
profileModel.mnemonic.remove()
mnemonicModule.remove()
}
}