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.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.} =

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

View File

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

View File

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

View File

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

View File

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

View File

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