コード例 #1
0
ファイル: controller.py プロジェクト: vesellov/PyWallet
 def fetch_balance(self):
     """
     Fetches the new balance & sets accounts_balance property.
     """
     if self.current_account is None:
         return
     address = '0x' + self.current_account.address.hex()
     chain_id = Settings.get_stored_network()
     try:
         balance = PyWalib.get_balance(address, chain_id)
     except ConnectionError:
         Dialog.on_balance_connection_error()
         Logger.warning('ConnectionError', exc_info=True)
         return
     except ValueError:
         # most likely the JSON object could not be decoded, refs #91
         # currently logged as an error, because we want more insight
         # in order to eventually handle it more specifically
         Dialog.on_balance_value_error()
         Logger.error('ValueError', exc_info=True)
         return
     except UnknownEtherscanException:
         # also handles uknown errors, refs #112
         Dialog.on_balance_unknown_error()
         Logger.error('UnknownEtherscanException', exc_info=True)
         return
     # triggers accounts_balance observers update
     self.accounts_balance[address] = balance
コード例 #2
0
ファイル: test_pywalib.py プロジェクト: imouren/PyWallet
 def test_get_balance(self):
     """
     Checks get_balance() returns a float.
     """
     address = ADDRESS
     balance_eth = PyWalib.get_balance(address)
     self.assertTrue(type(balance_eth), float)
コード例 #3
0
class Controller(FloatLayout):

    current_account = ObjectProperty(None, allownone=True)
    # keeps track of all dialogs alive
    dialogs = []

    def __init__(self, **kwargs):
        super(Controller, self).__init__(**kwargs)
        keystore_path = Controller.get_keystore_path()
        self.pywalib = PyWalib(keystore_path)
        Clock.schedule_once(lambda dt: self.load_landing_page())

    @property
    def overview(self):
        overview_bnavigation_id = self.ids.overview_bnavigation_id
        return overview_bnavigation_id.ids.overview_id

    @property
    def history(self):
        return self.overview.ids.history_id

    @property
    def send(self):
        overview_bnavigation_id = self.ids.overview_bnavigation_id
        return overview_bnavigation_id.ids.send_id

    @property
    def toolbar(self):
        return self.ids.toolbar_id

    def set_toolbar_title(self, title):
        self.toolbar.title_property = title

    def open_account_list_helper(self, on_selected_item):
        title = "Select account"
        items = []
        pywalib = self.pywalib
        account_list = pywalib.get_account_list()
        for account in account_list:
            address = '0x' + account.address.encode("hex")
            item = OneLineListItem(text=address)
            # makes sure the address doesn't wrap in multiple lines,
            # but gets shortened
            item.ids._lbl_primary.shorten = True
            item.account = account
            items.append(item)
        dialog = Controller.create_list_dialog(title, items, on_selected_item)
        dialog.open()

    def open_account_list_overview(self):
        def on_selected_item(instance, value):
            self.set_current_account(value.account)

        self.open_account_list_helper(on_selected_item)

    def set_current_account(self, account):
        self.current_account = account

    def on_current_account(self, instance, value):
        """
        Updates Overview.current_account and History.current_account,
        then fetch account data.
        """
        self.overview.current_account = value
        self.history.current_account = value
        self._load_balance()

    @staticmethod
    def show_invalid_form_dialog():
        title = "Invalid form"
        body = "Please check form fields."
        dialog = Controller.create_dialog(title, body)
        dialog.open()

    @staticmethod
    def patch_keystore_path():
        """
        Changes pywalib default keystore path depending on platform.
        Currently only updates it on Android.
        """
        if platform != "android":
            return
        import pywalib
        # uses kivy user_data_dir (/sdcard/<app_name>)
        pywalib.KEYSTORE_DIR_PREFIX = App.get_running_app().user_data_dir

    @staticmethod
    def get_keystore_path():
        """
        This is the Kivy default keystore path.
        """
        keystore_path = os.environ.get('KEYSTORE_PATH')
        if keystore_path is None:
            Controller.patch_keystore_path()
            keystore_path = PyWalib.get_default_keystore_path()
        return keystore_path

    @staticmethod
    def src_dir():
        return os.path.dirname(os.path.abspath(__file__))

    @staticmethod
    def create_list_dialog(title, items, on_selected_item):
        """
        Creates a dialog from given title and list.
        items is a list of BaseListItem objects.
        """
        # select_list = PWSelectList(items=items, on_release=on_release)
        select_list = PWSelectList(items=items)
        select_list.bind(selected_item=on_selected_item)
        content = select_list
        dialog = MDDialog(title=title, content=content, size_hint=(.9, .9))
        # workaround for MDDialog container size (too small by default)
        dialog.ids.container.size_hint_y = 1
        # close the dialog as we select the element
        select_list.bind(
            selected_item=lambda instance, value: dialog.dismiss())
        dialog.add_action_button("Dismiss", action=lambda *x: dialog.dismiss())
        return dialog

    @staticmethod
    def on_dialog_dismiss(dialog):
        """
        Removes it from the dialogs track list.
        """
        Controller.dialogs.remove(dialog)

    @staticmethod
    def dismiss_all_dialogs():
        """
        Dispatches dismiss event for all dialogs.
        """
        dialogs = Controller.dialogs[:]
        for dialog in dialogs:
            dialog.dispatch('on_dismiss')

    @staticmethod
    def create_dialog(title, body):
        """
        Creates a dialog from given title and body.
        Adds it to the dialogs track list.
        """
        content = MDLabel(font_style='Body1',
                          theme_text_color='Secondary',
                          text=body,
                          size_hint_y=None,
                          valign='top')
        content.bind(texture_size=content.setter('size'))
        dialog = MDDialog(title=title,
                          content=content,
                          size_hint=(.8, None),
                          height=dp(200),
                          auto_dismiss=False)
        dialog.add_action_button("Dismiss", action=lambda *x: dialog.dismiss())
        dialog.bind(on_dismiss=Controller.on_dialog_dismiss)
        Controller.dialogs.append(dialog)
        return dialog

    @staticmethod
    def on_balance_connection_error():
        title = "Network error"
        body = "Couldn't load balance, no network access."
        dialog = Controller.create_dialog(title, body)
        dialog.open()

    @staticmethod
    def on_history_connection_error():
        title = "Network error"
        body = "Couldn't load history, no network access."
        dialog = Controller.create_dialog(title, body)
        dialog.open()

    @staticmethod
    def show_not_implemented_dialog():
        title = "Not implemented"
        body = "This feature is not yet implemented."
        dialog = Controller.create_dialog(title, body)
        dialog.open()

    @mainthread
    def update_balance_label(self, balance):
        overview_id = self.overview
        overview_id.balance_property = balance

    def get_overview_title(self):
        overview_id = self.overview
        return overview_id.get_title()

    @staticmethod
    @mainthread
    def snackbar_message(text):
        Snackbar(text=text).show()

    def load_landing_page(self):
        """
        Loads the landing page.
        """
        try:
            # will trigger account data fetching
            self.current_account = self.pywalib.get_main_account()
            self.ids.screen_manager_id.current = "overview"
            self.ids.screen_manager_id.transition.direction = "right"
        except IndexError:
            self.load_create_new_account()

    @run_in_thread
    def _load_balance(self):
        account = self.current_account
        try:
            balance = self.pywalib.get_balance(account.address.encode("hex"))
        except ConnectionError:
            Controller.on_balance_connection_error()
            return
        self.update_balance_label(balance)

    def load_manage_keystores(self):
        """
        Loads the manage keystores screen.
        """
        # loads the manage keystores screen
        self.ids.screen_manager_id.transition.direction = "left"
        self.ids.screen_manager_id.current = 'manage_keystores'

    def load_create_new_account(self):
        """
        Loads the create new account tab from the maage keystores screen.
        """
        self.load_manage_keystores()
        # loads the create new account tab
        manage_keystores = self.ids.manage_keystores_id
        create_new_account = manage_keystores.ids.create_new_account_id
        create_new_account.dispatch('on_tab_press')

    def load_about_screen(self):
        """
        Loads the about screen.
        """
        self.ids.screen_manager_id.transition.direction = "left"
        self.ids.screen_manager_id.current = "about"