diff --git a/.gitignore b/.gitignore
index 7d847cc..f97c19d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ __pycache__/
.env
.vs/
.venv/
+data/
\ No newline at end of file
diff --git a/FireSales.bsdesign b/FireSales.bsdesign
index 9e29138..a4ac4a4 100644
Binary files a/FireSales.bsdesign and b/FireSales.bsdesign differ
diff --git a/data/listings.json b/data/listings.json
deleted file mode 100644
index db342aa..0000000
--- a/data/listings.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[
- {
- "domain": "woodburn43",
- "description": "This is a test listing update",
- "price": 100.2,
- "tx": "somelonghexstring",
- "updated": 1738214534
- }
-]
\ No newline at end of file
diff --git a/requests/accept.hurl b/requests/accept.hurl
new file mode 100644
index 0000000..e69de29
diff --git a/requests/getMessage.hurl b/requests/getMessage.hurl
new file mode 100644
index 0000000..2b52abb
--- /dev/null
+++ b/requests/getMessage.hurl
@@ -0,0 +1 @@
+GET http://127.0.0.1:5000/api/v1/listing-message?domain=woodburn43&description=This%20is%20a%20test%20listing%20update&price=100.2&contact=contact%40nathan.woodburn.au
\ No newline at end of file
diff --git a/requests/list.hurl b/requests/list.hurl
index 858ffd3..f16716b 100644
--- a/requests/list.hurl
+++ b/requests/list.hurl
@@ -3,5 +3,6 @@ POST http://127.0.0.1:5000/api/v1/list
"domain":"woodburn43",
"price":100.2,
"description":"This is a test listing update",
-"tx":"somelonghexstring"
+"contact":"contact@nathan.woodburn.au",
+"signature":"az51SGj9/7MjQ8Xl6LNM5Mu99FwEna8LTDkckWqH+9wZ6L5YQNV3vEyQIVI1BApS7oI8efgjE+edXHkXO4o7uw=="
}
\ No newline at end of file
diff --git a/sales.py b/sales.py
index d70ce35..26be029 100644
--- a/sales.py
+++ b/sales.py
@@ -19,7 +19,8 @@ class Listing:
self.domain = ''
self.price = 0
self.description = ''
- self.tx = ''
+ self.contact = ''
+ self.signature = ''
self.updated = -1
for key, value in kwargs.items():
@@ -28,16 +29,20 @@ class Listing:
self.updated = int(time.time())
def __str__(self):
- return f"Listing of {self.domain} for {self.price}, Description: {self.description}, Contact: {self.contact}, Signed: {self.signed}, Signature: {self.signature}, Updated: {self.updated}"
+ return f"Domain: {self.domain}\nPrice: {self.price}\nDescription: {self.description}\nContact: {self.contact}"
+
+ def getMessage(self):
+ return str(self).encode('utf-8').hex()
def toHTML(self):
return f"""
-
+
-
{self.domain}/
+
{self.domain}/ ✅
{self.price} HNS
{self.description}
-
TX: {self.tx}
+
Contact: {self.contact}
+
Delete Listing
"""
@@ -47,12 +52,13 @@ class Listing:
'domain': self.domain,
'description': self.description,
'price': self.price,
- 'tx': self.tx,
+ 'contact': self.contact,
+ 'signature': self.signature,
'updated': self.updated
}
-
- def to_dict(self):
- return self.toJSON()
+
+ def signed(self):
+ return validate_signature(self.domain,self.signature,self.getMessage())
def txValid(self):
# TODO Validate tx is valid
diff --git a/server.py b/server.py
index f600932..ea6de75 100644
--- a/server.py
+++ b/server.py
@@ -85,6 +85,42 @@ def view(domain: str):
return render_template("404.html"), 404
return render_template("view.html", listing=listing)
+@app.route("/list", methods=["POST"])
+def list_form():
+ # Get form data
+ data = request.form
+ domain = data['domain']
+ price = data['price']
+ description = data['description']
+ contact = data['contact']
+ signature = data['signature']
+
+ listing = sales.Listing(domain=domain,price=price,description=description,contact=contact,signature=signature)
+ if not listing.signed():
+ return render_template("list.html", domain=domain, price=price, description=description, contact=contact, signature=signature, error="Signature is not valid")
+
+ status = sales.add_listing(listing)
+ if status != True:
+ return render_template("list.html", domain=domain, price=price, description=description, contact=contact, signature=signature, error="Failed to add listing")
+ return render_template("list.html", success="Successfully added listing")
+
+@app.route("/delete/
")
+def delete_web(domain: str):
+ message = f"FS: {domain}"
+ return render_template("delete.html", domain=domain, message=message)
+
+@app.route("/delete/", methods=["POST"])
+def delete_form(domain:str):
+ data = request.form
+ signature = data['signature']
+
+
+ if not sales.validate_cancel_signature(domain,signature):
+ return render_template("delete.html", domain=domain, error="Invalid signature")
+
+ sales.remove_listing(domain)
+ return redirect("/")
+
@app.route("/view/", methods=["POST"])
def post_offer(domain: str):
data = request.form
@@ -101,24 +137,46 @@ def report(domain: str):
return render_template("404.html"), 404
return redirect("https://l.woodburn.au/contact")
+@app.route("/verify/")
+def verify(domain: str):
+ listing = sales.search_listings(domain)
+ if not listing:
+ return render_template("404.html"), 404
+ return render_template("verify.html", domain=domain, string=str(listing).replace('\n','
'), message=listing.getMessage(), signature=listing.signature)
#region API Routes
def validate_data(data,required):
for key in required:
if key not in data:
- return jsonify({'error': f'Missing {key}','success': False})
+ return jsonify({'error': f'Missing {key}','success': False}),400
return True
+@app.route("/api/v1/listing-message", methods=["GET"])
+def listingMessage():
+ # Create listing
+ valid = validate_data(request.args,['domain','description','price','contact'])
+ if valid != True:
+ return valid
+
+ listing = sales.Listing(**request.args)
+ return {
+ 'message': listing.getMessage(),
+ 'success': True
+ }
+
@app.route("/api/v1/list", methods=["POST"])
def list():
data = request.get_json()
# Validate data has domain,description,price,contact
- valid = validate_data(data,['domain','description','price','tx'])
+ valid = validate_data(data,['domain','description','price','contact'])
if valid != True:
return valid
listing = sales.Listing(**data)
+ if not listing.signed():
+ return jsonify({'error': 'Not signed','success': False,'message': f'Sign this message to post listing: {listing.getMessage()}'})
+
status = sales.add_listing(listing)
if status != True:
return jsonify({'error': 'Failed to add listing','success': False,'message': status})
diff --git a/templates/delete.html b/templates/delete.html
new file mode 100644
index 0000000..d497c0e
--- /dev/null
+++ b/templates/delete.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+ FireSales
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
FireSales
+
Self custodial domain sales
+
+
+
+
+ {{error}}
+ {{success}}
+
+
+
+
+
Delete listing for {{domain}}
+
Message to sign: {{message}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/templates/index.html b/templates/index.html
index da8387d..d36589b 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -20,10 +20,11 @@