# -*- coding: utf-8 -*- # Copyright (c) 2019-2021 tecnovert # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import os import json import struct import traceback import threading import http.client import urllib.parse from http.server import BaseHTTPRequestHandler, HTTPServer from jinja2 import Environment, PackageLoader from . import __version__ from .util import ( dumpj, format_timestamp, ) from .chainparams import ( chainparams, Coins, ) from .basicswap_util import ( SwapTypes, DebugTypes, strOfferState, strBidState, strTxState, strAddressType, getLockName, SEQUENCE_LOCK_TIME, ABS_LOCK_TIME, ) from .js_server import ( js_error, js_wallets, js_offers, js_sentoffers, js_bids, js_sentbids, js_network, js_revokeoffer, js_smsgaddresses, js_rates, js_rate, js_index, ) from .ui import ( PAGE_LIMIT, inputAmount, describeBid, getCoinType, setCoinFilter, get_data_entry, have_data_entry, get_data_entry_or, ) env = Environment(loader=PackageLoader('basicswap', 'templates')) env.filters['formatts'] = format_timestamp invalid_coins_from = (Coins.XMR, Coins.PART_ANON) def value_or_none(v): if v == -1 or v == '-1': return None return v def getCoinName(c): if c == Coins.PART_ANON: return chainparams[Coins.PART]['name'].capitalize() + 'Anon' if c == Coins.PART_BLIND: return chainparams[Coins.PART]['name'].capitalize() + 'Blind' return chainparams[c]['name'].capitalize() def listAvailableCoins(swap_client, with_variants=True, split_from=False): coins_from = [] coins = [] for k, v in swap_client.coin_clients.items(): if k not in chainparams: continue if v['connection_type'] == 'rpc': coins.append((int(k), getCoinName(k))) if split_from and k not in invalid_coins_from: coins_from.append(coins[-1]) if with_variants and k == Coins.PART: for v in (Coins.PART_ANON, Coins.PART_BLIND): coins.append((int(v), getCoinName(v))) if split_from and v not in invalid_coins_from: coins_from.append(coins[-1]) if split_from: return coins_from, coins return coins def validateTextInput(text, name, messages, max_length=None): if max_length is not None and len(text) > max_length: messages.append(f'Error: {name} is too long') return False if len(text) > 0 and all(c.isalnum() or c.isspace() for c in text) is False: messages.append(f'Error: {name} must consist of only letters and digits') return False return True def extractDomain(url): return url.split('://', 1)[1].split('/', 1)[0] def listAvailableExplorers(swap_client): explorers = [] for c in Coins: if c not in chainparams: continue for i, e in enumerate(swap_client.coin_clients[c]['explorers']): explorers.append(('{}_{}'.format(int(c), i), swap_client.coin_clients[c]['name'].capitalize() + ' - ' + extractDomain(e.base_url))) return explorers def listExplorerActions(swap_client): actions = [('height', 'Chain Height'), ('block', 'Get Block'), ('tx', 'Get Transaction'), ('balance', 'Address Balance'), ('unspent', 'List Unspent')] return actions def html_content_start(title, h2=None, refresh=None): content = '\n
' \ + '' \ + ('' if not refresh else ''.format(refresh)) \ + 'Info: ' + info_str + '
' \ + '' return bytes(content, 'UTF-8') def page_error(self, error_str): content = html_content_start('BasicSwap Error') \ + 'Error: ' + error_str + '
' \ + '