mirror of
https://github.com/basicswap/basicswap.git
synced 2025-01-09 12:19:29 +00:00
commit
9e042200f3
3 changed files with 88 additions and 12 deletions
|
@ -9,7 +9,7 @@ import json
|
||||||
import traceback
|
import traceback
|
||||||
import threading
|
import threading
|
||||||
import http.client
|
import http.client
|
||||||
import urllib.parse
|
from urllib import parse
|
||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
from jinja2 import Environment, PackageLoader
|
from jinja2 import Environment, PackageLoader
|
||||||
|
|
||||||
|
@ -90,10 +90,13 @@ def listExplorerActions(swap_client):
|
||||||
|
|
||||||
class HttpHandler(BaseHTTPRequestHandler):
|
class HttpHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
|
def generate_form_id(self):
|
||||||
|
return os.urandom(8).hex()
|
||||||
|
|
||||||
def checkForm(self, post_string, name, messages):
|
def checkForm(self, post_string, name, messages):
|
||||||
if post_string == '':
|
if post_string == '':
|
||||||
return None
|
return None
|
||||||
form_data = urllib.parse.parse_qs(post_string)
|
form_data = parse.parse_qs(post_string)
|
||||||
form_id = form_data[b'formid'][0].decode('utf-8')
|
form_id = form_data[b'formid'][0].decode('utf-8')
|
||||||
if self.server.last_form_id.get(name, None) == form_id:
|
if self.server.last_form_id.get(name, None) == form_id:
|
||||||
messages.append('Prevented double submit for form {}.'.format(form_id))
|
messages.append('Prevented double submit for form {}.'.format(form_id))
|
||||||
|
@ -118,10 +121,11 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
if swap_client.debug:
|
if swap_client.debug:
|
||||||
swap_client.log.error(traceback.format_exc())
|
swap_client.log.error(traceback.format_exc())
|
||||||
|
|
||||||
|
self.putHeaders(200, 'text/html')
|
||||||
return bytes(template.render(
|
return bytes(template.render(
|
||||||
title=self.server.title,
|
title=self.server.title,
|
||||||
h2=self.server.title,
|
h2=self.server.title,
|
||||||
form_id=os.urandom(8).hex(),
|
form_id=self.generate_form_id(),
|
||||||
**args_dict,
|
**args_dict,
|
||||||
), 'UTF-8')
|
), 'UTF-8')
|
||||||
|
|
||||||
|
@ -535,7 +539,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
||||||
def handle_http(self, status_code, path, post_string='', is_json=False):
|
def handle_http(self, status_code, path, post_string='', is_json=False):
|
||||||
parsed = urllib.parse.urlparse(self.path)
|
parsed = parse.urlparse(self.path)
|
||||||
url_split = parsed.path.split('/')
|
url_split = parsed.path.split('/')
|
||||||
if post_string == '' and len(parsed.query) > 0:
|
if post_string == '' and len(parsed.query) > 0:
|
||||||
post_string = parsed.query
|
post_string = parsed.query
|
||||||
|
@ -595,7 +599,6 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
return self.page_error(str(ex))
|
return self.page_error(str(ex))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.putHeaders(status_code, 'text/html')
|
|
||||||
if len(url_split) > 1:
|
if len(url_split) > 1:
|
||||||
page = url_split[1]
|
page = url_split[1]
|
||||||
if page == 'active':
|
if page == 'active':
|
||||||
|
|
|
@ -379,13 +379,22 @@ None
|
||||||
<span>New Bid</span> </button>
|
<span>New Bid</span> </button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if data.sent == 'True' and data.was_revoked != true %}
|
|
||||||
|
{% if data.sent == 'True' %}
|
||||||
|
|
||||||
|
<div class="w-full md:w-auto p-1.5 ml-2">
|
||||||
|
<button name="repeat_offer" value="Repeat Offer" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none">
|
||||||
|
<span>Repeat Offer</span> </button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if data.was_revoked != true %}
|
||||||
|
|
||||||
<div class="w-full md:w-auto p-1.5 ml-2">
|
<div class="w-full md:w-auto p-1.5 ml-2">
|
||||||
<button name="revoke_offer" value="Revoke Offer" type="submit" onclick="return confirmPopup();" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none">
|
<button name="revoke_offer" value="Revoke Offer" type="submit" onclick="return confirmPopup();" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-coolGray-500 hover:text-coolGray-600 border border-coolGray-200 hover:border-coolGray-300 bg-white rounded-md shadow-button focus:ring-0 focus:outline-none">
|
||||||
<span>Revoke order</span> </button>
|
<span>Revoke Offer</span> </button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- todo
|
<!-- todo
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
from urllib import parse
|
||||||
from .util import (
|
from .util import (
|
||||||
PAGE_LIMIT,
|
PAGE_LIMIT,
|
||||||
getCoinType,
|
getCoinType,
|
||||||
|
@ -44,6 +45,15 @@ def value_or_none(v):
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
|
def decode_offer_id(v):
|
||||||
|
try:
|
||||||
|
offer_id = bytes.fromhex(v)
|
||||||
|
ensure(len(offer_id) == 28, 'Bad offer ID')
|
||||||
|
return offer_id
|
||||||
|
except Exception:
|
||||||
|
raise ValueError('Bad offer ID')
|
||||||
|
|
||||||
|
|
||||||
def parseOfferFormData(swap_client, form_data, page_data, options={}):
|
def parseOfferFormData(swap_client, form_data, page_data, options={}):
|
||||||
errors = []
|
errors = []
|
||||||
parsed_data = {}
|
parsed_data = {}
|
||||||
|
@ -264,6 +274,51 @@ def postNewOffer(swap_client, form_data):
|
||||||
return postNewOfferFromParsed(swap_client, parsed_data)
|
return postNewOfferFromParsed(swap_client, parsed_data)
|
||||||
|
|
||||||
|
|
||||||
|
def offer_to_post_string(self, swap_client, offer_id):
|
||||||
|
|
||||||
|
offer, xmr_offer = swap_client.getXmrOffer(offer_id)
|
||||||
|
ensure(offer, 'Unknown offer ID')
|
||||||
|
|
||||||
|
ci_from = swap_client.ci(offer.coin_from)
|
||||||
|
ci_to = swap_client.ci(offer.coin_to)
|
||||||
|
offer_data = {
|
||||||
|
'formid': self.generate_form_id(),
|
||||||
|
'addr_to': offer.addr_to,
|
||||||
|
'addr_from': offer.addr_from,
|
||||||
|
'coin_from': offer.coin_from,
|
||||||
|
'coin_to': offer.coin_to,
|
||||||
|
# TODO store fee conf, or pass directly
|
||||||
|
# 'fee_from_conf'
|
||||||
|
# 'fee_to_conf'
|
||||||
|
'amt_from': ci_from.format_amount(offer.amount_from),
|
||||||
|
'amt_bid_min': ci_from.format_amount(offer.min_bid_amount),
|
||||||
|
'rate': ci_to.format_amount(offer.rate),
|
||||||
|
'amt_to': ci_to.format_amount((offer.amount_from * offer.rate) // ci_from.COIN()),
|
||||||
|
'validhrs': offer.time_valid // (60 * 60),
|
||||||
|
}
|
||||||
|
|
||||||
|
swap_client.log.error('[rm] offer.amount_negotiable {}'.format(offer.amount_negotiable))
|
||||||
|
swap_client.log.error('[rm] offer.rate_negotiable {}'.format(offer.rate_negotiable))
|
||||||
|
if offer.amount_negotiable:
|
||||||
|
offer_data['amt_var'] = True
|
||||||
|
if offer.rate_negotiable:
|
||||||
|
offer_data['rate_var'] = True
|
||||||
|
|
||||||
|
if offer.lock_type == TxLockTypes.SEQUENCE_LOCK_TIME or offer.lock_type == TxLockTypes.ABS_LOCK_TIME:
|
||||||
|
if offer.lock_value > 60 * 60:
|
||||||
|
offer_data['lockhrs'] = offer.lock_value // (60 * 60)
|
||||||
|
else:
|
||||||
|
offer_data['lockhrs'] = offer.lock_value // 60
|
||||||
|
try:
|
||||||
|
strategy = swap_client.getLinkedStrategy(Concepts.OFFER, offer.offer_id)
|
||||||
|
swap_client.log.error('[rm] strategy {}'.format(strategy))
|
||||||
|
offer_data['automation_strat_id'] = strategy[0]
|
||||||
|
except Exception:
|
||||||
|
pass # None found
|
||||||
|
|
||||||
|
return parse.urlencode(offer_data).encode()
|
||||||
|
|
||||||
|
|
||||||
def page_newoffer(self, url_split, post_string):
|
def page_newoffer(self, url_split, post_string):
|
||||||
server = self.server
|
server = self.server
|
||||||
swap_client = server.swap_client
|
swap_client = server.swap_client
|
||||||
|
@ -283,6 +338,13 @@ def page_newoffer(self, url_split, post_string):
|
||||||
'automation_strat_id': -1,
|
'automation_strat_id': -1,
|
||||||
'amt_bid_min': format_amount(1000, 8),
|
'amt_bid_min': format_amount(1000, 8),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
post_data = parse.parse_qs(post_string)
|
||||||
|
if 'offer_from' in post_data:
|
||||||
|
offer_from_id_hex = post_data['offer_from'][0]
|
||||||
|
offer_from_id = decode_offer_id(offer_from_id_hex)
|
||||||
|
post_string = offer_to_post_string(self, swap_client, offer_from_id)
|
||||||
|
|
||||||
form_data = self.checkForm(post_string, 'newoffer', err_messages)
|
form_data = self.checkForm(post_string, 'newoffer', err_messages)
|
||||||
|
|
||||||
if form_data:
|
if form_data:
|
||||||
|
@ -337,11 +399,7 @@ def page_newoffer(self, url_split, post_string):
|
||||||
|
|
||||||
def page_offer(self, url_split, post_string):
|
def page_offer(self, url_split, post_string):
|
||||||
ensure(len(url_split) > 2, 'Offer ID not specified')
|
ensure(len(url_split) > 2, 'Offer ID not specified')
|
||||||
try:
|
offer_id = decode_offer_id(url_split[2])
|
||||||
offer_id = bytes.fromhex(url_split[2])
|
|
||||||
ensure(len(offer_id) == 28, 'Bad offer ID')
|
|
||||||
except Exception:
|
|
||||||
raise ValueError('Bad offer ID')
|
|
||||||
server = self.server
|
server = self.server
|
||||||
swap_client = server.swap_client
|
swap_client = server.swap_client
|
||||||
summary = swap_client.getSummary()
|
summary = swap_client.getSummary()
|
||||||
|
@ -373,6 +431,12 @@ def page_offer(self, url_split, post_string):
|
||||||
messages.append('Offer revoked')
|
messages.append('Offer revoked')
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
messages.append('Revoke offer failed: ' + str(ex))
|
messages.append('Revoke offer failed: ' + str(ex))
|
||||||
|
elif b'repeat_offer' in form_data:
|
||||||
|
# Can't set the post data here as browsers will always resend the original post data when responding to redirects
|
||||||
|
self.send_response(302)
|
||||||
|
self.send_header('Location', '/newoffer?offer_from=' + offer_id.hex())
|
||||||
|
self.end_headers()
|
||||||
|
return bytes()
|
||||||
elif b'newbid' in form_data:
|
elif b'newbid' in form_data:
|
||||||
show_bid_form = True
|
show_bid_form = True
|
||||||
elif b'sendbid' in form_data:
|
elif b'sendbid' in form_data:
|
||||||
|
|
Loading…
Reference in a new issue