diff --git a/src/app/onboarding/view.nim b/src/app/onboarding/view.nim index dfe11d766f..b1fecc03a8 100644 --- a/src/app/onboarding/view.nim +++ b/src/app/onboarding/view.nim @@ -54,8 +54,8 @@ QtObject: AddressRoles.Identicon.int:"identicon", AddressRoles.Key.int:"key" }.toTable - proc storeAccountAndLogin(self: OnboardingView, selectedAccountIndex: int, password: string): string {.slot.} = - result = self.model.storeAccountAndLogin(selectedAccountIndex, password) + proc storeAccountAndLogin(self: OnboardingView, selectedAccountIndex: int, password: string) {.slot.} = + discard self.model.storeAccountAndLogin(selectedAccountIndex, password) # TODO: this is temporary and will be removed once accounts import and creation is working proc generateRandomAccountAndLogin*(self: OnboardingView) {.slot.} = diff --git a/src/app/profile/profileView.nim b/src/app/profile/profileView.nim new file mode 100644 index 0000000000..1e7936a80f --- /dev/null +++ b/src/app/profile/profileView.nim @@ -0,0 +1,58 @@ +import NimQml +import mailserversList + +QtObject: + type ProfileView* = ref object of QObject + username*: string + identicon*: string + mailserversList*: MailServersList + + proc setup(self: ProfileView) = + self.QObject.setup + + proc delete*(self: ProfileView) = + self.QObject.delete + + proc newProfileView*(): ProfileView = + new(result, delete) + result.username = "" + result.identicon = "" + result.mailserversList = newMailServersList() + result.setup + + proc username*(self: ProfileView): string {.slot.} = + result = self.username + + proc receivedUsername*(self: ProfileView, username: string) {.signal.} + + proc addMailserverToList*(self: ProfileView, name: string, endpoint: string) {.slot.} = + self.mailserversList.add(name, endpoint) + + proc setUsername*(self: ProfileView, username: string) {.slot.} = + self.username = username + self.receivedUsername(username) + + QtProperty[string] username: + read = username + write = setUsername + notify = receivedUsername + + proc identicon*(self: ProfileView): string {.slot.} = + result = self.identicon + + proc getMailserversList(self: ProfileView): QVariant {.slot.} = + return newQVariant(self.mailserversList) + + QtProperty[QVariant] mailserversList: + read = getMailserversList + + proc receivedIdenticon*(self: ProfileView, identicon: string) {.signal.} + + proc setIdenticon*(self: ProfileView, identicon: string) {.slot.} = + self.identicon = identicon + self.receivedIdenticon(identicon) + + QtProperty[string] identicon: + read = identicon + write = setIdenticon + notify = receivedIdenticon diff --git a/src/models/accounts.nim b/src/models/accounts.nim index 8e727beeb7..b88762f24d 100644 --- a/src/models/accounts.nim +++ b/src/models/accounts.nim @@ -1,5 +1,5 @@ -import json import eventemitter +import json_serialization import ../status/accounts as status_accounts import ../status/types @@ -14,37 +14,31 @@ type AccountModel* = ref object generatedAddresses*: seq[GeneratedAccount] events*: EventEmitter - subaccounts*: JsonNode #TODO use correct account, etc.. proc newAccountModel*(): AccountModel = result = AccountModel() result.events = createEventEmitter() result.generatedAddresses = @[] - result.subaccounts = %*{} proc delete*(self: AccountModel) = # delete self.generatedAddresses discard proc generateAddresses*(self: AccountModel): seq[GeneratedAccount] = - let accounts = status_accounts.generateAddresses().parseJson - for account in accounts: - var generatedAccount = account.toGeneratedAccount - - generatedAccount.name = status_accounts.generateAlias(account["publicKey"].str) - generatedAccount.photoPath = status_accounts.generateIdenticon(account["publicKey"].str) - - self.generatedAddresses.add(generatedAccount) + var accounts = status_accounts.generateAddresses() + for account in accounts.mitems: + account.name = status_accounts.generateAlias(account.derived.whisper.publicKey) + account.photoPath = status_accounts.generateIdenticon(account.derived.whisper.publicKey) + self.generatedAddresses.add(account) self.generatedAddresses # TODO: this is temporary and will be removed once accounts import and creation is working proc generateRandomAccountAndLogin*(self: AccountModel) = - let generatedAccounts = status_accounts.generateAddresses().parseJson - self.subaccounts = status_accounts.setupAccount(generatedAccounts[0], "qwerty").parseJson - self.events.emit("accountsReady", AccountArgs(account: self.subaccounts[1].toAccount)) + let generatedAccounts = status_accounts.generateAddresses() + let account = status_accounts.setupAccount(generatedAccounts[0], "qwerty") + self.events.emit("accountsReady", AccountArgs(account: account)) -proc storeAccountAndLogin*(self: AccountModel, selectedAccountIndex: int, password: string): string = +proc storeAccountAndLogin*(self: AccountModel, selectedAccountIndex: int, password: string): Account = let generatedAccount: GeneratedAccount = self.generatedAddresses[selectedAccountIndex] - result = status_accounts.setupAccount(%generatedAccount, password) - self.subaccounts = result.parseJson - self.events.emit("accountsReady", AccountArgs(account: generatedAccount.toAccount)) + result = status_accounts.setupAccount(generatedAccount, password) + self.events.emit("accountsReady", AccountArgs(account: result)) diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index 94ca9b6cd0..628d339f37 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -7,7 +7,6 @@ import app/profile/core as profile import signals/core as signals import app/onboarding/core as onboarding import state -import json import status/accounts as status_accounts import status/core as status_core import status/chat as status_chat @@ -17,6 +16,7 @@ import models/accounts import state import status/types import eventemitter +import json_serialization var signalsQObjPointer: pointer @@ -24,7 +24,7 @@ logScope: topics = "main" proc mainProc() = - let nodeAccounts = parseJson(status_accounts.initNodeAccounts()).toNodeAccounts # to be used for login + let nodeAccounts = Json.decode(status_accounts.initNodeAccounts(), seq[NodeAccount]) # to be used for login let app = newQApplication() let engine = newQQmlApplicationEngine() let signalController = signals.newController(app) diff --git a/src/status/accounts.nim b/src/status/accounts.nim index f457edd0e7..82caaf9744 100644 --- a/src/status/accounts.nim +++ b/src/status/accounts.nim @@ -6,19 +6,22 @@ import accounts/constants import nimcrypto import os import uuids +import types +import json_serialization +import chronicles proc queryAccounts*(): string = var response = callPrivateRPC("eth_accounts") result = parseJson(response)["result"][0].getStr() -proc generateAddresses*(): string = +proc generateAddresses*(): seq[GeneratedAccount] = let multiAccountConfig = %* { "n": 5, "mnemonicPhraseLength": 12, "bip39Passphrase": "", - "paths": ["m/43'/60'/1581'/0'/0", "m/44'/60'/0'/0/0"] + "paths": [PATH_WHISPER, PATH_WALLET_ROOT, PATH_DEFAULT_WALLET] } - result = $libstatus.multiAccountGenerateAndDeriveAddresses($multiAccountConfig) + result = Json.decode($libstatus.multiAccountGenerateAndDeriveAddresses($multiAccountConfig), seq[GeneratedAccount]) proc generateAlias*(publicKey: string): string = result = $libstatus.generateAlias(publicKey.toGoString) @@ -43,20 +46,20 @@ proc initNodeAccounts*(): string = discard $libstatus.initKeystore(keystoredir); result = $libstatus.openAccounts(datadir); -proc saveAccountAndLogin*(multiAccounts: JsonNode, alias: string, identicon: string, accountData: string, password: string, configJSON: string, settingsJSON: string): JsonNode = +proc saveAccountAndLogin*(multiAccounts: MultiAccounts, alias: string, identicon: string, accountData: string, password: string, configJSON: string, settingsJSON: string): Account = let hashedPassword = "0x" & $keccak_256.digest(password) let subaccountData = %* [ { - "public-key": multiAccounts[constants.PATH_DEFAULT_WALLET]["publicKey"], - "address": multiAccounts[constants.PATH_DEFAULT_WALLET]["address"], + "public-key": multiAccounts.defaultWallet.publicKey, + "address": multiAccounts.defaultWallet.address, "color": "#4360df", "wallet": true, "path": constants.PATH_DEFAULT_WALLET, "name": "Status account" }, { - "public-key": multiAccounts[constants.PATH_WHISPER]["publicKey"], - "address": multiAccounts[constants.PATH_WHISPER]["address"], + "public-key": multiAccounts.whisper.publicKey, + "address": multiAccounts.whisper.address, "name": alias, "photo-path": identicon, "path": constants.PATH_WHISPER, @@ -68,38 +71,39 @@ proc saveAccountAndLogin*(multiAccounts: JsonNode, alias: string, identicon: str let parsedSavedResult = savedResult.parseJson if parsedSavedResult["error"].getStr == "": - echo "Account saved succesfully" - subaccountData + debug "Account saved succesfully" -proc generateMultiAccounts*(account: JsonNode, password: string): JsonNode = + result = Account(name: alias, photoPath: identicon) + +proc generateMultiAccounts*(account: GeneratedAccount, password: string): MultiAccounts = let hashedPassword = "0x" & $keccak_256.digest(password) let multiAccount = %* { - "accountID": account["id"].getStr, - "paths": ["m/44'/60'/0'/0", "m/43'/60'/1581'", "m/43'/60'/1581'/0'/0", "m/44'/60'/0'/0/0"], + "accountID": account.id, + "paths": [PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET], "password": hashedPassword } var response = $libstatus.multiAccountStoreDerivedAccounts($multiAccount); - result = response.parseJson + result = Json.decode($response, MultiAccounts) -proc getAccountData*(account: JsonNode, alias: string, identicon: string): JsonNode = +proc getAccountData*(account: GeneratedAccount, alias: string, identicon: string): JsonNode = result = %* { "name": alias, - "address": account["address"].getStr, + "address": account.address, "photo-path": identicon, - "key-uid": account["keyUid"].getStr, + "key-uid": account.keyUid, "keycard-pairing": nil } -proc getAccountSettings*(account: JsonNode, alias: string, identicon: string, multiAccounts: JsonNode, defaultNetworks: JsonNode): JsonNode = +proc getAccountSettings*(account: GeneratedAccount, alias: string, identicon: string, multiAccounts: MultiAccounts, defaultNetworks: JsonNode): JsonNode = result = %* { - "key-uid": account["keyUid"].getStr, - "mnemonic": account["mnemonic"].getStr, - "public-key": multiAccounts[constants.PATH_WHISPER]["publicKey"].getStr, + "key-uid": account.keyUid, + "mnemonic": account.mnemonic, + "public-key": multiAccounts.whisper.publicKey, "name": alias, - "address": account["address"].getStr, - "eip1581-address": multiAccounts[constants.PATH_EIP_1581]["address"].getStr, - "dapps-address": multiAccounts[constants.PATH_DEFAULT_WALLET]["address"].getStr, - "wallet-root-address": multiAccounts[constants.PATH_WALLET_ROOT]["address"].getStr, + "address": account.address, + "eip1581-address": multiAccounts.eip1581.address, + "dapps-address": multiAccounts.defaultWallet.address, + "wallet-root-address": multiAccounts.walletRoot.address, "preview-privacy?": true, "signing-phrase": generateSigningPhrase(3), "log-level": "INFO", @@ -116,14 +120,14 @@ proc getAccountSettings*(account: JsonNode, alias: string, identicon: string, mu "installation-id": $genUUID() } -proc setupAccount*(account: JsonNode, password: string): string = +proc setupAccount*(account: GeneratedAccount, password: string): Account = let multiAccounts = generateMultiAccounts(account, password) - let whisperPubKey = account["derived"][constants.PATH_WHISPER]["publicKey"].getStr - let alias = $libstatus.generateAlias(whisperPubKey.toGoString) - let identicon = $libstatus.identicon(whisperPubKey.toGoString) + let whisperPubKey = account.derived.whisper.publicKey + let alias = generateAlias(whisperPubKey) + let identicon =generateIdenticon(whisperPubKey) let accountData = getAccountData(account, alias, identicon) var settingsJSON = getAccountSettings(account, alias, identicon, multiAccounts, constants.DEFAULT_NETWORKS) - $saveAccountAndLogin(multiAccounts, alias, identicon, $accountData, password, $constants.NODE_CONFIG, $settingsJSON) + saveAccountAndLogin(multiAccounts, alias, identicon, $accountData, password, $constants.NODE_CONFIG, $settingsJSON) diff --git a/src/status/types.nim b/src/status/types.nim index 70e66da5f3..9ef8295f25 100644 --- a/src/status/types.nim +++ b/src/status/types.nim @@ -1,5 +1,6 @@ -import json import eventemitter +import json_serialization +import accounts/constants type SignalCallback* = proc(eventMessage: cstring): void {.cdecl.} @@ -23,54 +24,43 @@ type str*: cstring length*: cint +type DerivedAccount* = object + publicKey*: string + address*: string + +type MultiAccounts* = object + whisper* {.serializedFieldName(PATH_WHISPER).}: DerivedAccount + walletRoot* {.serializedFieldName(PATH_WALLET_ROOT).}: DerivedAccount + defaultWallet* {.serializedFieldName(PATH_DEFAULT_WALLET).}: DerivedAccount + eip1581* {.serializedFieldName(PATH_EIP_1581).}: DerivedAccount + + type Account* = object of RootObj name*: string - keyUid*: string - photoPath*: string + keyUid* {.serializedFieldName("key-uid").}: string + photoPath* {.serializedFieldName("photo-path").}: string type - NodeAccount* = ref object of Account + NodeAccount* = object timestamp*: int - keycardPairing*: string + keycardPairing* {.serializedFieldName("keycard-pairing").}: string + # deserialisation does not handle base classes, so flatten + name*: string + keyUid* {.serializedFieldName("key-uid").}: string + photoPath* {.serializedFieldName("photo-path").}: string type - GeneratedAccount* = ref object of Account + GeneratedAccount* = object publicKey*: string address*: string id*: string mnemonic*: string - derived*: JsonNode - -proc toNodeAccount*(nodeAccount: JsonNode): NodeAccount = - result = NodeAccount( - name: nodeAccount["name"].getStr, - timestamp: nodeAccount["timestamp"].getInt, - photoPath: nodeAccount["photo-path"].getStr, - keycardPairing: nodeAccount["keycard-pairing"].getStr, - keyUid: nodeAccount["key-uid"].getStr) - -proc toNodeAccounts*(nodeAccounts: JsonNode): seq[NodeAccount] = - result = newSeq[NodeAccount]() - for v in nodeAccounts: - result.add v.toNodeAccount - -proc toGeneratedAccount*(generatedAccount: JsonNode): GeneratedAccount = - generatedAccount["name"] = %*"" - generatedAccount["photoPath"] = %*"" - result = generatedAccount.to(GeneratedAccount) - -proc toAccount*(generatedAccount: JsonNode): Account = - result = Account( - name: generatedAccount["name"].getStr, - keyUid: generatedAccount{"key-uid"}.getStr, - photoPath: generatedAccount["photo-path"].getStr) - -proc toAccount*(generatedAccount: GeneratedAccount): Account = - result = Account( - name: generatedAccount.name, - keyUid: generatedAccount.keyUid, - photoPath: generatedAccount.photoPath) + derived*: MultiAccounts + # deserialisation does not handle base classes, so flatten + name*: string + keyUid*: string + photoPath*: string type AccountArgs* = ref object of Args account*: Account diff --git a/ui/onboarding/GenKey.qml b/ui/onboarding/GenKey.qml index b05875d925..96db4be085 100644 --- a/ui/onboarding/GenKey.qml +++ b/ui/onboarding/GenKey.qml @@ -211,7 +211,7 @@ SwipeView { } const selectedAccountIndex = wizardStep2.selectedIndex - const storeResponse = onboardingModel.storeAccountAndLogin(selectedAccountIndex, txtPassword.text) + onboardingModel.storeAccountAndLogin(selectedAccountIndex, txtPassword.text) swipeView.loginDone(); } diff --git a/ui/onboarding/OnboardingMain.qml b/ui/onboarding/OnboardingMain.qml index 9bab027a5d..9dfcf667ad 100644 --- a/ui/onboarding/OnboardingMain.qml +++ b/ui/onboarding/OnboardingMain.qml @@ -54,7 +54,6 @@ Page { id: genKeyState onEntered: { genKey.visible = true - onboardingModel.generateAddresses() } onExited: genKey.visible = false