diff --git a/src/sakia/app.py b/src/sakia/app.py index f046032e292b0deaad43734737afdf1bd55b6452..8402fb1a8addcb1983ee0a09457df3722c242051 100644 --- a/src/sakia/app.py +++ b/src/sakia/app.py @@ -1,7 +1,13 @@ +import os +import shutil + import attr import datetime import logging import socket + +import yaml + import sakia.i18n_rc import async_timeout import aiohttp @@ -83,10 +89,11 @@ class Application(QObject): loop = attr.ib() options = attr.ib() app_data = attr.ib() - parameters = attr.ib() - db = attr.ib() - currency = attr.ib() - plugins_dir = attr.ib() + root_servers = attr.ib(default=None) + parameters = attr.ib(default=None) + db = attr.ib(default=None) + currency = attr.ib(default=None) + plugins_dir = attr.ib(default=None) network_service = attr.ib(default=None) blockchain_service = attr.ib(default=None) identities_service = attr.ib(default=None) @@ -109,13 +116,40 @@ class Application(QObject): qapp.setAttribute(Qt.AA_EnableHighDpiScaling, True) options = SakiaOptions.from_arguments(argv) app_data = AppDataFile.in_config_path(options.config_path).load_or_init() - app = cls(qapp, loop, options, app_data, None, None, options.currency, None) + app = cls( + qapp, loop, options, app_data, None, None, None, options.currency, None + ) + app.load_root_servers() # app.set_proxy() app.load_profile(options.profile) app.documents_service = DocumentsService.instanciate(app) app.switch_language() return app + def load_root_servers(self): + """ + Load root servers config + + :return: + """ + filename = "root_servers.yml" + root_servers_default_path = os.path.join(os.path.dirname(__file__), filename) + root_servers_config_path = os.path.join(self.options.config_path, filename) + self._logger.debug( + "Check root servers config file: {}...".format(root_servers_config_path) + ) + if not os.path.exists(root_servers_config_path): + self._logger.debug( + "Create root servers config file: {}".format(root_servers_config_path) + ) + shutil.copy(root_servers_default_path, root_servers_config_path) + + self._logger.debug( + "Load root servers config file: {}".format(root_servers_config_path) + ) + with open(root_servers_config_path, "r", encoding="utf-8",) as stream: + self.root_servers = yaml.load(stream, Loader=yaml.FullLoader) + def load_profile(self, profile_name): """ Initialize databases depending on profile loaded @@ -149,7 +183,7 @@ class Application(QObject): sources_processor = SourcesProcessor.instanciate(self) transactions_processor = TransactionsProcessor.instanciate(self) dividends_processor = DividendsProcessor.instanciate(self) - nodes_processor.initialize_root_nodes(self.currency) + nodes_processor.initialize_root_nodes(self.currency, self.root_servers) self.db.commit() self.documents_service = DocumentsService.instanciate(self) diff --git a/src/sakia/constants.py b/src/sakia/constants.py index 28c73bb8270c0520dffc021099f7d15042a5cce8..b3a5c983b3a48b7f9c5993514634dd41ba6d64ab 100644 --- a/src/sakia/constants.py +++ b/src/sakia/constants.py @@ -1,13 +1,7 @@ import os -import yaml MAX_CONFIRMATIONS = 6 -with open( - os.path.join(os.path.dirname(__file__), "root_servers.yml"), "r", encoding="utf-8" -) as stream: - ROOT_SERVERS = yaml.load(stream, Loader=yaml.FullLoader) - with open( os.path.join(os.path.dirname(__file__), "g1_license.html"), "r", encoding="utf-8" ) as stream: diff --git a/src/sakia/data/files/root_servers.py b/src/sakia/data/files/root_servers.py new file mode 100644 index 0000000000000000000000000000000000000000..aa96c69b1c59793d5273f68ac6294b345d531afe --- /dev/null +++ b/src/sakia/data/files/root_servers.py @@ -0,0 +1,35 @@ +import attr +import json +import os +import logging + + +@attr.s(frozen=True) +class RootServersFile: + """ + The repository for RootServers + """ + + _file = attr.ib() + _logger = attr.ib(default=attr.Factory(lambda: logging.getLogger("sakia"))) + filename = "root_servers.yml" + + @classmethod + def in_config_path(cls, config_path, profile_name): + if not os.path.exists(os.path.join(config_path, profile_name)): + os.makedirs(os.path.join(config_path, profile_name)) + return cls(os.path.join(config_path, profile_name, RootServersFile.filename)) + + def load_or_init(self, profile_name): + """ + Update root_servers constant + + :param sakia.data.entities.UserParameters user_parameters: the user_parameters to update + """ + try: + with open(self._file, "r") as json_data: + user_parameters = UserParameters(**json.load(json_data)) + user_parameters.profile_name = profile_name + except (OSError, json.decoder.JSONDecodeError): + user_parameters = UserParameters(profile_name=profile_name) + return user_parameters diff --git a/src/sakia/data/processors/nodes.py b/src/sakia/data/processors/nodes.py index ee56ae65cb5b15c932ecd2128bcd8586ddd91c73..474883a659aab0365781822e9e64cc612c53c6bf 100644 --- a/src/sakia/data/processors/nodes.py +++ b/src/sakia/data/processors/nodes.py @@ -1,9 +1,6 @@ import attr import sqlite3 -from duniterpy.documents.ws2p.heads import HeadV2 - -from sakia.constants import ROOT_SERVERS from ..entities import Node from duniterpy.documents import BlockUID import logging @@ -14,17 +11,13 @@ import time class NodesProcessor: _repo = attr.ib() # :type sakia.data.repositories.NodesRepo - @classmethod - def instanciate(cls, app): - return cls(app.db.nodes_repo) - - def initialize_root_nodes(self, currency): + def initialize_root_nodes(self, currency, root_servers): if not self.nodes(currency): - for pubkey in ROOT_SERVERS[currency]["nodes"]: + for pubkey in root_servers[currency]["nodes"]: node = Node( currency=currency, pubkey=pubkey, - endpoints=ROOT_SERVERS[currency]["nodes"][pubkey], + endpoints=root_servers[currency]["nodes"][pubkey], peer_blockstamp=BlockUID.empty(), state=0, ) @@ -187,9 +180,3 @@ class NodesProcessor: node.last_state_change = time.time() node.state = min(5, node.state + weight) self.update_node(node) - - def drop_all(self, currency): - nodes = self._repo.get_all() - for n in nodes: - if n.pubkey not in ROOT_SERVERS[currency].keys(): - self._repo.drop(n) diff --git a/src/sakia/gui/dialogs/connection_cfg/controller.py b/src/sakia/gui/dialogs/connection_cfg/controller.py index c6b3e4458a819860b8d4be9de92ceb0ef4cf10b1..893b17ca1efaf1533c889be63222852009320479 100644 --- a/src/sakia/gui/dialogs/connection_cfg/controller.py +++ b/src/sakia/gui/dialogs/connection_cfg/controller.py @@ -71,7 +71,7 @@ class ConnectionConfigController(QObject): :return: a new AccountConfigController controller :rtype: AccountConfigController """ - view = ConnectionConfigView(parent.view if parent else None) + view = ConnectionConfigView(parent.view if parent else None, app) model = ConnectionConfigModel( None, app, None, IdentitiesProcessor.instanciate(app) ) diff --git a/src/sakia/gui/dialogs/connection_cfg/view.py b/src/sakia/gui/dialogs/connection_cfg/view.py index f568a810b5311c6206a56f32838d3d8eedce9a22..4eeee1d6bc65517d3dbfbe698be0e0fbce69d878 100644 --- a/src/sakia/gui/dialogs/connection_cfg/view.py +++ b/src/sakia/gui/dialogs/connection_cfg/view.py @@ -1,4 +1,3 @@ -import asyncio from PyQt5.QtWidgets import QDialog from PyQt5.QtCore import pyqtSignal, Qt, QElapsedTimer, QDateTime, QCoreApplication from .connection_cfg_uic import Ui_ConnectionConfigurationDialog @@ -7,10 +6,10 @@ from duniterpy.key import SigningKey from duniterpy.key.scrypt_params import ScryptParams from math import ceil, log from sakia.gui.widgets import toast -from sakia.decorators import asyncify from sakia.helpers import timestamp_to_dhms from sakia.gui.widgets.dialogs import dialog_async_exec, QAsyncMessageBox -from sakia.constants import ROOT_SERVERS, G1_LICENSE +from sakia.constants import G1_LICENSE +from sakia.app import Application class ConnectionConfigView(QDialog, Ui_ConnectionConfigurationDialog): @@ -20,11 +19,14 @@ class ConnectionConfigView(QDialog, Ui_ConnectionConfigurationDialog): values_changed = pyqtSignal() - def __init__(self, parent): + def __init__(self, parent, app: Application): """ - Constructor + Init ConnectionConfigView + :param parent: Parent QObject + :param app: Application instance """ super().__init__(parent) + self.app = app self.setupUi(self) self.last_speed = 0.1 self.average_speed = 1 @@ -156,7 +158,7 @@ class ConnectionConfigView(QDialog, Ui_ConnectionConfigurationDialog): self.setWindowTitle( QCoreApplication.translate( "ConnectionConfigView", "New sakia account on {0} network" - ).format(ROOT_SERVERS[currency]["display"]) + ).format(self.app.root_servers[currency]["display"]) ) def action_show_pubkey(self): diff --git a/src/sakia/gui/dialogs/contact/controller.py b/src/sakia/gui/dialogs/contact/controller.py index 658ae806a64844213a19f2a4e14704b3c08778ec..1933c9a0d30e1368cee3284a2ca0fd3a905689d9 100644 --- a/src/sakia/gui/dialogs/contact/controller.py +++ b/src/sakia/gui/dialogs/contact/controller.py @@ -1,14 +1,6 @@ import asyncio -from PyQt5.QtCore import Qt, QObject -from PyQt5.QtWidgets import QApplication - -from sakia.constants import ROOT_SERVERS -from sakia.decorators import asyncify -from sakia.gui.sub.search_user.controller import SearchUserController -from sakia.gui.sub.user_information.controller import UserInformationController -from sakia.gui.sub.password_input import PasswordInputController -from sakia.gui.widgets import dialogs +from PyQt5.QtCore import QObject from .model import ContactModel from .view import ContactView import attr @@ -52,8 +44,6 @@ class ContactController(QObject): Certify and identity :param sakia.gui.component.controller.ComponentController parent: the parent :param sakia.core.Application app: the application - :param sakia.core.Account account: the account certifying the identity - :param sakia.core.Community community: the community :return: """ dialog = cls.create(parent, app) diff --git a/src/sakia/gui/main_window/controller.py b/src/sakia/gui/main_window/controller.py index 18be94e1fe3832e38959ed38853b8da919d5373b..25c7f7ccb3de1b1b99e09de6a4b110fcb65989c7 100644 --- a/src/sakia/gui/main_window/controller.py +++ b/src/sakia/gui/main_window/controller.py @@ -4,7 +4,6 @@ from PyQt5.QtCore import QEvent, pyqtSlot, QObject, QCoreApplication from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QMessageBox, QApplication -from sakia.constants import ROOT_SERVERS from .model import MainWindowModel from .status_bar.controller import StatusBarController from .toolbar.controller import ToolbarController @@ -128,7 +127,7 @@ class MainWindowController(QObject): in the window have to be refreshed """ self.status_bar.refresh() - display_name = ROOT_SERVERS[currency]["display"] + display_name = self.model.app.root_servers[currency]["display"] self.view.setWindowTitle( QCoreApplication.translate( "MainWindowController", "sakia {0} - {1}" diff --git a/src/sakia/gui/main_window/toolbar/model.py b/src/sakia/gui/main_window/toolbar/model.py index 4fa75079fa6fc17e39357d8413a1f897ee421396..15e64c056043145bdb86e17da6511899d65289d1 100644 --- a/src/sakia/gui/main_window/toolbar/model.py +++ b/src/sakia/gui/main_window/toolbar/model.py @@ -3,8 +3,6 @@ from sakia.data.processors import ConnectionsProcessor import attr import math from sakia import __version__ -from sakia.constants import ROOT_SERVERS -from duniterpy.api import errors from sakia.money import Referentials @@ -74,7 +72,7 @@ class ToolbarModel(QObject): # try to request money parameters params = self.blockchain_service.parameters() - localized_data["currency"] = ROOT_SERVERS[self.app.currency]["display"] + localized_data["currency"] = self.app.root_servers[self.app.currency]["display"] localized_data["growth"] = params.c localized_data["growth_per_dt"] = QLocale().toString( params.c / (params.dt_reeval / params.dt), "f", 8 diff --git a/src/sakia/gui/navigation/identity/controller.py b/src/sakia/gui/navigation/identity/controller.py index 8072c364b633f80a4aa0d88c1e05772efd6fbc9f..9beae4a81e880270db70cb18ab2ab7c8bd57014c 100644 --- a/src/sakia/gui/navigation/identity/controller.py +++ b/src/sakia/gui/navigation/identity/controller.py @@ -1,10 +1,8 @@ import logging from PyQt5.QtGui import QCursor -from PyQt5.QtWidgets import QAction from PyQt5.QtCore import QObject, pyqtSignal, QCoreApplication from sakia.errors import NoPeerAvailable -from sakia.constants import ROOT_SERVERS from sakia.data.entities import Identity from duniterpy.api import errors from .model import IdentityModel @@ -63,7 +61,7 @@ class IdentityController(QObject): certification = CertificationController.integrate_to_main_view( None, app, connection ) - view = IdentityView(parent.view, certification.view) + view = IdentityView(parent.view, certification.view, app) model = IdentityModel( None, app, @@ -106,7 +104,8 @@ class IdentityController(QObject): params = self.model.parameters() if params: self.view.set_money_text( - params, ROOT_SERVERS[self.model.connection.currency]["display"] + params, + self.model.app.root_servers[self.model.connection.currency]["display"], ) self.refresh_localized_data() diff --git a/src/sakia/gui/navigation/identity/model.py b/src/sakia/gui/navigation/identity/model.py index 9366a086097e9dcfb0a17637c80ce8fe610d4224..0b953926ab96e56fd5f353e5435309a9b7037737 100644 --- a/src/sakia/gui/navigation/identity/model.py +++ b/src/sakia/gui/navigation/identity/model.py @@ -11,7 +11,6 @@ from PyQt5.QtCore import ( QCoreApplication, ) from sakia.errors import NoPeerAvailable -from sakia.constants import ROOT_SERVERS from .table_model import CertifiersTableModel, CertifiersFilterProxyModel from sakia.data.processors import BlockchainProcessor from duniterpy.api import errors @@ -99,7 +98,9 @@ class IdentityModel(QObject): logging.debug("community parameters error: " + str(e)) return None - localized_data["currency"] = ROOT_SERVERS[self.connection.currency]["display"] + localized_data["currency"] = self.app.root_servers[self.connection.currency][ + "display" + ] localized_data["growth"] = params.c localized_data["dt_reeval_in_days"] = QLocale().toString( params.dt_reeval / 86400, "f", 2 diff --git a/src/sakia/gui/navigation/identity/view.py b/src/sakia/gui/navigation/identity/view.py index 55842c14a145ba90a1e1f55b17dc926c9b4f4bf4..c99f0da2eafe94c9d52970bab6609e71307a90fa 100644 --- a/src/sakia/gui/navigation/identity/view.py +++ b/src/sakia/gui/navigation/identity/view.py @@ -1,10 +1,20 @@ from PyQt5.QtWidgets import QWidget, QMessageBox, QAbstractItemView, QHeaderView -from PyQt5.QtCore import QEvent, QLocale, pyqtSignal, Qt, QDateTime, QCoreApplication +from PyQt5.QtCore import ( + QEvent, + QLocale, + pyqtSignal, + Qt, + QDateTime, + QCoreApplication, + QObject, +) + +from sakia.app import Application from .identity_uic import Ui_IdentityWidget from enum import Enum from sakia.helpers import timestamp_to_dhms -from sakia.constants import ROOT_SERVERS from sakia.gui.widgets.dialogs import dialog_async_exec +from ...sub.certification.view import CertificationView class IdentityView(QWidget, Ui_IdentityWidget): @@ -19,8 +29,17 @@ class IdentityView(QWidget, Ui_IdentityWidget): OFFLINE = 1 READY = 2 - def __init__(self, parent, certification_view): + def __init__( + self, parent: QObject, certification_view: CertificationView, app: Application + ): + """ + Init IdentityView + :param parent: QObject instance + :param certification_view: CertificationView instance + :param app: Application instance + """ super().__init__(parent) + self.app = app self.certification_view = certification_view self.setupUi(self) self.stacked_widget.insertWidget(1, certification_view) @@ -254,7 +273,7 @@ The parameters of the Web of Trust of {:} are :<br/> <b>By asking to join as member, you recognize that this is your unique account, and that you will only certify persons that you know well enough.</b> """.format( - ROOT_SERVERS[currency]["display"], + self.app.root_servers[currency]["display"], params.c, QLocale().toString(params.dt / 86400, "f", 2), QCoreApplication.translate("IdentityView", "Fundamental growth (c)"), @@ -262,7 +281,7 @@ and that you will only certify persons that you know well enough.</b> QCoreApplication.translate( "IdentityView", "Initial Universal Dividend UD(0) in" ), - ROOT_SERVERS[currency]["display"], + self.app.root_servers[currency]["display"], dt_as_str, QCoreApplication.translate( "IdentityView", "Time period between two UD" @@ -271,7 +290,7 @@ and that you will only certify persons that you know well enough.</b> QCoreApplication.translate( "IdentityView", "Time period between two UD reevaluation" ), - ROOT_SERVERS[currency]["display"], + self.app.root_servers[currency]["display"], QLocale().toString(params.sig_period / 86400, "f", 2), QCoreApplication.translate( "IdentityView", "Minimum delay between 2 certifications (in days)" diff --git a/src/sakia/gui/sub/certification/controller.py b/src/sakia/gui/sub/certification/controller.py index 00a69a0378f9bc070dc3e9c7e79af4b7be68729f..de59e4dd61c44a5a9d6005d2445b824892f3e8fe 100644 --- a/src/sakia/gui/sub/certification/controller.py +++ b/src/sakia/gui/sub/certification/controller.py @@ -1,7 +1,6 @@ from PyQt5.QtCore import Qt, QObject, pyqtSignal, QCoreApplication from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout -from sakia.constants import ROOT_SERVERS from sakia.decorators import asyncify from sakia.gui.sub.search_user.controller import SearchUserController from sakia.gui.sub.user_information.controller import UserInformationController @@ -55,6 +54,7 @@ class CertificationController(QObject): search_user.view, user_information.view, password_input.view, + app, ) model = CertificationModel(app) view.set_label_confirm(app.currency) @@ -160,7 +160,7 @@ The 2°) is however preferable to the 3°)... whereas <b>1°) is mandatory in an <b>Reminder</b>: Certifying is not only uniquely ensuring that you met the person, its ensuring the {:} community that you know her well enough and that you will know how to find a double account done by a person certified by you using cross checking which will help to reveal the problem if needs to be.</br>""".format( - ROOT_SERVERS[self.model.app.currency]["display"] + self.model.app.root_servers[self.model.app.currency]["display"] ), ) if result == dialogs.QMessageBox.No: diff --git a/src/sakia/gui/sub/certification/view.py b/src/sakia/gui/sub/certification/view.py index ba6bec59985321e59541e9585e25a40bf409bd71..5915359dd3e0131e3595d4eb1a2e73a70d593faf 100644 --- a/src/sakia/gui/sub/certification/view.py +++ b/src/sakia/gui/sub/certification/view.py @@ -1,12 +1,18 @@ from PyQt5.QtWidgets import QWidget, QDialogButtonBox, QFileDialog, QMessageBox -from PyQt5.QtCore import QT_TRANSLATE_NOOP, Qt, pyqtSignal, QCoreApplication +from PyQt5.QtCore import QT_TRANSLATE_NOOP, Qt, pyqtSignal, QCoreApplication, QObject + +from sakia.app import Application from .certification_uic import Ui_CertificationWidget from sakia.gui.widgets import toast from sakia.gui.widgets.dialogs import QAsyncMessageBox -from sakia.constants import ROOT_SERVERS, G1_LICENSE +from sakia.constants import G1_LICENSE from duniterpy.documents import Identity, MalformedDocumentError from enum import Enum +from ..password_input.view import PasswordInputView +from ..search_user.view import SearchUserView +from ..user_information.view import UserInformationView + class CertificationView(QWidget, Ui_CertificationWidget): """ @@ -57,18 +63,25 @@ class CertificationView(QWidget, Ui_CertificationWidget): identity_document_imported = pyqtSignal(Identity) def __init__( - self, parent, search_user_view, user_information_view, password_input_view + self, + parent: QObject, + search_user_view: SearchUserView, + user_information_view: UserInformationView, + password_input_view: PasswordInputView, + app: Application, ): """ + Init CertificationView - :param parent: - :param sakia.gui.search_user.view.SearchUserView search_user_view: - :param sakia.gui.user_information.view.UserInformationView user_information_view: - :param list[sakia.data.entities.Connection] connections: + :param parent: QObject instance + :param search_user_view: SearchUserView instance + :param user_information_view: UserInformationView instance + :param password_input_view: PasswordInputView instance + :param app: Application instance """ super().__init__(parent) self.setupUi(self) - + self.app = app self.search_user_view = search_user_view self.user_information_view = user_information_view self.password_input_view = password_input_view @@ -141,7 +154,8 @@ class CertificationView(QWidget, Ui_CertificationWidget): self.label_confirm.setText( """<b>Vous confirmez engager votre responsabilité envers la communauté Duniter {:} et acceptez de certifier le compte Duniter {:} sélectionné.<br/><br/>""".format( - ROOT_SERVERS[currency]["display"], ROOT_SERVERS[currency]["display"] + self.app.root_servers[currency]["display"], + self.app.root_servers[currency]["display"], ) ) diff --git a/src/sakia/options.py b/src/sakia/options.py index 54a3a334797bd789ede2cfa22d98231f727330cc..67408f62902423df8b14fee1002a02b0776f7660 100644 --- a/src/sakia/options.py +++ b/src/sakia/options.py @@ -1,7 +1,6 @@ import attr import logging -from sakia.constants import ROOT_SERVERS -from logging import FileHandler, StreamHandler +from logging import StreamHandler from logging.handlers import RotatingFileHandler from optparse import OptionParser from os import environ, path, makedirs @@ -63,7 +62,7 @@ class SakiaOptions: "--currency", dest="currency", default="g1", - help="Select a currency between {0}".format(",".join(ROOT_SERVERS.keys())), + help="Select a currency between g1, g1-test", ) parser.add_option( @@ -82,7 +81,7 @@ class SakiaOptions: (options, args) = parser.parse_args(argv) - if options.currency not in ROOT_SERVERS.keys(): + if options.currency not in ("g1", "g1-test"): raise RuntimeError("{0} is not a valid currency".format(options.currency)) else: self.currency = options.currency diff --git a/src/sakia/root_servers.yml b/src/sakia/root_servers.yml index 0e745ab1d384e2c37095ecf2fadcbb439abbea15..25a2b0ca8ca40003457e74e3f43bfe1b6ac3c37d 100644 --- a/src/sakia/root_servers.yml +++ b/src/sakia/root_servers.yml @@ -3,15 +3,10 @@ g1: nodes: 8iVdpXqFLCxGyPqgVx5YbFSkmWKkceXveRd2yvBKeARL: - "BMAS g1.duniter.org 443" - - "BASIC_MERKLED_API g1.duniter.org 10901" 38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE: - - "BMAS g1.duniter.fr 443" - - "BASIC_MERKLED_API g1.duniter.fr 10901" + - "BMAS g1.e-is.pro 443" D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx: - - "BASIC_MERKLED_API g1-monit.elois.org 10901" - 5cnvo5bmR8QbtyNVnkDXWq6n5My6oNLd1o6auJApGCsv: - - "BASIC_MERKLED_API g1.duniter.inso.ovh 80" - - "BMAS g1.duniter.inso.ovh 443" + - "BMAS g1.elo.tf 443" g1-test: display: ğ1-test nodes: diff --git a/tests/conftest.py b/tests/conftest.py index 1e69c829baefbf74d5f750a4aff0d0f0bdbab259..bee1764ad24ba5d31b4ccb578e41eab9d9cdb65f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,6 @@ from duniterpy.grammars import output sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src"))) -from sakia.constants import ROOT_SERVERS from duniterpy.documents import BlockUID from duniterpy.key.scrypt_params import ScryptParams from sakia.app import Application @@ -95,12 +94,13 @@ def application( event_loop, meta_repo, sakia_options, app_data, user_parameters, plugins_dir ): - ROOT_SERVERS["test_currency"] = {"display": "Fake Currency", "nodes": []} + root_servers = {"test_currency": {"display": "Fake Currency", "nodes": []}} app = Application( qapp=get_application(), loop=event_loop, options=sakia_options, app_data=app_data, + root_servers=root_servers, parameters=user_parameters, db=meta_repo, currency="test_currency",