Esempio n. 1
0
    def setUpClass(cls):
        super(Test, cls).setUpClass()

        eckey = ECKey()
        eckey.generate()
        cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
        cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()

        if os.path.isdir(cfg.TEST_DATADIRS):
            logging.info('Removing ' + cfg.TEST_DATADIRS)
            shutil.rmtree(cfg.TEST_DATADIRS)

        for i in range(NUM_NODES):
            prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey)

        prepareOtherDir(cfg.TEST_DATADIRS, NMC_NODE)
        prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, 'bitcoin.conf')

        cls.daemons = []
        cls.swap_clients = []
        cls.http_threads = []

        cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), cfg.BITCOIN_BINDIR, cfg.BITCOIND))
        logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].pid)
        cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), cfg.NAMECOIN_BINDIR, cfg.NAMECOIND))
        logging.info('Started %s %d', cfg.NAMECOIND, cls.daemons[-1].pid)

        for i in range(NUM_NODES):
            cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(i)), cfg.PARTICL_BINDIR, cfg.PARTICLD))
            logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].pid)

        for i in range(NUM_NODES):
            rpc = make_part_cli_rpc_func(i)
            waitForRPC(rpc)
            if i == 0:
                rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
            elif i == 1:
                rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
                rpc('getnewextaddress', ['lblExtTest'])
                rpc('rescanblockchain')
            else:
                rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']])

            basicswap_dir = os.path.join(os.path.join(cfg.TEST_DATADIRS, str(i)), 'basicswap')
            settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
            with open(settings_path) as fs:
                settings = json.load(fs)
            fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
            cls.swap_clients.append(BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)))
            cls.swap_clients[-1].setDaemonPID(Coins.BTC, cls.daemons[0].pid)
            cls.swap_clients[-1].setDaemonPID(Coins.NMC, cls.daemons[1].pid)
            cls.swap_clients[-1].setDaemonPID(Coins.PART, cls.daemons[2 + i].pid)
            cls.swap_clients[-1].start()

            t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, cls.swap_clients[i])
            cls.http_threads.append(t)
            t.start()

        waitForRPC(nmcRpc)
        num_blocks = 500
        logging.info('Mining %d namecoin blocks', num_blocks)
        cls.nmc_addr = nmcRpc('getnewaddress mining_addr legacy')
        nmcRpc('generatetoaddress {} {}'.format(num_blocks, cls.nmc_addr))

        ro = nmcRpc('getblockchaininfo')
        try:
            assert(ro['bip9_softforks']['csv']['status'] == 'active')
        except Exception:
            logging.info('nmc: csv is not active')
        try:
            assert(ro['bip9_softforks']['segwit']['status'] == 'active')
        except Exception:
            logging.info('nmc: segwit is not active')

        waitForRPC(btcRpc)
        cls.btc_addr = btcRpc('getnewaddress mining_addr bech32')
        logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr)
        btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr))

        ro = btcRpc('getblockchaininfo')
        checkForks(ro)

        ro = nmcRpc('getwalletinfo')
        print('nmcRpc', ro)

        signal.signal(signal.SIGINT, signal_handler)
        cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
        cls.update_thread.start()

        cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,))
        cls.coins_update_thread.start()

        # Wait for height, or sequencelock is thrown off by genesis blocktime
        num_blocks = 3
        logging.info('Waiting for Particl chain height %d', num_blocks)
        for i in range(60):
            particl_blocks = cls.swap_clients[0].callrpc('getblockchaininfo')['blocks']
            print('particl_blocks', particl_blocks)
            if particl_blocks >= num_blocks:
                break
            delay_event.wait(1)
        assert(particl_blocks >= num_blocks)
Esempio n. 2
0
    def setUpClass(cls):
        super(Test, cls).setUpClass()

        cls.update_thread = None
        cls.coins_update_thread = None
        cls.http_threads = []
        cls.swap_clients = []
        cls.part_daemons = []
        cls.btc_daemons = []

        cls.part_stakelimit = 0
        cls.btc_addr = None

        logger.propagate = False
        logger.handlers = []
        logger.setLevel(
            logging.INFO)  # DEBUG shows many messages from requests.post
        formatter = logging.Formatter(
            '%(asctime)s %(levelname)s : %(message)s')
        stream_stdout = logging.StreamHandler()
        stream_stdout.setFormatter(formatter)
        logger.addHandler(stream_stdout)

        if os.path.isdir(TEST_DIR):
            logging.info('Removing ' + TEST_DIR)
            shutil.rmtree(TEST_DIR)
        if not os.path.exists(TEST_DIR):
            os.makedirs(TEST_DIR)

        cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, 'test.log'))
        cls.stream_fp.setFormatter(formatter)
        logger.addHandler(cls.stream_fp)

        try:
            logging.info('Preparing coin nodes.')
            for i in range(NUM_NODES):
                prepareDataDir(TEST_DIR, i, 'particl.conf', 'part_')

                cls.part_daemons.append(
                    startDaemon(os.path.join(TEST_DIR, 'part_' + str(i)),
                                cfg.PARTICL_BINDIR, cfg.PARTICLD))
                logging.info('Started %s %d', cfg.PARTICLD,
                             cls.part_daemons[-1].pid)

            for i in range(NUM_NODES):
                # Load mnemonics after all nodes have started to avoid staking getting stuck in TryToSync
                rpc = make_rpc_func(i)
                waitForRPC(rpc)
                if i == 0:
                    rpc('extkeyimportmaster', [
                        'abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'
                    ])
                elif i == 1:
                    rpc('extkeyimportmaster', [
                        'pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic',
                        '', 'true'
                    ])
                    rpc('getnewextaddress', ['lblExtTest'])
                    rpc('rescanblockchain')
                else:
                    rpc('extkeyimportmaster',
                        [rpc('mnemonic', ['new'])['master']])
                # Lower output split threshold for more stakeable outputs
                rpc('walletsettings', [
                    'stakingoptions', {
                        'stakecombinethreshold': 100,
                        'stakesplitthreshold': 200
                    }
                ])

            for i in range(NUM_BTC_NODES):
                prepareDataDir(TEST_DIR,
                               i,
                               'bitcoin.conf',
                               'btc_',
                               base_p2p_port=BTC_BASE_PORT,
                               base_rpc_port=BTC_BASE_RPC_PORT)

                cls.btc_daemons.append(
                    startDaemon(os.path.join(TEST_DIR, 'btc_' + str(i)),
                                cfg.BITCOIN_BINDIR, cfg.BITCOIND))
                logging.info('Started %s %d', cfg.BITCOIND,
                             cls.part_daemons[-1].pid)

                waitForRPC(make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT))

            logging.info('Preparing swap clients.')
            eckey = ECKey()
            eckey.generate()
            cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST,
                                    eckey.get_bytes())
            cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()

            for i in range(NUM_NODES):
                prepare_swapclient_dir(TEST_DIR, i, cls.network_key,
                                       cls.network_pubkey)
                basicswap_dir = os.path.join(
                    os.path.join(TEST_DIR, 'basicswap_' + str(i)))
                settings_path = os.path.join(basicswap_dir,
                                             cfg.CONFIG_FILENAME)
                with open(settings_path) as fs:
                    settings = json.load(fs)
                fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
                sc = BasicSwap(fp,
                               basicswap_dir,
                               settings,
                               'regtest',
                               log_name='BasicSwap{}'.format(i))
                sc.setDaemonPID(Coins.BTC, cls.btc_daemons[i].pid)
                sc.setDaemonPID(Coins.PART, cls.part_daemons[i].pid)
                sc.start()
                cls.swap_clients.append(sc)

                t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST,
                               TEST_HTTP_PORT + i, False, cls.swap_clients[i])
                cls.http_threads.append(t)
                t.start()

            cls.btc_addr = callnoderpc(0,
                                       'getnewaddress',
                                       ['mining_addr', 'bech32'],
                                       base_rpc_port=BTC_BASE_RPC_PORT)

            num_blocks = 500
            logging.info('Mining %d Bitcoin blocks to %s', num_blocks,
                         cls.btc_addr)
            callnoderpc(0,
                        'generatetoaddress', [num_blocks, cls.btc_addr],
                        base_rpc_port=BTC_BASE_RPC_PORT)

            checkForks(
                callnoderpc(0,
                            'getblockchaininfo',
                            base_rpc_port=BTC_BASE_RPC_PORT))

            logging.info('Starting update thread.')
            signal.signal(signal.SIGINT, signal_handler)
            cls.update_thread = threading.Thread(target=run_loop, args=(cls, ))
            cls.update_thread.start()

            cls.coins_update_thread = threading.Thread(target=run_coins_loop,
                                                       args=(cls, ))
            cls.coins_update_thread.start()
        except Exception:
            traceback.print_exc()
            Test.tearDownClass()
            raise ValueError('setUpClass() failed.')
Esempio n. 3
0
def runClient(fp, data_dir, chain, test_mode):
    global swap_client
    settings_path = os.path.join(data_dir, 'basicswap.json')
    pids_path = os.path.join(data_dir, '.pids')

    if not os.path.exists(settings_path):
        raise ValueError('Settings file not found: ' + str(settings_path))

    with open(settings_path) as fs:
        settings = json.load(fs)

    swap_client = BasicSwap(fp, data_dir, settings, chain)

    daemons = []
    pids = []
    threads = []

    if os.path.exists(pids_path):
        with open(pids_path) as fd:
            for ln in fd:
                # TODO: try close
                logger.warning('Found pid for daemon {} '.format(ln.strip()))

    # Ensure daemons are stopped
    swap_client.stopDaemons()

    try:
        # Try start daemons
        for c, v in settings['chainclients'].items():
            if v['manage_daemon'] is True:
                logger.info('Starting {} daemon'.format(c.capitalize()))

                filename = c + 'd' + ('.exe' if os.name == 'nt' else '')
                daemons.append(startDaemon(v['datadir'], v['bindir'],
                                           filename))
                pid = daemons[-1].pid
                pids.append((c, pid))
                swap_client.setDaemonPID(c, pid)
                logger.info('Started {} {}'.format(filename, pid))
        if len(pids) > 0:
            with open(pids_path, 'w') as fd:
                for p in pids:
                    fd.write('{}:{}\n'.format(*p))

        if not test_mode:
            # Signal only works in main thread
            signal.signal(signal.SIGINT, signal_handler)
            signal.signal(signal.SIGTERM, signal_handler)
        swap_client.start()

        if 'htmlhost' in settings:
            swap_client.log.info('Starting server at %s:%d.' %
                                 (settings['htmlhost'], settings['htmlport']))
            allow_cors = settings[
                'allowcors'] if 'allowcors' in settings else ALLOW_CORS
            tS1 = HttpThread(fp, settings['htmlhost'], settings['htmlport'],
                             allow_cors, swap_client)
            threads.append(tS1)
            tS1.start()

        logger.info('Exit with Ctrl + c.')
        while swap_client.is_running:
            time.sleep(0.5)
            swap_client.update()
    except Exception as ex:
        traceback.print_exc()

    swap_client.log.info('Stopping threads.')
    for t in threads:
        t.stop()
        t.join()

    closed_pids = []
    for d in daemons:
        int_pid = d.pid
        logger.info('Terminating {}'.format(int_pid))
        try:
            d.terminate()
            d.wait(timeout=120)
            if d.stdout:
                d.stdout.close()
            if d.stderr:
                d.stderr.close()
            if d.stdin:
                d.stdin.close()
            closed_pids.append(int_pid)
        except Exception as ex:
            logger.error('Error: {}'.format(ex))

    if os.path.exists(pids_path):
        with open(pids_path) as fd:
            lines = fd.read().split('\n')
        still_running = ''
        for ln in lines:
            try:
                if not int(ln.split(':')[1]) in closed_pids:
                    still_running += ln + '\n'
            except Exception:
                pass
        with open(pids_path, 'w') as fd:
            fd.write(still_running)
Esempio n. 4
0
    def setUpClass(cls):
        super(Test, cls).setUpClass()

        eckey = ECKey()
        eckey.generate()
        cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
        cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()

        if os.path.isdir(cfg.DATADIRS):
            logging.info('Removing ' + cfg.DATADIRS)
            shutil.rmtree(cfg.DATADIRS)

        for i in range(NUM_NODES):
            prepareDir(cfg.DATADIRS, i, cls.network_key, cls.network_pubkey)

        prepareOtherDir(cfg.DATADIRS, NMC_NODE)
        prepareOtherDir(cfg.DATADIRS, BTC_NODE, 'bitcoin.conf')

        cls.daemons = []
        cls.swap_clients = []

        cls.daemons.append(
            startDaemon(BTC_NODE, cfg.BITCOIN_BINDIR, cfg.BITCOIND))
        logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].pid)
        cls.daemons.append(
            startDaemon(NMC_NODE, cfg.NAMECOIN_BINDIR, cfg.NAMECOIND))
        logging.info('Started %s %d', cfg.NAMECOIND, cls.daemons[-1].pid)

        for i in range(NUM_NODES):
            cls.daemons.append(startDaemon(i))
            logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].pid)
        time.sleep(1)
        for i in range(NUM_NODES):
            basicswap_dir = os.path.join(os.path.join(cfg.DATADIRS, str(i)),
                                         'basicswap')
            settings_path = os.path.join(basicswap_dir, 'basicswap.json')
            with open(settings_path) as fs:
                settings = json.load(fs)
            fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
            cls.swap_clients.append(
                BasicSwap(fp,
                          basicswap_dir,
                          settings,
                          'regtest',
                          log_name='BasicSwap{}'.format(i)))
            cls.swap_clients[-1].setDaemonPID(Coins.BTC, cls.daemons[0].pid)
            cls.swap_clients[-1].setDaemonPID(Coins.NMC, cls.daemons[1].pid)
            cls.swap_clients[-1].setDaemonPID(Coins.PART,
                                              cls.daemons[2 + i].pid)
            cls.swap_clients[-1].start()
        cls.swap_clients[0].callrpc('extkeyimportmaster', [
            'abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'
        ])
        cls.swap_clients[1].callrpc('extkeyimportmaster', [
            'pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic',
            '', 'true'
        ])
        cls.swap_clients[1].callrpc('getnewextaddress', ['lblExtTest'])
        cls.swap_clients[1].callrpc('rescanblockchain')

        waitForRPC(nmcRpc)
        num_blocks = 500
        logging.info('Mining %d namecoin blocks', num_blocks)
        cls.nmc_addr = nmcRpc('getnewaddress mining_addr legacy')
        nmcRpc('generatetoaddress {} {}'.format(num_blocks, cls.nmc_addr))

        ro = nmcRpc('getblockchaininfo')
        try:
            assert (ro['bip9_softforks']['csv']['status'] == 'active')
        except Exception:
            logging.info('nmc: csv is not active')
        try:
            assert (ro['bip9_softforks']['segwit']['status'] == 'active')
        except Exception:
            logging.info('nmc: segwit is not active')

        waitForRPC(btcRpc)
        cls.btc_addr = btcRpc('getnewaddress mining_addr bech32')
        logging.info('Mining %d bitcoin blocks to %s', num_blocks,
                     cls.btc_addr)
        btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr))

        ro = btcRpc('getblockchaininfo')
        assert (ro['bip9_softforks']['csv']['status'] == 'active')
        assert (ro['bip9_softforks']['segwit']['status'] == 'active')

        ro = nmcRpc('getwalletinfo')
        print('nmcRpc', ro)

        cls.http_threads = []
        host = '0.0.0.0'  # All interfaces (docker)
        for i in range(3):
            t = HttpThread(cls.swap_clients[i].fp, host, TEST_HTML_PORT + i,
                           False, cls.swap_clients[i])
            cls.http_threads.append(t)
            t.start()

        signal.signal(signal.SIGINT, signal_handler)
        cls.update_thread = threading.Thread(target=run_loop, args=(cls, ))
        cls.update_thread.start()
Esempio n. 5
0
    def setUpClass(cls):
        super(Test, cls).setUpClass()

        eckey = ECKey()
        eckey.generate()
        cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
        cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()

        if os.path.isdir(cfg.TEST_DATADIRS):
            logging.info('Removing ' + cfg.TEST_DATADIRS)
            shutil.rmtree(cfg.TEST_DATADIRS)

        for i in range(NUM_NODES):
            data_dir = prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey)
            callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'particl-wallet')  # Necessary for 0.21

        prepareOtherDir(cfg.TEST_DATADIRS, LTC_NODE)
        data_dir = prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, 'bitcoin.conf')
        callrpc_cli(cfg.BITCOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet')  # Necessary for 0.21

        cls.daemons = []
        cls.swap_clients = []
        cls.http_threads = []

        cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), cfg.BITCOIN_BINDIR, cfg.BITCOIND))
        logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].pid)
        cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(LTC_NODE)), cfg.LITECOIN_BINDIR, cfg.LITECOIND))
        logging.info('Started %s %d', cfg.LITECOIND, cls.daemons[-1].pid)

        for i in range(NUM_NODES):
            cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(i)), cfg.PARTICL_BINDIR, cfg.PARTICLD))
            logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].pid)

        for i in range(NUM_NODES):
            # Load mnemonics after all nodes have started to avoid staking getting stuck in TryToSync
            rpc = make_part_cli_rpc_func(i)
            waitForRPC(rpc)
            if i == 0:
                rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
            elif i == 1:
                rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
                rpc('getnewextaddress', ['lblExtTest'])
                rpc('rescanblockchain')
            else:
                rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']])
            # Lower output split threshold for more stakeable outputs
            rpc('walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])

            basicswap_dir = os.path.join(os.path.join(cfg.TEST_DATADIRS, str(i)), 'basicswap')
            settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
            with open(settings_path) as fs:
                settings = json.load(fs)
            fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
            sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i))
            sc.setDaemonPID(Coins.BTC, cls.daemons[0].pid)
            sc.setDaemonPID(Coins.LTC, cls.daemons[1].pid)
            sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].pid)
            sc.start()
            cls.swap_clients.append(sc)

            t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, cls.swap_clients[i])
            cls.http_threads.append(t)
            t.start()

        waitForRPC(ltcRpc)
        num_blocks = 500
        logging.info('Mining %d litecoin blocks', num_blocks)
        cls.ltc_addr = ltcRpc('getnewaddress mining_addr legacy')
        ltcRpc('generatetoaddress {} {}'.format(num_blocks, cls.ltc_addr))

        ro = ltcRpc('getblockchaininfo')
        checkForks(ro)

        waitForRPC(btcRpc)
        cls.btc_addr = btcRpc('getnewaddress mining_addr bech32')
        logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr)
        btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr))

        ro = btcRpc('getblockchaininfo')
        checkForks(ro)

        ro = ltcRpc('getwalletinfo')
        print('ltcRpc', ro)

        signal.signal(signal.SIGINT, signal_handler)
        cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
        cls.update_thread.start()

        cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,))
        cls.coins_update_thread.start()

        # Wait for height, or sequencelock is thrown off by genesis blocktime
        num_blocks = 3
        logging.info('Waiting for Particl chain height %d', num_blocks)
        for i in range(60):
            particl_blocks = cls.swap_clients[0].callrpc('getblockchaininfo')['blocks']
            print('particl_blocks', particl_blocks)
            if particl_blocks >= num_blocks:
                break
            test_delay_event.wait(1)
        assert(particl_blocks >= num_blocks)
Esempio n. 6
0
def runClient(fp, data_dir, chain):
    global swap_client
    settings_path = os.path.join(data_dir, cfg.CONFIG_FILENAME)
    pids_path = os.path.join(data_dir, '.pids')

    if not os.path.exists(settings_path):
        raise ValueError('Settings file not found: ' + str(settings_path))

    with open(settings_path) as fs:
        settings = json.load(fs)

    swap_client = BasicSwap(fp, data_dir, settings, chain)

    daemons = []
    pids = []
    threads = []

    if os.path.exists(pids_path):
        with open(pids_path) as fd:
            for ln in fd:
                # TODO: try close
                logger.warning('Found pid for daemon {} '.format(ln.strip()))

    # Ensure daemons are stopped
    swap_client.stopDaemons()

    try:
        # Try start daemons
        for c, v in settings['chainclients'].items():
            if c == 'monero':
                if v['manage_daemon'] is True:
                    logger.info('Starting {} daemon'.format(c.capitalize()))
                    daemons.append(
                        startXmrDaemon(v['datadir'], v['bindir'], 'monerod'))
                    pid = daemons[-1].pid
                    logger.info('Started {} {}'.format('monerod', pid))

                if v['manage_wallet_daemon'] is True:
                    logger.info('Starting {} wallet daemon'.format(
                        c.capitalize()))
                    daemons.append(
                        startXmrWalletDaemon(v['datadir'], v['bindir'],
                                             'monero-wallet-rpc'))
                    pid = daemons[-1].pid
                    logger.info('Started {} {}'.format('monero-wallet-rpc',
                                                       pid))

                continue
            if v['manage_daemon'] is True:
                logger.info('Starting {} daemon'.format(c.capitalize()))

                filename = c + 'd' + ('.exe' if os.name == 'nt' else '')
                daemons.append(startDaemon(v['datadir'], v['bindir'],
                                           filename))
                pid = daemons[-1].pid
                pids.append((c, pid))
                swap_client.setDaemonPID(c, pid)
                logger.info('Started {} {}'.format(filename, pid))
        if len(pids) > 0:
            with open(pids_path, 'w') as fd:
                for p in pids:
                    fd.write('{}:{}\n'.format(*p))

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)
        swap_client.start()

        if 'htmlhost' in settings:
            swap_client.log.info('Starting server at %s:%d.' %
                                 (settings['htmlhost'], settings['htmlport']))
            allow_cors = settings[
                'allowcors'] if 'allowcors' in settings else cfg.DEFAULT_ALLOW_CORS
            tS1 = HttpThread(fp, settings['htmlhost'], settings['htmlport'],
                             allow_cors, swap_client)
            threads.append(tS1)
            tS1.start()

        logger.info('Exit with Ctrl + c.')
        while swap_client.is_running:
            time.sleep(0.5)
            swap_client.update()
    except Exception as ex:
        traceback.print_exc()

    swap_client.finalise()
    swap_client.log.info('Stopping HTTP threads.')
    for t in threads:
        t.stop()
        t.join()

    closed_pids = []
    for d in daemons:
        logging.info('Interrupting {}'.format(d.pid))
        try:
            d.send_signal(signal.SIGINT)
        except Exception as e:
            logging.info('Interrupting %d, error %s', d.pid, str(e))
    for d in daemons:
        try:
            d.wait(timeout=120)
            for fp in (d.stdout, d.stderr, d.stdin):
                if fp:
                    fp.close()
            closed_pids.append(d.pid)
        except Exception as ex:
            logger.error('Error: {}'.format(ex))

    if os.path.exists(pids_path):
        with open(pids_path) as fd:
            lines = fd.read().split('\n')
        still_running = ''
        for ln in lines:
            try:
                if not int(ln.split(':')[1]) in closed_pids:
                    still_running += ln + '\n'
            except Exception:
                pass
        with open(pids_path, 'w') as fd:
            fd.write(still_running)