NIP corrections

This commit is contained in:
koalasat 2024-07-15 12:33:09 +02:00
parent bdc10eb289
commit cbb063f06d
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
6 changed files with 68 additions and 28 deletions

View File

@ -8,7 +8,7 @@ from django.utils import timezone
from api.lightning.node import LNNode from api.lightning.node import LNNode
from api.models import Currency, LNPayment, MarketTick, OnchainPayment, Order from api.models import Currency, LNPayment, MarketTick, OnchainPayment, Order
from api.tasks import send_devfund_donation, send_notification, send_order_nostr_event from api.tasks import send_devfund_donation, send_notification, nostr_send_order_event
from api.utils import get_minning_fee, validate_onchain_address, location_country from api.utils import get_minning_fee, validate_onchain_address, location_country
from chat.models import Message from chat.models import Message
@ -704,9 +704,9 @@ class Logics:
if context["invoice_amount"] < MIN_SWAP_AMOUNT: if context["invoice_amount"] < MIN_SWAP_AMOUNT:
context["swap_allowed"] = False context["swap_allowed"] = False
context[ context["swap_failure_reason"] = (
"swap_failure_reason" f"Order amount is smaller than the minimum swap available of {MIN_SWAP_AMOUNT} Sats"
] = f"Order amount is smaller than the minimum swap available of {MIN_SWAP_AMOUNT} Sats" )
order.log( order.log(
f"Onchain payment option was not offered: amount is smaller than the minimum swap available of {MIN_SWAP_AMOUNT} Sats", f"Onchain payment option was not offered: amount is smaller than the minimum swap available of {MIN_SWAP_AMOUNT} Sats",
level="WARN", level="WARN",
@ -714,9 +714,9 @@ class Logics:
return True, context return True, context
elif context["invoice_amount"] > MAX_SWAP_AMOUNT: elif context["invoice_amount"] > MAX_SWAP_AMOUNT:
context["swap_allowed"] = False context["swap_allowed"] = False
context[ context["swap_failure_reason"] = (
"swap_failure_reason" f"Order amount is bigger than the maximum swap available of {MAX_SWAP_AMOUNT} Sats"
] = f"Order amount is bigger than the maximum swap available of {MAX_SWAP_AMOUNT} Sats" )
order.log( order.log(
f"Onchain payment option was not offered: amount is bigger than the maximum swap available of {MAX_SWAP_AMOUNT} Sats", f"Onchain payment option was not offered: amount is bigger than the maximum swap available of {MAX_SWAP_AMOUNT} Sats",
level="WARN", level="WARN",
@ -741,9 +741,9 @@ class Logics:
) )
if not valid: if not valid:
context["swap_allowed"] = False context["swap_allowed"] = False
context[ context["swap_failure_reason"] = (
"swap_failure_reason" "Not enough onchain liquidity available to offer a swap"
] = "Not enough onchain liquidity available to offer a swap" )
order.log( order.log(
"Onchain payment option was not offered: onchain liquidity available to offer a swap", "Onchain payment option was not offered: onchain liquidity available to offer a swap",
level="WARN", level="WARN",
@ -1019,6 +1019,8 @@ class Logics:
order.log("Order expired while waiting for maker bond") order.log("Order expired while waiting for maker bond")
order.log("Maker bond was cancelled") order.log("Maker bond was cancelled")
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# 2.a) When maker cancels after bond # 2.a) When maker cancels after bond
@ -1039,6 +1041,8 @@ class Logics:
order.log("Order cancelled by maker while public or paused") order.log("Order cancelled by maker while public or paused")
order.log("Maker bond was <b>unlocked</b>") order.log("Maker bond was <b>unlocked</b>")
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# 2.b) When maker cancels after bond and before taker bond is locked # 2.b) When maker cancels after bond and before taker bond is locked
@ -1058,6 +1062,8 @@ class Logics:
order.log("Maker bond was <b>unlocked</b>") order.log("Maker bond was <b>unlocked</b>")
order.log("Taker bond was <b>cancelled</b>") order.log("Taker bond was <b>cancelled</b>")
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# 3) When taker cancels before bond # 3) When taker cancels before bond
@ -1070,6 +1076,8 @@ class Logics:
order.log("Taker cancelled before locking the bond") order.log("Taker cancelled before locking the bond")
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# 4) When taker or maker cancel after bond (before escrow) # 4) When taker or maker cancel after bond (before escrow)
@ -1099,6 +1107,8 @@ class Logics:
order.log("Maker bond was <b>settled</b>") order.log("Maker bond was <b>settled</b>")
order.log("Taker bond was <b>unlocked</b>") order.log("Taker bond was <b>unlocked</b>")
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# 4.b) When taker cancel after bond (before escrow) # 4.b) When taker cancel after bond (before escrow)
@ -1121,6 +1131,8 @@ class Logics:
order.log("Taker bond was <b>settled</b>") order.log("Taker bond was <b>settled</b>")
order.log("Maker bond was <b>unlocked</b>") order.log("Maker bond was <b>unlocked</b>")
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# 5) When trade collateral has been posted (after escrow) # 5) When trade collateral has been posted (after escrow)
@ -1136,6 +1148,9 @@ class Logics:
order.log( order.log(
f"Taker Robot({user.robot.id},{user.username}) accepted the collaborative cancellation" f"Taker Robot({user.robot.id},{user.username}) accepted the collaborative cancellation"
) )
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# if the taker had asked, and now the maker does: cancel order, return everything # if the taker had asked, and now the maker does: cancel order, return everything
@ -1144,6 +1159,9 @@ class Logics:
order.log( order.log(
f"Maker Robot({user.robot.id},{user.username}) accepted the collaborative cancellation" f"Maker Robot({user.robot.id},{user.username}) accepted the collaborative cancellation"
) )
nostr_send_order_event.delay(order_id=order.id)
return True, None return True, None
# Otherwise just make true the asked for cancel flags # Otherwise just make true the asked for cancel flags
@ -1181,6 +1199,8 @@ class Logics:
order.update_status(Order.Status.CCA) order.update_status(Order.Status.CCA)
send_notification.delay(order_id=order.id, message="collaborative_cancelled") send_notification.delay(order_id=order.id, message="collaborative_cancelled")
nostr_send_order_event.delay(order_id=order.id)
order.log("Order was collaboratively cancelled") order.log("Order was collaboratively cancelled")
order.log("Maker bond was <b>unlocked</b>") order.log("Maker bond was <b>unlocked</b>")
order.log("Taker bond was <b>unlocked</b>") order.log("Taker bond was <b>unlocked</b>")
@ -1208,7 +1228,7 @@ class Logics:
order.save() # update all fields order.save() # update all fields
send_order_nostr_event.delay(order_id=order.id, message="new") nostr_send_order_event.delay(order_id=order.id)
order.log(f"Order({order.id},{str(order)}) is public in the order book") order.log(f"Order({order.id},{str(order)}) is public in the order book")
return return
@ -1352,6 +1372,9 @@ class Logics:
except Exception: except Exception:
pass pass
send_notification.delay(order_id=order.id, message="order_taken_confirmed") send_notification.delay(order_id=order.id, message="order_taken_confirmed")
nostr_send_order_event.delay(order_id=order.id)
order.log( order.log(
f"<b>Contract formalized.</b> Maker: Robot({order.maker.robot.id},{order.maker}). Taker: Robot({order.taker.robot.id},{order.taker}). API median price {order.currency.exchange_rate} {dict(Currency.currency_choices)[order.currency.currency]}/BTC. Premium is {order.premium}%. Contract size {order.last_satoshis} Sats" f"<b>Contract formalized.</b> Maker: Robot({order.maker.robot.id},{order.maker}). Taker: Robot({order.taker.robot.id},{order.taker}). API median price {order.currency.exchange_rate} {dict(Currency.currency_choices)[order.currency.currency]}/BTC. Premium is {order.premium}%. Contract size {order.last_satoshis} Sats"
) )
@ -1743,11 +1766,15 @@ class Logics:
order.log( order.log(
f"Robot({user.robot.id},{user.username}) paused the public order" f"Robot({user.robot.id},{user.username}) paused the public order"
) )
nostr_send_order_event.delay(order_id=order.id)
elif order.status == Order.Status.PAU: elif order.status == Order.Status.PAU:
order.update_status(Order.Status.PUB) order.update_status(Order.Status.PUB)
order.log( order.log(
f"Robot({user.robot.id},{user.username}) made public the paused order" f"Robot({user.robot.id},{user.username}) made public the paused order"
) )
nostr_send_order_event.delay(order_id=order.id)
else: else:
order.log( order.log(
f"Robot({user.robot.id},{user.username}) tried to pause/unpause an order that was not public or paused", f"Robot({user.robot.id},{user.username}) tried to pause/unpause an order that was not public or paused",

View File

@ -1,4 +1,6 @@
import pygeohash import pygeohash
import hashlib
import uuid
from nostr_sdk import Keys, Client, EventBuilder, NostrSigner from nostr_sdk import Keys, Client, EventBuilder, NostrSigner
from api.models import Order from api.models import Order
from decouple import config from decouple import config
@ -7,7 +9,7 @@ from decouple import config
class Nostr: class Nostr:
"""Simple nostr events manager to be used as a cache system for clients""" """Simple nostr events manager to be used as a cache system for clients"""
async def send_new_order_event(self, order): async def send_order_event(self, order):
"""Creates the event and sends it to the coordinator relay""" """Creates the event and sends it to the coordinator relay"""
# Initialize with coordinator Keys # Initialize with coordinator Keys
keys = Keys.generate() keys = Keys.generate()
@ -23,12 +25,16 @@ class Nostr:
print(f"Nostr event sent: {output}") print(f"Nostr event sent: {output}")
def generate_tags(self, order): def generate_tags(self, order):
hashed_id = hashlib.md5(
f"{config("COORDINATOR_ALIAS", cast=str)}{order.id}".encode("utf-8")
).hexdigest()
return [ return [
["d", order.id], ["d", uuid.UUID(hashed_id)],
["name", order.maker.robot_name], ["name", order.maker.robot_name],
["k", order.type.lower()], ["k", order.type.lower()],
["f", order.currency], ["f", order.currency],
["s", Order.Status(order.status).label], ["s", self.get_status_tag(order)],
["amt", order.last_satoshis], ["amt", order.last_satoshis],
["fa", order.amount], ["fa", order.amount],
["pm", order.payment_method.split(" ")], ["pm", order.payment_method.split(" ")],
@ -39,9 +45,16 @@ class Nostr:
], ],
["expiration", order.expires_at.timestamp()], ["expiration", order.expires_at.timestamp()],
["y", "robosats"], ["y", "robosats"],
["coordinator", config("COORDINATOR_ALIAS", cast=str)]["z", "order"],
["n", order.network], ["n", order.network],
["layer", "lightning"], ["layer", "lightning"],
["g", pygeohash.encode(order.latitude, order.longitude)], ["g", pygeohash.encode(order.latitude, order.longitude)],
["bond", order.bond], ["bond", order.bond],
["z", "order"],
["coordinator", config("COORDINATOR_ALIAS", cast=str)],
] ]
def get_status_tag(self, order):
if order.status == Order.Status.PUB:
return "pending"
else:
return "canceled"

View File

@ -253,7 +253,7 @@ def cache_market():
@shared_task(name="", ignore_result=True, time_limit=120) @shared_task(name="", ignore_result=True, time_limit=120)
def send_order_nostr_event(order_id=None, message=None): def nostr_send_order_event(order_id=None):
if order_id: if order_id:
from api.models import Order from api.models import Order
from api.nostr import Nostr from api.nostr import Nostr
@ -261,8 +261,7 @@ def send_order_nostr_event(order_id=None, message=None):
order = Order.objects.get(id=order_id) order = Order.objects.get(id=order_id)
nostr = Nostr() nostr = Nostr()
if message == "new": coroutine = nostr.send_order_event(order)
coroutine = nostr.send_new_order_event(order)
if coroutine: if coroutine:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine) loop.run_until_complete(coroutine)

View File

@ -205,14 +205,14 @@ services:
# - redis # - redis
# network_mode: service:bitcoind # network_mode: service:bitcoind
# strfry: strfry:
# build: https://github.com/hoytech/strfry.git image: dockurr/strfry:0.9.6
# container_name: test-strfry container_name: test-strfry
# restart: unless-stopped restart: unless-stopped
# volumes: volumes:
# - ./nodeapp/strfry/config/strfry.conf:/strfry/strfry.conf:r - ./nodeapp/strfry/db:/app/strfry-db
# network_mode: service:bitcoind - ./nodeapp/strfry/config/strfry.conf:/etc/strfry.conf:r
network_mode: service:bitcoind
volumes: volumes:
redisdata: redisdata:

View File

@ -29,3 +29,4 @@ drf-spectacular-sidecar==2024.7.1
django-cors-headers==4.4.0 django-cors-headers==4.4.0
base91==1.0.1 base91==1.0.1
nostr-sdk==0.32.2 nostr-sdk==0.32.2
pygeohash==1.2.0

View File

@ -5,7 +5,7 @@ from django.urls import reverse
from api.management.commands.clean_orders import Command as CleanOrders from api.management.commands.clean_orders import Command as CleanOrders
from api.management.commands.follow_invoices import Command as FollowInvoices from api.management.commands.follow_invoices import Command as FollowInvoices
from api.models import Order from api.models import Order
from api.tasks import follow_send_payment, send_notification, send_order_nostr_event from api.tasks import follow_send_payment, send_notification, nostr_send_order_event
from tests.utils.node import ( from tests.utils.node import (
add_invoice, add_invoice,
create_address, create_address,
@ -156,7 +156,7 @@ class Trade:
wait_nodes_sync() wait_nodes_sync()
@patch("api.tasks.send_notification.delay", send_notification) @patch("api.tasks.send_notification.delay", send_notification)
@patch("api.tasks.send_order_nostr_event.delay", send_order_nostr_event) @patch("api.tasks.nostr_send_order_event.delay", nostr_send_order_event)
def publish_order(self): def publish_order(self):
# Maker's first order fetch. Should trigger maker bond hold invoice generation. # Maker's first order fetch. Should trigger maker bond hold invoice generation.
self.get_order() self.get_order()