fix: change onboarding account to whisper key

Previously, the displayed key for generated accounts was displaying the public key of the account, and not the whisper account. This has been fixed.

Futher work has gone in to strongly-typing a lot of the responses from status-go and removed a lot of the manual string parsing.

Simplified types and type-conversions by using the `nim-serialization` library.
This commit is contained in:
emizzle 2020-05-25 17:45:29 +10:00 committed by Iuri Matias
parent c3ddec43fa
commit e1d1880aca
8 changed files with 136 additions and 91 deletions

View File

@ -54,8 +54,8 @@ QtObject:
AddressRoles.Identicon.int:"identicon", AddressRoles.Identicon.int:"identicon",
AddressRoles.Key.int:"key" }.toTable AddressRoles.Key.int:"key" }.toTable
proc storeAccountAndLogin(self: OnboardingView, selectedAccountIndex: int, password: string): string {.slot.} = proc storeAccountAndLogin(self: OnboardingView, selectedAccountIndex: int, password: string) {.slot.} =
result = self.model.storeAccountAndLogin(selectedAccountIndex, password) discard self.model.storeAccountAndLogin(selectedAccountIndex, password)
# TODO: this is temporary and will be removed once accounts import and creation is working # TODO: this is temporary and will be removed once accounts import and creation is working
proc generateRandomAccountAndLogin*(self: OnboardingView) {.slot.} = proc generateRandomAccountAndLogin*(self: OnboardingView) {.slot.} =

View File

@ -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

View File

@ -1,5 +1,5 @@
import json
import eventemitter import eventemitter
import json_serialization
import ../status/accounts as status_accounts import ../status/accounts as status_accounts
import ../status/types import ../status/types
@ -14,37 +14,31 @@ type
AccountModel* = ref object AccountModel* = ref object
generatedAddresses*: seq[GeneratedAccount] generatedAddresses*: seq[GeneratedAccount]
events*: EventEmitter events*: EventEmitter
subaccounts*: JsonNode #TODO use correct account, etc..
proc newAccountModel*(): AccountModel = proc newAccountModel*(): AccountModel =
result = AccountModel() result = AccountModel()
result.events = createEventEmitter() result.events = createEventEmitter()
result.generatedAddresses = @[] result.generatedAddresses = @[]
result.subaccounts = %*{}
proc delete*(self: AccountModel) = proc delete*(self: AccountModel) =
# delete self.generatedAddresses # delete self.generatedAddresses
discard discard
proc generateAddresses*(self: AccountModel): seq[GeneratedAccount] = proc generateAddresses*(self: AccountModel): seq[GeneratedAccount] =
let accounts = status_accounts.generateAddresses().parseJson var accounts = status_accounts.generateAddresses()
for account in accounts: for account in accounts.mitems:
var generatedAccount = account.toGeneratedAccount account.name = status_accounts.generateAlias(account.derived.whisper.publicKey)
account.photoPath = status_accounts.generateIdenticon(account.derived.whisper.publicKey)
generatedAccount.name = status_accounts.generateAlias(account["publicKey"].str) self.generatedAddresses.add(account)
generatedAccount.photoPath = status_accounts.generateIdenticon(account["publicKey"].str)
self.generatedAddresses.add(generatedAccount)
self.generatedAddresses self.generatedAddresses
# TODO: this is temporary and will be removed once accounts import and creation is working # TODO: this is temporary and will be removed once accounts import and creation is working
proc generateRandomAccountAndLogin*(self: AccountModel) = proc generateRandomAccountAndLogin*(self: AccountModel) =
let generatedAccounts = status_accounts.generateAddresses().parseJson let generatedAccounts = status_accounts.generateAddresses()
self.subaccounts = status_accounts.setupAccount(generatedAccounts[0], "qwerty").parseJson let account = status_accounts.setupAccount(generatedAccounts[0], "qwerty")
self.events.emit("accountsReady", AccountArgs(account: self.subaccounts[1].toAccount)) 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] let generatedAccount: GeneratedAccount = self.generatedAddresses[selectedAccountIndex]
result = status_accounts.setupAccount(%generatedAccount, password) result = status_accounts.setupAccount(generatedAccount, password)
self.subaccounts = result.parseJson self.events.emit("accountsReady", AccountArgs(account: result))
self.events.emit("accountsReady", AccountArgs(account: generatedAccount.toAccount))

View File

@ -7,7 +7,6 @@ import app/profile/core as profile
import signals/core as signals import signals/core as signals
import app/onboarding/core as onboarding import app/onboarding/core as onboarding
import state import state
import json
import status/accounts as status_accounts import status/accounts as status_accounts
import status/core as status_core import status/core as status_core
import status/chat as status_chat import status/chat as status_chat
@ -17,6 +16,7 @@ import models/accounts
import state import state
import status/types import status/types
import eventemitter import eventemitter
import json_serialization
var signalsQObjPointer: pointer var signalsQObjPointer: pointer
@ -24,7 +24,7 @@ logScope:
topics = "main" topics = "main"
proc mainProc() = 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 app = newQApplication()
let engine = newQQmlApplicationEngine() let engine = newQQmlApplicationEngine()
let signalController = signals.newController(app) let signalController = signals.newController(app)

View File

@ -6,19 +6,22 @@ import accounts/constants
import nimcrypto import nimcrypto
import os import os
import uuids import uuids
import types
import json_serialization
import chronicles
proc queryAccounts*(): string = proc queryAccounts*(): string =
var response = callPrivateRPC("eth_accounts") var response = callPrivateRPC("eth_accounts")
result = parseJson(response)["result"][0].getStr() result = parseJson(response)["result"][0].getStr()
proc generateAddresses*(): string = proc generateAddresses*(): seq[GeneratedAccount] =
let multiAccountConfig = %* { let multiAccountConfig = %* {
"n": 5, "n": 5,
"mnemonicPhraseLength": 12, "mnemonicPhraseLength": 12,
"bip39Passphrase": "", "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 = proc generateAlias*(publicKey: string): string =
result = $libstatus.generateAlias(publicKey.toGoString) result = $libstatus.generateAlias(publicKey.toGoString)
@ -43,20 +46,20 @@ proc initNodeAccounts*(): string =
discard $libstatus.initKeystore(keystoredir); discard $libstatus.initKeystore(keystoredir);
result = $libstatus.openAccounts(datadir); 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 hashedPassword = "0x" & $keccak_256.digest(password)
let subaccountData = %* [ let subaccountData = %* [
{ {
"public-key": multiAccounts[constants.PATH_DEFAULT_WALLET]["publicKey"], "public-key": multiAccounts.defaultWallet.publicKey,
"address": multiAccounts[constants.PATH_DEFAULT_WALLET]["address"], "address": multiAccounts.defaultWallet.address,
"color": "#4360df", "color": "#4360df",
"wallet": true, "wallet": true,
"path": constants.PATH_DEFAULT_WALLET, "path": constants.PATH_DEFAULT_WALLET,
"name": "Status account" "name": "Status account"
}, },
{ {
"public-key": multiAccounts[constants.PATH_WHISPER]["publicKey"], "public-key": multiAccounts.whisper.publicKey,
"address": multiAccounts[constants.PATH_WHISPER]["address"], "address": multiAccounts.whisper.address,
"name": alias, "name": alias,
"photo-path": identicon, "photo-path": identicon,
"path": constants.PATH_WHISPER, "path": constants.PATH_WHISPER,
@ -68,38 +71,39 @@ proc saveAccountAndLogin*(multiAccounts: JsonNode, alias: string, identicon: str
let parsedSavedResult = savedResult.parseJson let parsedSavedResult = savedResult.parseJson
if parsedSavedResult["error"].getStr == "": if parsedSavedResult["error"].getStr == "":
echo "Account saved succesfully" debug "Account saved succesfully"
subaccountData
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 hashedPassword = "0x" & $keccak_256.digest(password)
let multiAccount = %* { let multiAccount = %* {
"accountID": account["id"].getStr, "accountID": account.id,
"paths": ["m/44'/60'/0'/0", "m/43'/60'/1581'", "m/43'/60'/1581'/0'/0", "m/44'/60'/0'/0/0"], "paths": [PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET],
"password": hashedPassword "password": hashedPassword
} }
var response = $libstatus.multiAccountStoreDerivedAccounts($multiAccount); 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 = %* { result = %* {
"name": alias, "name": alias,
"address": account["address"].getStr, "address": account.address,
"photo-path": identicon, "photo-path": identicon,
"key-uid": account["keyUid"].getStr, "key-uid": account.keyUid,
"keycard-pairing": nil "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 = %* { result = %* {
"key-uid": account["keyUid"].getStr, "key-uid": account.keyUid,
"mnemonic": account["mnemonic"].getStr, "mnemonic": account.mnemonic,
"public-key": multiAccounts[constants.PATH_WHISPER]["publicKey"].getStr, "public-key": multiAccounts.whisper.publicKey,
"name": alias, "name": alias,
"address": account["address"].getStr, "address": account.address,
"eip1581-address": multiAccounts[constants.PATH_EIP_1581]["address"].getStr, "eip1581-address": multiAccounts.eip1581.address,
"dapps-address": multiAccounts[constants.PATH_DEFAULT_WALLET]["address"].getStr, "dapps-address": multiAccounts.defaultWallet.address,
"wallet-root-address": multiAccounts[constants.PATH_WALLET_ROOT]["address"].getStr, "wallet-root-address": multiAccounts.walletRoot.address,
"preview-privacy?": true, "preview-privacy?": true,
"signing-phrase": generateSigningPhrase(3), "signing-phrase": generateSigningPhrase(3),
"log-level": "INFO", "log-level": "INFO",
@ -116,14 +120,14 @@ proc getAccountSettings*(account: JsonNode, alias: string, identicon: string, mu
"installation-id": $genUUID() "installation-id": $genUUID()
} }
proc setupAccount*(account: JsonNode, password: string): string = proc setupAccount*(account: GeneratedAccount, password: string): Account =
let multiAccounts = generateMultiAccounts(account, password) let multiAccounts = generateMultiAccounts(account, password)
let whisperPubKey = account["derived"][constants.PATH_WHISPER]["publicKey"].getStr let whisperPubKey = account.derived.whisper.publicKey
let alias = $libstatus.generateAlias(whisperPubKey.toGoString) let alias = generateAlias(whisperPubKey)
let identicon = $libstatus.identicon(whisperPubKey.toGoString) let identicon =generateIdenticon(whisperPubKey)
let accountData = getAccountData(account, alias, identicon) let accountData = getAccountData(account, alias, identicon)
var settingsJSON = getAccountSettings(account, alias, identicon, multiAccounts, constants.DEFAULT_NETWORKS) 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)

View File

@ -1,5 +1,6 @@
import json
import eventemitter import eventemitter
import json_serialization
import accounts/constants
type SignalCallback* = proc(eventMessage: cstring): void {.cdecl.} type SignalCallback* = proc(eventMessage: cstring): void {.cdecl.}
@ -23,54 +24,43 @@ type
str*: cstring str*: cstring
length*: cint 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 type
Account* = object of RootObj Account* = object of RootObj
name*: string name*: string
keyUid*: string keyUid* {.serializedFieldName("key-uid").}: string
photoPath*: string photoPath* {.serializedFieldName("photo-path").}: string
type type
NodeAccount* = ref object of Account NodeAccount* = object
timestamp*: int 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 type
GeneratedAccount* = ref object of Account GeneratedAccount* = object
publicKey*: string publicKey*: string
address*: string address*: string
id*: string id*: string
mnemonic*: string mnemonic*: string
derived*: JsonNode derived*: MultiAccounts
# deserialisation does not handle base classes, so flatten
proc toNodeAccount*(nodeAccount: JsonNode): NodeAccount = name*: string
result = NodeAccount( keyUid*: string
name: nodeAccount["name"].getStr, photoPath*: string
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)
type AccountArgs* = ref object of Args type AccountArgs* = ref object of Args
account*: Account account*: Account

View File

@ -211,7 +211,7 @@ SwipeView {
} }
const selectedAccountIndex = wizardStep2.selectedIndex const selectedAccountIndex = wizardStep2.selectedIndex
const storeResponse = onboardingModel.storeAccountAndLogin(selectedAccountIndex, txtPassword.text) onboardingModel.storeAccountAndLogin(selectedAccountIndex, txtPassword.text)
swipeView.loginDone(); swipeView.loginDone();
} }

View File

@ -54,7 +54,6 @@ Page {
id: genKeyState id: genKeyState
onEntered: { onEntered: {
genKey.visible = true genKey.visible = true
onboardingModel.generateAddresses()
} }
onExited: genKey.visible = false onExited: genKey.visible = false