refactor(fleet-configuration): fleet configuration added to `StatusFoundation`
This commit is contained in:
parent
7a9784b854
commit
bf651c093e
|
@ -28,14 +28,14 @@ import ../modules/main/module as main_module
|
|||
import ../global/local_account_settings
|
||||
import ../global/global_singleton
|
||||
|
||||
import ../core/[main]
|
||||
|
||||
#################################################
|
||||
# This will be removed later once we move to c++ and handle there async things
|
||||
# and improved some services, like EventsService which should implement
|
||||
# provider/subscriber principe, similar we should have SettingsService.
|
||||
import ../../constants
|
||||
import ../core/[main]
|
||||
import eventemitter
|
||||
import status/[fleet]
|
||||
import ../profile/core as profile
|
||||
import ../chat/core as chat
|
||||
import ../wallet/v1/core as wallet
|
||||
|
@ -165,7 +165,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||
result.osNotificationService = os_notification_service.newService(statusFoundation.status.events)
|
||||
result.keychainService = keychain_service.newService(statusFoundation.status.events)
|
||||
result.settingsService = settings_service.newService()
|
||||
result.accountsService = accounts_service.newService()
|
||||
result.accountsService = accounts_service.newService(statusFoundation.fleetConfiguration)
|
||||
result.contactsService = contacts_service.newService(statusFoundation.status.events, statusFoundation.threadpool)
|
||||
result.chatService = chat_service.newService(result.contactsService)
|
||||
result.communityService = community_service.newService(result.chatService)
|
||||
|
@ -191,7 +191,6 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||
result.startupModule = startup_module.newModule[AppController](
|
||||
result,
|
||||
statusFoundation.status.events,
|
||||
statusFoundation.status.fleet,
|
||||
result.keychainService,
|
||||
result.accountsService
|
||||
)
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import json, typetraits, tables, sequtils
|
||||
|
||||
type
|
||||
Fleet* {.pure.} = enum
|
||||
Prod = "eth.prod",
|
||||
Staging = "eth.staging",
|
||||
Test = "eth.test",
|
||||
WakuV2Prod = "wakuv2.prod"
|
||||
WakuV2Test = "wakuv2.test"
|
||||
GoWakuTest = "go-waku.test"
|
||||
|
||||
FleetNodes* {.pure.} = enum
|
||||
Bootnodes = "boot",
|
||||
Mailservers = "mail",
|
||||
Rendezvous = "rendezvous",
|
||||
Whisper = "whisper",
|
||||
Waku = "waku"
|
||||
LibP2P = "libp2p"
|
||||
Websocket = "websocket"
|
||||
|
||||
Meta* = object
|
||||
hostname*: string
|
||||
timestamp*: uint64
|
||||
|
||||
Conf* = Table[string, Table[string, Table[string, string]]]
|
||||
|
||||
type
|
||||
FleetConfiguration* = ref object
|
||||
fleet: Conf
|
||||
meta: Meta
|
||||
|
||||
## Forward declaration
|
||||
proc extractConfig(self: FleetConfiguration, jsonString: string)
|
||||
|
||||
proc newFleetConfiguration*(jsonString: string): FleetConfiguration =
|
||||
result = FleetConfiguration()
|
||||
result.extractConfig(jsonString)
|
||||
|
||||
proc delete*(self: FleetConfiguration) =
|
||||
discard
|
||||
|
||||
proc extractConfig(self: FleetConfiguration, jsonString: string) =
|
||||
let fleetJson = jsonString.parseJSON
|
||||
self.meta.hostname = fleetJson["meta"]["hostname"].getStr
|
||||
self.meta.timestamp = fleetJson["meta"]["timestamp"].getBiggestInt.uint64
|
||||
self.fleet = initTable[string, Table[string, Table[string, string]]]()
|
||||
|
||||
for fleet in fleetJson["fleets"].keys():
|
||||
self.fleet[fleet] = initTable[string, Table[string, string]]()
|
||||
for nodes in fleetJson["fleets"][fleet].keys():
|
||||
self.fleet[fleet][nodes] = initTable[string, string]()
|
||||
for server in fleetJson["fleets"][fleet][nodes].keys():
|
||||
self.fleet[fleet][nodes][server] = fleetJson["fleets"][fleet][nodes][server].getStr
|
||||
|
||||
proc getNodes*(self: FleetConfiguration, fleet: Fleet, nodeType: FleetNodes = FleetNodes.Bootnodes): seq[string] =
|
||||
if not self.fleet[$fleet].hasKey($nodeType): return
|
||||
result = toSeq(self.fleet[$fleet][$nodeType].values)
|
||||
|
||||
proc getMailservers*(self: FleetConfiguration, fleet: Fleet, isWakuV2: bool): Table[string, string] =
|
||||
# TODO: If using wakuV2, this assumes that Waku nodes in fleet.status.json are also store nodes.
|
||||
# Maybe it make senses to add a "waku-store" section in case we want to have separate node types?
|
||||
# Discuss with @iurimatias, @cammellos and Vac team
|
||||
let fleetKey = if isWakuV2: $FleetNodes.Waku else: $FleetNodes.Mailservers
|
||||
if not self.fleet[$fleet].hasKey(fleetKey) :
|
||||
result = initTable[string,string]()
|
||||
return
|
||||
result = self.fleet[$fleet][fleetKey]
|
|
@ -2,6 +2,7 @@ import NimQml, chronicles, task_runner
|
|||
import ../../constants
|
||||
import status/status as status_lib_status
|
||||
import
|
||||
./fleets/fleet_configuration,
|
||||
./tasks/marathon,
|
||||
./tasks/marathon/mailserver/controller,
|
||||
./tasks/marathon/mailserver/worker,
|
||||
|
@ -9,10 +10,11 @@ import
|
|||
./signals/signals_manager
|
||||
|
||||
export status_lib_status
|
||||
export marathon, task_runner, signals_manager
|
||||
export marathon, task_runner, signals_manager, fleet_configuration
|
||||
|
||||
type StatusFoundation* = ref object
|
||||
status*: Status # in one point of time this should be completely removed
|
||||
fleetConfiguration*: FleetConfiguration
|
||||
threadpool*: ThreadPool
|
||||
marathon*: Marathon
|
||||
signalsManager*: SignalsManager
|
||||
|
@ -22,9 +24,10 @@ type StatusFoundation* = ref object
|
|||
proc newStatusFoundation*(fleetConfig: string): StatusFoundation =
|
||||
result = StatusFoundation()
|
||||
|
||||
result.status = newStatusInstance(fleetConfig)
|
||||
result.status = newStatusInstance()
|
||||
result.status.initNode(STATUSGODIR, KEYSTOREDIR)
|
||||
|
||||
result.fleetConfiguration = newFleetConfiguration(fleetConfig)
|
||||
result.mailserverController = newMailserverController(result.status.events)
|
||||
result.mailserverWorker = newMailserverWorker(cast[ByteAddress](result.mailserverController.vptr))
|
||||
result.threadpool = newThreadPool()
|
||||
|
@ -34,6 +37,9 @@ proc newStatusFoundation*(fleetConfig: string): StatusFoundation =
|
|||
proc delete*(self: StatusFoundation) =
|
||||
self.threadpool.teardown()
|
||||
self.marathon.teardown()
|
||||
self.mailserverWorker.teardown()
|
||||
self.mailserverController.delete()
|
||||
self.fleetConfiguration.delete()
|
||||
self.signalsManager.delete()
|
||||
self.status.reset()
|
||||
|
||||
|
|
|
@ -1,46 +1,237 @@
|
|||
import
|
||||
chronos, chronicles
|
||||
algorithm, chronos, chronicles, json, math, os, random, sequtils, sets,
|
||||
tables, strutils
|
||||
from times import cpuTime
|
||||
|
||||
import
|
||||
status/statusgo_backend_new/mailservers as status_mailservers,
|
||||
status/fleet
|
||||
|
||||
status/statusgo_backend/settings as status_settings,
|
||||
status/statusgo_backend/chat as status_chat,
|
||||
status/statusgo_backend/mailservers as status_mailservers,
|
||||
status/statusgo_backend/core as status_core,
|
||||
status/fleet,
|
||||
./events as mailserver_events
|
||||
|
||||
logScope:
|
||||
topics = "mailserver model"
|
||||
|
||||
################################################################################
|
||||
## ##
|
||||
## NOTE: MailserverModel runs on a separate (long-running) thread ##
|
||||
## ##
|
||||
## How do mailservers work ? ##
|
||||
## ##
|
||||
## - We send a request to the mailserver, we are only interested in the ##
|
||||
## messages since `last-request` up to the last seven days ##
|
||||
## and the last 24 hours for topics that were just joined ##
|
||||
## - The mailserver doesn't directly respond to the request and ##
|
||||
## instead we start receiving messages in the filters for the requested ##
|
||||
## topics. ##
|
||||
## - If the mailserver was not ready when we tried for instance to request ##
|
||||
## the history of a topic after joining a chat, the request will be done ##
|
||||
## as soon as the mailserver becomes available ##
|
||||
## ##
|
||||
################################################################################
|
||||
type
|
||||
MailserverModel* = ref object
|
||||
mailservers*: seq[string]
|
||||
events*: MailserverEvents
|
||||
nodes*: Table[string, MailserverStatus]
|
||||
activeMailserver*: string
|
||||
lastConnectionAttempt*: float
|
||||
## At this moment we cannot remove FleetModel from `status-lib` easily since the following error occurs:
|
||||
## /desktop-app/src/app/core/tasks/marathon/mailserver/worker.nim(120, 37) template/generic instantiation of `async` from here
|
||||
## /desktop-app/vendor/status-lib/vendor/nim-task-runner/vendor/nim-chronos/chronos/asyncmacro2.nim(210, 31) Error: 'worker' is not GC-safe as it calls 'init'
|
||||
##
|
||||
## But at some point in future we will spend more time and figure out what's the issue.
|
||||
fleet*: FleetModel
|
||||
wakuVersion*: int
|
||||
|
||||
MailserverStatus* = enum
|
||||
Unknown = -1,
|
||||
Disconnected = 0,
|
||||
Connecting = 1
|
||||
Connected = 2,
|
||||
|
||||
proc peerIdFromMultiAddress(nodeAddr: string): string =
|
||||
let multiAddressParts = nodeAddr.split("/")
|
||||
return multiAddressParts[multiAddressParts.len - 1]
|
||||
|
||||
proc cmpMailserverReply(x, y: (string, int)): int =
|
||||
if x[1] > y[1]: 1
|
||||
elif x[1] == y[1]: 0
|
||||
else: -1
|
||||
|
||||
proc poolSize(fleetSize: int): int = ceil(fleetSize / 4).int
|
||||
|
||||
proc newMailserverModel*(vptr: ByteAddress): MailserverModel =
|
||||
result = MailserverModel()
|
||||
result.events = newMailserverEvents(vptr)
|
||||
result.nodes = initTable[string, MailserverStatus]()
|
||||
result.activeMailserver = ""
|
||||
|
||||
proc disconnectActiveMailserver(self: MailserverModel) =
|
||||
try:
|
||||
warn "Disconnecting active mailserver due to error"
|
||||
discard status_mailservers.disconnectActiveMailserver()
|
||||
except Exception as e:
|
||||
error "error: ", errDescription=e.msg
|
||||
proc init*(self: MailserverModel) =
|
||||
trace "MailserverModel::init()"
|
||||
let fleets =
|
||||
if defined(windows) and defined(production):
|
||||
"/../resources/fleets.json"
|
||||
else:
|
||||
"/../fleets.json"
|
||||
|
||||
self.wakuVersion = status_settings.getWakuVersion()
|
||||
|
||||
let fleetConfig = readFile(joinPath(getAppDir(), fleets))
|
||||
self.fleet = newFleetModel(fleetConfig)
|
||||
self.wakuVersion = status_settings.getWakuVersion()
|
||||
|
||||
let fleet = parseEnum[Fleet](status_settings.getFleet())
|
||||
self.mailservers = toSeq(self.fleet.config.getMailservers(fleet, self.wakuVersion == 2).values)
|
||||
|
||||
for mailserver in status_settings.getMailservers().getElems():
|
||||
self.mailservers.add(mailserver["address"].getStr())
|
||||
|
||||
proc getActiveMailserver*(self: MailserverModel): string = self.activeMailserver
|
||||
|
||||
proc isActiveMailserverAvailable*(self: MailserverModel): bool =
|
||||
if not self.nodes.hasKey(self.activeMailserver):
|
||||
result = false
|
||||
else:
|
||||
result = self.nodes[self.activeMailserver] == MailserverStatus.Connected
|
||||
|
||||
proc connect(self: MailserverModel, nodeAddr: string) =
|
||||
debug "Connecting to mailserver", nodeAddr
|
||||
var connected = false
|
||||
# TODO: this should come from settings
|
||||
var knownMailservers = initHashSet[string]()
|
||||
for m in self.mailservers:
|
||||
knownMailservers.incl m
|
||||
if not knownMailservers.contains(nodeAddr):
|
||||
warn "Mailserver not known", nodeAddr
|
||||
return
|
||||
|
||||
self.activeMailserver = if self.wakuVersion == 2: peerIdFromMultiAddress(nodeAddr) else: nodeAddr
|
||||
self.events.emit("mailserver:changed", MailserverArgs(peer: nodeAddr))
|
||||
|
||||
# Adding a peer and marking it as connected can't be executed sync in WakuV1, because
|
||||
# There's a delay between requesting a peer being added, and a signal being
|
||||
# received after the peer was added. So we first set the peer status as
|
||||
# Connecting and once a peerConnected signal is received, we mark it as
|
||||
# Connected
|
||||
|
||||
if self.nodes.hasKey(self.activeMailserver) and self.nodes[self.activeMailserver] == MailserverStatus.Connected:
|
||||
connected = true
|
||||
else:
|
||||
# Attempt to connect to mailserver by adding it as a peer
|
||||
if self.wakuVersion == 2:
|
||||
if status_core.dialPeer(nodeAddr): # WakuV2 dial is sync (should it be async?)
|
||||
discard status_mailservers.setMailserver(self.activeMailserver)
|
||||
self.nodes[self.activeMailserver] = MailserverStatus.Connected
|
||||
connected = true
|
||||
else:
|
||||
status_mailservers.update(nodeAddr)
|
||||
self.nodes[nodeAddr] = MailserverStatus.Connecting
|
||||
|
||||
self.lastConnectionAttempt = cpuTime()
|
||||
|
||||
if connected:
|
||||
info "Mailserver available"
|
||||
self.events.emit("mailserverAvailable", MailserverArgs())
|
||||
|
||||
proc peerSummaryChange*(self: MailserverModel, peers: seq[string]) =
|
||||
# When a node is added as a peer, or disconnected
|
||||
# a DiscoverySummary signal is emitted. In here we
|
||||
# change the status of the nodes the app is connected to
|
||||
# Connected / Disconnected and emit peerConnected / peerDisconnected
|
||||
# events.
|
||||
|
||||
var mailserverAvailable = false
|
||||
for knownPeer in self.nodes.keys:
|
||||
if not peers.contains(knownPeer) and (self.nodes[knownPeer] == MailserverStatus.Connected or (self.nodes[knownPeer] == MailserverStatus.Connecting and (cpuTime() - self.lastConnectionAttempt) > 8)):
|
||||
info "Peer disconnected", peer=knownPeer
|
||||
self.nodes[knownPeer] = MailserverStatus.Disconnected
|
||||
self.events.emit("peerDisconnected", MailserverArgs(peer: knownPeer))
|
||||
if self.activeMailserver == knownPeer:
|
||||
warn "Active mailserver disconnected!", peer = knownPeer
|
||||
self.activeMailserver = ""
|
||||
|
||||
for peer in peers:
|
||||
if self.nodes.hasKey(peer) and (self.nodes[peer] == MailserverStatus.Connected): continue
|
||||
info "Peer connected", peer
|
||||
self.nodes[peer] = MailserverStatus.Connected
|
||||
self.events.emit("peerConnected", MailserverArgs(peer: peer))
|
||||
|
||||
if peer == self.activeMailserver:
|
||||
if self.nodes.hasKey(self.activeMailserver):
|
||||
if self.activeMailserver == peer:
|
||||
mailserverAvailable = true
|
||||
|
||||
if mailserverAvailable:
|
||||
info "Mailserver available"
|
||||
self.events.emit("mailserverAvailable", MailserverArgs())
|
||||
|
||||
proc requestMessages*(self: MailserverModel) =
|
||||
try:
|
||||
info "Requesting message history"
|
||||
discard status_mailservers.requestAllHistoricMessages()
|
||||
except Exception as e:
|
||||
error "error: ", errDescription=e.msg
|
||||
self.disconnectActiveMailserver()
|
||||
info "Requesting messages from", mailserver=self.activeMailserver
|
||||
discard status_mailservers.requestAllHistoricMessages()
|
||||
|
||||
proc requestStoreMessages*(self: MailserverModel, topics: seq[string], fromValue: int64 = 0, toValue: int64 = 0, force: bool = false) =
|
||||
info "Requesting messages from", mailserver=self.activeMailserver
|
||||
let generatedSymKey = status_chat.generateSymKeyFromPassword()
|
||||
status_mailservers.requestStoreMessages(topics, generatedSymKey, self.activeMailserver, 1000, fromValue, toValue, force)
|
||||
|
||||
proc requestMoreMessages*(self: MailserverModel, chatId: string) =
|
||||
try:
|
||||
info "Requesting more messages for", chatId=chatId
|
||||
discard status_mailservers.syncChatFromSyncedFrom(chatId)
|
||||
except Exception as e:
|
||||
error "error: ", errDescription=e.msg
|
||||
self.disconnectActiveMailserver()
|
||||
info "Requesting more messages from", mailserver=self.activeMailserver, chatId=chatId
|
||||
discard status_mailservers.syncChatFromSyncedFrom(chatId)
|
||||
|
||||
proc fillGaps*(self: MailserverModel, chatId: string, messageIds: seq[string]) =
|
||||
try:
|
||||
info "Requesting fill gaps from", chatId=chatId
|
||||
discard status_mailservers.fillGaps(chatId, messageIds)
|
||||
except Exception as e:
|
||||
error "error: ", errDescription=e.msg
|
||||
self.disconnectActiveMailserver()
|
||||
info "Requesting fill gaps from", mailserver=self.activeMailserver, chatId=chatId
|
||||
discard status_mailservers.fillGaps(chatId, messageIds)
|
||||
|
||||
proc findNewMailserver(self: MailserverModel) =
|
||||
warn "Finding a new mailserver...", wakuVersion=self.wakuVersion
|
||||
|
||||
let mailserversReply = parseJson(status_mailservers.ping(self.mailservers, 500, self.wakuVersion == 2))["result"]
|
||||
|
||||
var availableMailservers:seq[(string, int)] = @[]
|
||||
for reply in mailserversReply:
|
||||
if(reply["error"].kind != JNull): continue # The results with error are ignored
|
||||
availableMailservers.add((reply["address"].getStr, reply["rttMs"].getInt))
|
||||
availableMailservers.sort(cmpMailserverReply)
|
||||
|
||||
# No mailservers where returned... do nothing.
|
||||
if availableMailservers.len == 0:
|
||||
warn "No mailservers available"
|
||||
return
|
||||
|
||||
# Picks a random mailserver amongs the ones with the lowest latency
|
||||
# The pool size is 1/4 of the mailservers were pinged successfully
|
||||
randomize()
|
||||
|
||||
let mailServer = availableMailservers[rand(poolSize(availableMailservers.len - 1))][0]
|
||||
|
||||
self.connect(mailserver)
|
||||
|
||||
proc cycleMailservers(self: MailserverModel) =
|
||||
warn "Automatically switching mailserver"
|
||||
if self.activeMailserver != "":
|
||||
info "Disconnecting active mailserver", peer=self.activeMailserver
|
||||
self.nodes[self.activeMailserver] = MailserverStatus.Disconnected
|
||||
if self.wakuVersion == 2:
|
||||
dropPeerByID(self.activeMailserver)
|
||||
else:
|
||||
removePeer(self.activeMailserver)
|
||||
self.activeMailserver = ""
|
||||
self.findNewMailserver()
|
||||
|
||||
proc checkConnection*(self: MailserverModel) {.async.} =
|
||||
while true:
|
||||
info "Verifying mailserver connection state..."
|
||||
let pinnedMailserver = status_settings.getPinnedMailserver()
|
||||
if self.wakuVersion == 1 and pinnedMailserver != "" and self.activeMailserver != pinnedMailserver:
|
||||
# connect to current mailserver from the settings
|
||||
self.mailservers.add(pinnedMailserver)
|
||||
self.connect(pinnedMailserver)
|
||||
else:
|
||||
# or setup a random mailserver:
|
||||
if not self.isActiveMailserverAvailable:
|
||||
# TODO: have a timeout for reconnection before changing to a different server
|
||||
self.cycleMailservers()
|
||||
await sleepAsync(10.seconds)
|
||||
|
|
|
@ -11,7 +11,6 @@ import ../../../app_service/service/keychain/service as keychain_service
|
|||
import ../../../app_service/service/accounts/service_interface as accounts_service
|
||||
|
||||
import eventemitter
|
||||
import status/[fleet]
|
||||
|
||||
export io_interface
|
||||
|
||||
|
@ -26,7 +25,6 @@ type
|
|||
|
||||
proc newModule*[T](delegate: T,
|
||||
events: EventEmitter,
|
||||
fleet: FleetModel,
|
||||
keychainService: keychain_service.Service,
|
||||
accountsService: accounts_service.ServiceInterface):
|
||||
Module[T] =
|
||||
|
@ -37,8 +35,7 @@ proc newModule*[T](delegate: T,
|
|||
result.controller = controller.newController(result, events, accountsService)
|
||||
|
||||
# Submodules
|
||||
result.onboardingModule = onboarding_module.newModule(result, events, fleet,
|
||||
accountsService)
|
||||
result.onboardingModule = onboarding_module.newModule(result, events, accountsService)
|
||||
result.loginModule = login_module.newModule(result, events, keychainService,
|
||||
accountsService)
|
||||
|
||||
|
|
|
@ -18,19 +18,16 @@ type
|
|||
ref object of controller_interface.AccessInterface
|
||||
delegate: io_interface.AccessInterface
|
||||
events: EventEmitter
|
||||
fleet: FleetModel
|
||||
accountsService: accounts_service.ServiceInterface
|
||||
selectedAccountId: string
|
||||
|
||||
proc newController*(delegate: io_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
fleet: FleetModel,
|
||||
accountsService: accounts_service.ServiceInterface):
|
||||
Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.fleet = fleet
|
||||
result.accountsService = accountsService
|
||||
|
||||
method delete*(self: Controller) =
|
||||
|
@ -53,8 +50,7 @@ method setSelectedAccountByIndex*(self: Controller, index: int) =
|
|||
self.selectedAccountId = accounts[index].id
|
||||
|
||||
method storeSelectedAccountAndLogin*(self: Controller, password: string) =
|
||||
if(not self.accountsService.setupAccount(self.fleet.config,
|
||||
self.selectedAccountId, password)):
|
||||
if(not self.accountsService.setupAccount(self.selectedAccountId, password)):
|
||||
self.delegate.setupAccountError()
|
||||
|
||||
method validateMnemonic*(self: Controller, mnemonic: string): string =
|
||||
|
|
|
@ -10,22 +10,19 @@ method delete*(self: AccessInterface) {.base.} =
|
|||
method init*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getGeneratedAccounts*(self: AccessInterface):
|
||||
seq[GeneratedAccountDto] {.base.} =
|
||||
method getGeneratedAccounts*(self: AccessInterface): seq[GeneratedAccountDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setSelectedAccountByIndex*(self: AccessInterface, index: int) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method storeSelectedAccountAndLogin*(self: AccessInterface, password: string)
|
||||
{.base.} =
|
||||
method storeSelectedAccountAndLogin*(self: AccessInterface, password: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getImportedAccount*(self: AccessInterface): GeneratedAccountDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method validateMnemonic*(self: AccessInterface, mnemonic: string):
|
||||
string {.base.} =
|
||||
method validateMnemonic*(self: AccessInterface, mnemonic: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method importMnemonic*(self: AccessInterface, mnemonic: string) {.base.} =
|
||||
|
|
|
@ -7,7 +7,6 @@ import ../../../global/global_singleton
|
|||
import ../../../../app_service/service/accounts/service_interface as accounts_service
|
||||
|
||||
import eventemitter
|
||||
import status/[fleet]
|
||||
|
||||
export io_interface
|
||||
|
||||
|
@ -19,17 +18,14 @@ type
|
|||
controller: controller.AccessInterface
|
||||
moduleLoaded: bool
|
||||
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
fleet: FleetModel,
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter,
|
||||
accountsService: accounts_service.ServiceInterface):
|
||||
Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.view = view.newView(result)
|
||||
result.viewVariant = newQVariant(result.view)
|
||||
result.controller = controller.newController(result, events, fleet,
|
||||
accountsService)
|
||||
result.controller = controller.newController(result, events, accountsService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, json, tables
|
||||
import NimQml, json
|
||||
import json_serialization
|
||||
import status/[status, settings]
|
||||
import status/contacts as status_contacts
|
||||
|
@ -63,9 +63,11 @@ proc init*(self: ProfileController, account: Account) =
|
|||
self.view.ens.init()
|
||||
self.view.initialized()
|
||||
|
||||
for name, endpoint in self.status.fleet.config.getMailservers(self.status.settings.getFleet(), self.status.settings.getWakuVersion() == 2).pairs():
|
||||
let mailserver = MailServer(name: name, endpoint: endpoint)
|
||||
self.view.mailservers.add(mailserver)
|
||||
# Delete this once it's refactored.
|
||||
#
|
||||
# for name, endpoint in self.status.fleet.config.getMailservers(self.status.settings.getFleet(), self.status.settings.getWakuVersion() == 2).pairs():
|
||||
# let mailserver = MailServer(name: name, endpoint: endpoint)
|
||||
# self.view.mailservers.add(mailserver)
|
||||
|
||||
for mailserver in self.status.settings.getMailservers().getElems():
|
||||
let mailserver = MailServer(name: mailserver["name"].getStr(), endpoint: mailserver["address"].getStr())
|
||||
|
|
|
@ -24,20 +24,23 @@ QtObject:
|
|||
self.fleetChanged($self.status.settings.getFleet())
|
||||
|
||||
proc setFleet*(self: Fleets, newFleet: string) {.slot.} =
|
||||
let fleet = parseEnum[Fleet](newFleet)
|
||||
let statusGoResult = self.status.settings.setFleet(self.status.fleet.config, fleet)
|
||||
if statusGoResult.error != "":
|
||||
error "Error saving updated node config", msg=statusGoResult.error
|
||||
discard
|
||||
# Delete this once it's refactored.
|
||||
#
|
||||
# let fleet = parseEnum[Fleet](newFleet)
|
||||
# let statusGoResult = self.status.settings.setFleet(self.status.fleet.config, fleet)
|
||||
# if statusGoResult.error != "":
|
||||
# error "Error saving updated node config", msg=statusGoResult.error
|
||||
|
||||
let isWakuV2 = if fleet == WakuV2Prod or fleet == WakuV2Test: true else: false
|
||||
# Updating waku version because it makes no sense for some fleets to run under wakuv1 or v2 config
|
||||
if isWakuV2:
|
||||
self.status.settings.setWakuVersion(2)
|
||||
else:
|
||||
self.status.settings.setWakuVersion(1)
|
||||
# let isWakuV2 = if fleet == WakuV2Prod or fleet == WakuV2Test: true else: false
|
||||
# # Updating waku version because it makes no sense for some fleets to run under wakuv1 or v2 config
|
||||
# if isWakuV2:
|
||||
# self.status.settings.setWakuVersion(2)
|
||||
# else:
|
||||
# self.status.settings.setWakuVersion(1)
|
||||
|
||||
self.fleetChanged(newFleet)
|
||||
quit(QuitSuccess) # quits the app TODO: change this to logout instead when supported
|
||||
# self.fleetChanged(newFleet)
|
||||
# quit(QuitSuccess) # quits the app TODO: change this to logout instead when supported
|
||||
|
||||
proc getFleet*(self: Fleets): string {.slot.} = $self.status.settings.getFleet()
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ QtObject:
|
|||
proc setNetworkAndPersist*(self: NetworkView, network: string) {.slot.} =
|
||||
self.network = network
|
||||
self.networkChanged()
|
||||
self.status.accounts.changeNetwork(self.status.fleet.config, network) ###############################
|
||||
self.status.accounts.changeNetwork(network) ###############################
|
||||
quit(QuitSuccess) # quits the app TODO: change this to logout instead when supported
|
||||
|
||||
QtProperty[QVariant] current:
|
||||
|
|
|
@ -4,9 +4,10 @@ import json_serialization, chronicles
|
|||
import service_interface
|
||||
import ./dto/accounts
|
||||
import ./dto/generated_accounts
|
||||
import status/statusgo_backend_new/accounts as status_go
|
||||
import status/statusgo_backend_new/general as status_go_general
|
||||
import status/statusgo_backend_new/accounts as status_account
|
||||
import status/statusgo_backend_new/general as status_general
|
||||
|
||||
import ../../../app/core/fleets/fleet_configuration
|
||||
import ../../common/[account_constants, utils, string_utils]
|
||||
import ../../../constants as main_constants
|
||||
export service_interface
|
||||
|
@ -18,6 +19,7 @@ const PATHS = @[PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALL
|
|||
|
||||
type
|
||||
Service* = ref object of ServiceInterface
|
||||
fleetConfiguration: FleetConfiguration
|
||||
generatedAccounts: seq[GeneratedAccountDto]
|
||||
loggedInAccount: AccountDto
|
||||
importedAccount: GeneratedAccountDto
|
||||
|
@ -26,8 +28,9 @@ type
|
|||
method delete*(self: Service) =
|
||||
discard
|
||||
|
||||
proc newService*(): Service =
|
||||
proc newService*(fleetConfiguration: FleetConfiguration): Service =
|
||||
result = Service()
|
||||
result.fleetConfiguration = fleetConfiguration
|
||||
result.isFirstTimeAccountLogin = false
|
||||
|
||||
method getLoggedInAccount*(self: Service): AccountDto =
|
||||
|
@ -40,11 +43,11 @@ method isFirstTimeAccountLogin*(self: Service): bool =
|
|||
return self.isFirstTimeAccountLogin
|
||||
|
||||
method generateAlias*(self: Service, publicKey: string): string =
|
||||
return status_go.generateAlias(publicKey).result.getStr
|
||||
return status_account.generateAlias(publicKey).result.getStr
|
||||
|
||||
method init*(self: Service) =
|
||||
try:
|
||||
let response = status_go.generateAddresses(PATHS)
|
||||
let response = status_account.generateAddresses(PATHS)
|
||||
|
||||
self.generatedAccounts = map(response.result.getElems(),
|
||||
proc(x: JsonNode): GeneratedAccountDto = toGeneratedAccountDto(x))
|
||||
|
@ -52,8 +55,7 @@ method init*(self: Service) =
|
|||
for account in self.generatedAccounts.mitems:
|
||||
account.alias = self.generateAlias(account.derivedAccounts.whisper.publicKey)
|
||||
|
||||
let responseIdenticon = status_go.generateIdenticon(
|
||||
account.derivedAccounts.whisper.publicKey)
|
||||
let responseIdenticon = status_account.generateIdenticon(account.derivedAccounts.whisper.publicKey)
|
||||
account.identicon = responseIdenticon.result.getStr
|
||||
|
||||
except Exception as e:
|
||||
|
@ -67,7 +69,7 @@ method clear*(self: Service) =
|
|||
|
||||
method validateMnemonic*(self: Service, mnemonic: string): string =
|
||||
try:
|
||||
let response = status_go_general.validateMnemonic(mnemonic)
|
||||
let response = status_general.validateMnemonic(mnemonic)
|
||||
|
||||
var error = "response doesn't contain \"error\""
|
||||
if(response.result.contains("error")):
|
||||
|
@ -88,10 +90,9 @@ method generatedAccounts*(self: Service): seq[GeneratedAccountDto] =
|
|||
|
||||
method openedAccounts*(self: Service): seq[AccountDto] =
|
||||
try:
|
||||
let response = status_go.openedAccounts(main_constants.STATUSGODIR)
|
||||
let response = status_account.openedAccounts(main_constants.STATUSGODIR)
|
||||
|
||||
let accounts = map(response.result.getElems(),
|
||||
proc(x: JsonNode): AccountDto = toAccountDto(x))
|
||||
let accounts = map(response.result.getElems(), proc(x: JsonNode): AccountDto = toAccountDto(x))
|
||||
|
||||
return accounts
|
||||
|
||||
|
@ -101,7 +102,7 @@ method openedAccounts*(self: Service): seq[AccountDto] =
|
|||
proc storeDerivedAccounts(self: Service, accountId, hashedPassword: string,
|
||||
paths: seq[string]): DerivedAccounts =
|
||||
try:
|
||||
let response = status_go.storeDerivedAccounts(accountId, hashedPassword, paths)
|
||||
let response = status_account.storeDerivedAccounts(accountId, hashedPassword, paths)
|
||||
result = toDerivedAccounts(response.result)
|
||||
|
||||
except Exception as e:
|
||||
|
@ -110,8 +111,7 @@ proc storeDerivedAccounts(self: Service, accountId, hashedPassword: string,
|
|||
proc saveAccountAndLogin(self: Service, hashedPassword: string, account,
|
||||
subaccounts, settings, config: JsonNode): AccountDto =
|
||||
try:
|
||||
let response = status_go.saveAccountAndLogin(hashedPassword, account,
|
||||
subaccounts, settings, config)
|
||||
let response = status_account.saveAccountAndLogin(hashedPassword, account, subaccounts, settings, config)
|
||||
|
||||
var error = "response doesn't contain \"error\""
|
||||
if(response.result.contains("error")):
|
||||
|
@ -213,8 +213,7 @@ proc getAccountSettings(self: Service, accountId: string,
|
|||
if(self.importedAccount.id == accountId):
|
||||
return self.prepareAccountSettingsJsonObject(self.importedAccount, installationId)
|
||||
|
||||
proc getDefaultNodeConfig*(self: Service, fleetConfig: FleetConfig,
|
||||
installationId: string): JsonNode =
|
||||
proc getDefaultNodeConfig*(self: Service, installationId: string): JsonNode =
|
||||
let networkConfig = getNetworkConfig(DEFAULT_NETWORK_NAME)
|
||||
let upstreamUrl = networkConfig["config"]["UpstreamConfig"]["URL"]
|
||||
let fleet = Fleet.PROD
|
||||
|
@ -223,10 +222,10 @@ proc getDefaultNodeConfig*(self: Service, fleetConfig: FleetConfig,
|
|||
newDataDir.removeSuffix("_rpc")
|
||||
result = NODE_CONFIG.copy()
|
||||
result["ClusterConfig"]["Fleet"] = newJString($fleet)
|
||||
result["ClusterConfig"]["BootNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Bootnodes)
|
||||
result["ClusterConfig"]["TrustedMailServers"] = %* fleetConfig.getNodes(fleet, FleetNodes.Mailservers)
|
||||
result["ClusterConfig"]["StaticNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Whisper)
|
||||
result["ClusterConfig"]["RendezvousNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Rendezvous)
|
||||
result["ClusterConfig"]["BootNodes"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Bootnodes)
|
||||
result["ClusterConfig"]["TrustedMailServers"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Mailservers)
|
||||
result["ClusterConfig"]["StaticNodes"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Whisper)
|
||||
result["ClusterConfig"]["RendezvousNodes"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Rendezvous)
|
||||
result["NetworkId"] = networkConfig["config"]["NetworkId"]
|
||||
result["DataDir"] = newDataDir.newJString()
|
||||
result["UpstreamConfig"]["Enabled"] = networkConfig["config"]["UpstreamConfig"]["Enabled"]
|
||||
|
@ -235,22 +234,21 @@ proc getDefaultNodeConfig*(self: Service, fleetConfig: FleetConfig,
|
|||
|
||||
# TODO: fleet.status.im should have different sections depending on the node type
|
||||
# or maybe it's not necessary because a node has the identify protocol
|
||||
result["ClusterConfig"]["RelayNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||
result["ClusterConfig"]["StoreNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||
result["ClusterConfig"]["FilterNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||
result["ClusterConfig"]["LightpushNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku)
|
||||
result["ClusterConfig"]["RelayNodes"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Waku)
|
||||
result["ClusterConfig"]["StoreNodes"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Waku)
|
||||
result["ClusterConfig"]["FilterNodes"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Waku)
|
||||
result["ClusterConfig"]["LightpushNodes"] = %* self.fleetConfiguration.getNodes(fleet, FleetNodes.Waku)
|
||||
|
||||
# TODO: commented since it's not necessary (we do the connections thru C bindings). Enable it thru an option once status-nodes are able to be configured in desktop
|
||||
# result["ListenAddr"] = if existsEnv("STATUS_PORT"): newJString("0.0.0.0:" & $getEnv("STATUS_PORT")) else: newJString("0.0.0.0:30305")
|
||||
|
||||
method setupAccount*(self: Service, fleetConfig: FleetConfig, accountId,
|
||||
password: string): bool =
|
||||
method setupAccount*(self: Service, accountId, password: string): bool =
|
||||
try:
|
||||
let installationId = $genUUID()
|
||||
let accountDataJson = self.getAccountDataForAccountId(accountId)
|
||||
let subaccountDataJson = self.getSubaccountDataForAccountId(accountId)
|
||||
let settingsJson = self.getAccountSettings(accountId, installationId)
|
||||
let nodeConfigJson = self.getDefaultNodeConfig(fleetConfig, installationId)
|
||||
let nodeConfigJson = self.getDefaultNodeConfig(installationId)
|
||||
|
||||
if(accountDataJson.isNil or subaccountDataJson.isNil or settingsJson.isNil or
|
||||
nodeConfigJson.isNil):
|
||||
|
@ -261,8 +259,8 @@ method setupAccount*(self: Service, fleetConfig: FleetConfig, accountId,
|
|||
let hashedPassword = hashString(password)
|
||||
discard self.storeDerivedAccounts(accountId, hashedPassword, PATHS)
|
||||
|
||||
self.loggedInAccount = self.saveAccountAndLogin(hashedPassword,
|
||||
accountDataJson, subaccountDataJson, settingsJson, nodeConfigJson)
|
||||
self.loggedInAccount = self.saveAccountAndLogin(hashedPassword, accountDataJson, subaccountDataJson, settingsJson,
|
||||
nodeConfigJson)
|
||||
|
||||
return self.getLoggedInAccount.isValid()
|
||||
|
||||
|
@ -272,16 +270,15 @@ method setupAccount*(self: Service, fleetConfig: FleetConfig, accountId,
|
|||
|
||||
method importMnemonic*(self: Service, mnemonic: string): bool =
|
||||
try:
|
||||
let response = status_go.multiAccountImportMnemonic(mnemonic)
|
||||
let response = status_account.multiAccountImportMnemonic(mnemonic)
|
||||
self.importedAccount = toGeneratedAccountDto(response.result)
|
||||
|
||||
let responseDerived = status_go.deriveAccounts(self.importedAccount.id, PATHS)
|
||||
let responseDerived = status_account.deriveAccounts(self.importedAccount.id, PATHS)
|
||||
self.importedAccount.derivedAccounts = toDerivedAccounts(responseDerived.result)
|
||||
|
||||
self.importedAccount.alias= self.generateAlias(self.importedAccount.derivedAccounts.whisper.publicKey)
|
||||
|
||||
let responseIdenticon = status_go.generateIdenticon(
|
||||
self.importedAccount.derivedAccounts.whisper.publicKey)
|
||||
let responseIdenticon = status_account.generateIdenticon(self.importedAccount.derivedAccounts.whisper.publicKey)
|
||||
self.importedAccount.identicon = responseIdenticon.result.getStr
|
||||
|
||||
return self.importedAccount.isValid()
|
||||
|
@ -301,7 +298,7 @@ method login*(self: Service, account: AccountDto, password: string): string =
|
|||
elif(img.imgType == "large"):
|
||||
largeImage = img.uri
|
||||
|
||||
let response = status_go.login(account.name, account.keyUid, hashedPassword, account.identicon, thumbnailImage,
|
||||
let response = status_account.login(account.name, account.keyUid, hashedPassword, account.identicon, thumbnailImage,
|
||||
largeImage)
|
||||
|
||||
var error = "response doesn't contain \"error\""
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import ./dto/accounts as dto_accounts
|
||||
import ./dto/generated_accounts as dto_generated_accounts
|
||||
|
||||
import status/fleet as status_lib_fleet
|
||||
|
||||
export dto_accounts
|
||||
export dto_generated_accounts
|
||||
export status_lib_fleet
|
||||
|
||||
type
|
||||
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
@ -17,37 +14,31 @@ method delete*(self: ServiceInterface) {.base.} =
|
|||
method init*(self: ServiceInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method openedAccounts*(self: ServiceInterface):
|
||||
seq[AccountDto] {.base.} =
|
||||
method openedAccounts*(self: ServiceInterface): seq[AccountDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method generatedAccounts*(self: ServiceInterface):
|
||||
seq[GeneratedAccountDto] {.base.} =
|
||||
method generatedAccounts*(self: ServiceInterface): seq[GeneratedAccountDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setupAccount*(self: ServiceInterface, fleetConfig: FleetConfig,
|
||||
accountId, password: string): bool {.base.} =
|
||||
method setupAccount*(self: ServiceInterface, accountId, password: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getLoggedInAccount*(self: ServiceInterface): AccountDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getImportedAccount*(self: ServiceInterface): GeneratedAccountDto
|
||||
{.base.} =
|
||||
method getImportedAccount*(self: ServiceInterface): GeneratedAccountDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isFirstTimeAccountLogin*(self: ServiceInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method validateMnemonic*(self: ServiceInterface, mnemonic: string):
|
||||
string {.base.} =
|
||||
method validateMnemonic*(self: ServiceInterface, mnemonic: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method importMnemonic*(self: ServiceInterface, mnemonic: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method login*(self: ServiceInterface, account: AccountDto, password: string):
|
||||
string {.base.} =
|
||||
method login*(self: ServiceInterface, account: AccountDto, password: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method clear*(self: ServiceInterface) {.base.} =
|
||||
|
|
Loading…
Reference in New Issue