Exemple #1
0
def main():
    # The hook will only be used in the Qt GUI right now
    setup_thread_excepthook()
    # on osx, delete Process Serial Number arg generated for apps launched in Finder
    sys.argv = [x for x in sys.argv if not x.startswith('-psn')]

    # old 'help' syntax
    if len(sys.argv) > 1 and sys.argv[1] == 'help':
        sys.argv.remove('help')
        sys.argv.append('-h')

    # read arguments from stdin pipe and prompt
    for i, arg in enumerate(sys.argv):
        if arg == '-':
            if not sys.stdin.isatty():
                sys.argv[i] = sys.stdin.read()
                break
            else:
                raise Exception('Cannot get argument from stdin')
        elif arg == '?':
            sys.argv[i] = input("Enter argument:")
        elif arg == ':':
            sys.argv[i] = prompt_password('Enter argument (will not echo):',
                                          False)

    # parse command line
    parser = get_parser()
    args = parser.parse_args()

    # config is an object passed to the various constructors (wallet, interface, gui)
    config_options = args.__dict__
    config_options = {
        key: value
        for key, value in config_options.items()
        if value is not None and key not in config_variables.get(args.cmd, {})
    }

    logs.set_level(config_options['verbose'])

    if config_options.get('server'):
        config_options['auto_connect'] = False
    config_options['cwd'] = os.getcwd()

    # fixme: this can probably be achieved with a runtime hook (pyinstaller)
    try:
        if is_bundle and os.path.exists(
                os.path.join(sys._MEIPASS, 'is_portable')):
            config_options['portable'] = True
    except AttributeError:
        config_options['portable'] = False

    if config_options.get('portable'):
        config_options['electrum_sv_path'] = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), 'electrum_sv_data')

    if config_options.get('file_logging'):
        log_path = os.path.join(platform.user_dir(prefer_local=True), "logs")
        os.makedirs(log_path, exist_ok=True)
        log_path = os.path.join(log_path,
                                time.strftime("%Y%m%d-%H%M%S") + ".log")
        logs.add_file_output(log_path)

    if config_options.get('testnet'):
        Net.set_to(SVTestnet)

    # check uri
    uri = config_options.get('url')
    if uri:
        if not web.is_URI(uri):
            print('unknown command:', uri, file=sys.stderr)
            sys.exit(1)
        config_options['url'] = uri

    # todo: defer this to gui
    config = SimpleConfig(config_options)
    cmdname = config.get('cmd')

    # Set the app state proxy
    if cmdname == 'gui':
        try:
            from electrumsv.gui.qt.app_state import QtAppStateProxy
        except ImportError as e:
            platform.missing_import(e)
        QtAppStateProxy(config, 'qt')
    else:
        AppStateProxy(config, 'cmdline')

    # run non-RPC commands separately
    if cmdname in ['create', 'restore']:
        run_non_RPC(config)
        sys.exit(0)

    if cmdname == 'gui':
        fd, server = daemon.get_fd_or_server(config)
        if fd is not None:
            d = daemon.Daemon(fd, True)
            d.start()
            app_state.app.run_gui()
            sys.exit(0)
        else:
            result = server.gui(config_options)

    elif cmdname == 'daemon':
        subcommand = config.get('subcommand')
        if subcommand in ['load_wallet']:
            init_daemon(config_options)

        if subcommand in [None, 'start']:
            fd, server = daemon.get_fd_or_server(config)
            if fd is not None:
                if subcommand == 'start':
                    pid = os.fork()
                    if pid:
                        print("starting daemon (PID %d)" % pid,
                              file=sys.stderr)
                        sys.exit(0)
                d = daemon.Daemon(fd, False)
                d.start()
                if config.get('websocket_server'):
                    try:
                        from electrumsv import websockets
                    except ImportError as e:
                        platform.missing_import(e)
                    websockets.WebSocketServer(config, d.network).start()
                if config.get('requests_dir'):
                    path = os.path.join(config.get('requests_dir'),
                                        'index.html')
                    if not os.path.exists(path):
                        print("Requests directory not configured.")
                        print("You can configure it using "
                              "https://github.com/spesmilo/electrum-merchant")
                        sys.exit(1)
                d.join()
                sys.exit(0)
            else:
                result = server.daemon(config_options)
        else:
            server = daemon.get_server(config)
            if server is not None:
                result = server.daemon(config_options)
            else:
                print("Daemon not running")
                sys.exit(1)
    else:
        # command line
        server = daemon.get_server(config)
        init_cmdline(config_options, server)
        if server is not None:
            result = server.run_cmdline(config_options)
        else:
            cmd = known_commands[cmdname]
            if cmd.requires_network:
                print("Daemon not running; try 'electrum-sv daemon start'")
                sys.exit(1)
            else:
                result = run_offline_command(config, config_options)
                # print result
    if isinstance(result, str):
        print(result)
    elif type(result) is dict and result.get('error'):
        print(result.get('error'), file=sys.stderr)
    elif result is not None:
        print(json_encode(result))
    sys.exit(0)
Exemple #2
0
def main():
    enforce_requirements()
    setup_windows_console()

    # The hook will only be used in the Qt GUI right now
    setup_thread_excepthook()

    # on osx, delete Process Serial Number arg generated for apps launched in Finder
    sys.argv = [x for x in sys.argv if not x.startswith('-psn')]

    # old 'help' syntax
    if len(sys.argv) > 1 and sys.argv[1] == 'help':
        sys.argv.remove('help')
        sys.argv.append('-h')

    # read arguments from stdin pipe and prompt
    for i, arg in enumerate(sys.argv):
        if arg == '-':
            if not sys.stdin.isatty():
                sys.argv[i] = sys.stdin.read()
                break
            else:
                raise Exception('Cannot get argument from stdin')
        elif arg == '?':
            sys.argv[i] = input("Enter argument:")
        elif arg == ':':
            sys.argv[i] = prompt_password('Enter argument (will not echo):',
                                          False)

    # parse command line
    parser = get_parser()
    args = parser.parse_args()

    # config is an object passed to various constructors
    config_options = args.__dict__
    config_options = {
        key: value
        for key, value in config_options.items()
        if value is not None and key not in config_variables.get(args.cmd, {})
    }

    logs.set_level(config_options['verbose'])

    if config_options.get('server'):
        config_options['auto_connect'] = False
    config_options['cwd'] = os.getcwd()

    # fixme: this can probably be achieved with a runtime hook (pyinstaller)
    portable_base_path = None
    try:
        if startup.is_bundle and os.path.exists(
                os.path.join(sys._MEIPASS, 'is_portable')):
            config_options['portable'] = True
            # Ensure the wallet data is stored in the same directory as the executable.
            portable_base_path = os.path.dirname(sys.executable)
    except AttributeError:
        config_options['portable'] = False

    if config_options.get('portable'):
        if portable_base_path is None:
            # Default to the same directory the 'electrum-sv' script is in.
            portable_base_path = os.path.dirname(os.path.realpath(sys.argv[0]))
        config_options['electrum_sv_path'] = os.path.join(
            portable_base_path, 'electrum_sv_data')

    if config_options.get('file_logging'):
        if config_options.get('portable'):
            log_path = os.path.join(config_options['electrum_sv_path'], "logs")
        else:
            log_path = os.path.join(platform.user_dir(prefer_local=True),
                                    "logs")
        os.makedirs(log_path, exist_ok=True)
        log_path = os.path.join(log_path,
                                time.strftime("%Y%m%d-%H%M%S") + ".log")
        logs.add_file_output(log_path)

    if config_options.get('testnet'):
        Net.set_to(SVTestnet)
    elif config_options.get('scalingtestnet'):
        Net.set_to(SVScalingTestnet)

    # check uri
    uri = config_options.get('url')
    if uri:
        if not web.is_URI(uri):
            print('unknown command:', uri, file=sys.stderr)
            sys.exit(1)
        config_options['url'] = uri

    # todo: defer this to gui
    config = SimpleConfig(config_options)
    cmdname = config.get('cmd')

    # Set the app state proxy
    if cmdname == 'gui':
        try:
            from electrumsv.gui.qt.app_state import QtAppStateProxy
        except ImportError as e:
            platform.missing_import(e)
        QtAppStateProxy(config, 'qt')
    elif cmdname == 'daemon' and 'daemon_app_module' in config_options:
        load_app_module(config_options['daemon_app_module'], config)
    else:
        AppStateProxy(config, 'cmdline')
        app_state.set_app(DefaultApp())

    # run non-RPC commands separately
    if cmdname in ['create', 'restore']:
        run_non_RPC(config)
        sys.exit(0)

    if cmdname == 'gui':
        fd, server = daemon.get_fd_or_server(config)
        if fd is not None:
            run_app_with_daemon(fd, True, config_options)
        else:
            result = server.gui(config_options)

    elif cmdname == 'daemon':
        subcommand = config.get('subcommand')
        if subcommand in ['load_wallet']:
            init_daemon(config_options)

        if subcommand in [None, 'start']:
            fd, server = daemon.get_fd_or_server(config)
            if fd is not None:
                if not app_state.has_app():
                    print("No application present to run.")
                    sys.exit(0)

                if subcommand == 'start':
                    if not hasattr(os, "fork"):
                        print(
                            f"Starting the daemon is not supported on {sys.platform}."
                        )
                        sys.exit(0)
                    pid = os.fork()
                    if pid:
                        print("Starting daemon (PID %d)" % pid,
                              file=sys.stderr)
                        sys.exit(0)

                run_app_with_daemon(fd, False, config_options)
            else:
                result = server.daemon(config_options)
        else:
            server = daemon.get_server(config)
            if server is not None:
                result = server.daemon(config_options)
            else:
                print("Daemon not running")
                sys.exit(1)
    else:
        # command line
        server = daemon.get_server(config)
        init_cmdline(config_options, server)
        if server is not None:
            result = server.run_cmdline(config_options)
        else:
            cmd = known_commands[cmdname]
            if cmd.requires_network:
                print("Daemon not running; try 'electrum-sv daemon start'")
                sys.exit(1)
            else:
                result = run_offline_command(config, config_options)
                # print result
    if isinstance(result, str):
        print(result)
    elif type(result) is dict and result.get('error'):
        print(result.get('error'), file=sys.stderr)
    elif result is not None:
        print(json_encode(result))
    sys.exit(0)