robosats/api/nostr.py
2024-09-06 10:23:27 +02:00

102 lines
3.3 KiB
Python

import pygeohash
import hashlib
import uuid
from asgiref.sync import sync_to_async
from nostr_sdk import Keys, Client, EventBuilder, NostrSigner, Kind, Tag
from api.models import Order
from decouple import config
class Nostr:
"""Simple nostr events manager to be used as a cache system for clients"""
async def send_order_event(self, order):
"""Creates the event and sends it to the coordinator relay"""
if config("NOSTR_NSEC", cast=str, default="") == "":
return
print("Sending nostr event")
# Initialize with coordinator Keys
keys = Keys.parse(config("NOSTR_NSEC", cast=str))
signer = NostrSigner.keys(keys)
client = Client(signer)
# Add relays and connect
await client.add_relays(["ws://localhost:7777"])
await client.connect()
robot_name = await self.get_robot_name(order)
currency = await self.get_robot_currency(order)
event = EventBuilder(
Kind(38383), "", self.generate_tags(order, robot_name, currency)
).to_event(keys)
await client.send_event(event)
print(f"Nostr event sent: {event.as_json()}")
@sync_to_async
def get_robot_name(self, order):
return order.maker.username
@sync_to_async
def get_robot_currency(self, order):
return str(order.currency)
def generate_tags(self, order, robot_name, currency):
hashed_id = hashlib.md5(
f"{config("COORDINATOR_ALIAS", cast=str)}{order.id}".encode("utf-8")
).hexdigest()
tags = [
Tag.parse(["d", str(uuid.UUID(hashed_id))]),
Tag.parse(["name", robot_name]),
Tag.parse(["k", "sell" if order.type == Order.Types.SELL else "buy"]),
Tag.parse(["f", currency]),
Tag.parse(["s", self.get_status_tag(order)]),
Tag.parse(["amt", "0"]),
Tag.parse(
["fa"]
+ (
[str(order.amount)]
if not order.has_range
else [str(order.min_amount), str(order.max_amount)]
)
),
Tag.parse(["pm"] + order.payment_method.split(" ")),
Tag.parse(["premium", str(order.premium)]),
Tag.parse(
[
"source",
f"http://{config("HOST_NAME")}/order/{config("COORDINATOR_ALIAS", cast=str).lower()}/{order.id}",
]
),
Tag.parse(["expiration", str(int(order.expires_at.timestamp()))]),
Tag.parse(["y", "robosats", config("COORDINATOR_ALIAS", cast=str).lower()]),
Tag.parse(["n", str(config("NETWORK"))]),
Tag.parse(["layer"] + self.get_layer_tag(order)),
Tag.parse(["bond", str(order.bond_size)]),
Tag.parse(["z", "order"]),
]
if order.latitude and order.longitude:
tags.extend(
[Tag.parse(["g", pygeohash.encode(order.latitude, order.longitude)])]
)
return tags
def get_status_tag(self, order):
if order.status == Order.Status.PUB:
return "pending"
else:
return "success"
def get_layer_tag(self, order):
if order.type == Order.Types.SELL:
return ["onchain", "lightning"]
else:
return ["lightning"]