robosats/api/nostr.py

115 lines
3.7 KiB
Python
Raw Normal View History

2024-07-01 16:00:17 +00:00
import pygeohash
2024-07-15 10:33:09 +00:00
import hashlib
import uuid
2024-08-07 08:13:48 +00:00
from asgiref.sync import sync_to_async
2024-08-07 22:45:42 +00:00
from nostr_sdk import Keys, Client, EventBuilder, NostrSigner, Kind, Tag
2024-07-01 16:00:17 +00:00
from api.models import Order
from decouple import config
class Nostr:
"""Simple nostr events manager to be used as a cache system for clients"""
2024-07-15 10:33:09 +00:00
async def send_order_event(self, order):
2024-07-01 16:00:17 +00:00
"""Creates the event and sends it to the coordinator relay"""
2024-07-15 14:36:30 +00:00
2024-07-16 09:11:08 +00:00
if config("NOSTR_NSEC", cast=str, default="") == "":
return
2024-07-15 14:36:30 +00:00
print("Sending nostr event")
2024-07-01 16:00:17 +00:00
# Initialize with coordinator Keys
2024-07-16 09:11:08 +00:00
keys = Keys.parse(config("NOSTR_NSEC", cast=str))
2024-07-01 16:00:17 +00:00
signer = NostrSigner.keys(keys)
client = Client(signer)
# Add relays and connect
2024-07-15 08:19:53 +00:00
await client.add_relays(["ws://localhost:7777"])
2024-07-01 16:00:17 +00:00
await client.connect()
2024-08-07 08:13:48 +00:00
robot_name = await self.get_robot_name(order)
2024-09-16 10:11:56 +00:00
robot_hash_id = await self.get_robot_hash_id(order)
2024-08-07 08:13:48 +00:00
currency = await self.get_robot_currency(order)
2024-08-07 22:45:42 +00:00
event = EventBuilder(
2024-09-16 10:11:56 +00:00
Kind(38383),
"",
self.generate_tags(order, robot_name, robot_hash_id, currency),
2024-08-07 22:45:42 +00:00
).to_event(keys)
2024-08-07 22:28:38 +00:00
await client.send_event(event)
print(f"Nostr event sent: {event.as_json()}")
2024-07-01 16:00:17 +00:00
2024-08-07 08:13:48 +00:00
@sync_to_async
def get_robot_name(self, order):
return order.maker.username
2024-09-16 10:11:56 +00:00
@sync_to_async
def get_robot_hash_id(self, order):
return order.maker.robot.hash_id
2024-08-07 08:13:48 +00:00
@sync_to_async
def get_robot_currency(self, order):
return str(order.currency)
2024-09-16 10:11:56 +00:00
def generate_tags(self, order, robot_name, robot_hash_id, currency):
2024-07-15 10:33:09 +00:00
hashed_id = hashlib.md5(
f"{config("COORDINATOR_ALIAS", cast=str)}{order.id}".encode("utf-8")
).hexdigest()
2024-07-21 17:59:30 +00:00
tags = [
2024-08-07 20:49:16 +00:00
Tag.parse(["d", str(uuid.UUID(hashed_id))]),
2024-09-16 10:11:56 +00:00
Tag.parse(["name", robot_name, robot_hash_id]),
2024-08-07 20:49:16 +00:00
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"]),
2024-08-09 08:57:19 +00:00
Tag.parse(
2024-09-06 08:23:27 +00:00
["fa"]
+ (
[str(order.amount)]
if not order.has_range
else [str(order.min_amount), str(order.max_amount)]
)
2024-08-09 08:57:19 +00:00
),
2024-08-07 20:49:16 +00:00
Tag.parse(["pm"] + order.payment_method.split(" ")),
Tag.parse(["premium", str(order.premium)]),
Tag.parse(
[
"source",
2024-08-07 22:28:38 +00:00
f"http://{config("HOST_NAME")}/order/{config("COORDINATOR_ALIAS", cast=str).lower()}/{order.id}",
2024-08-07 20:49:16 +00:00
]
),
2024-09-16 10:11:56 +00:00
Tag.parse(
[
"expiration",
str(int(order.expires_at.timestamp())),
str(order.escrow_duration),
]
),
2024-08-07 22:28:38 +00:00
Tag.parse(["y", "robosats", config("COORDINATOR_ALIAS", cast=str).lower()]),
2024-08-07 20:49:16 +00:00
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"]),
2024-07-01 16:00:17 +00:00
]
2024-08-07 21:03:07 +00:00
2024-07-21 17:59:30 +00:00
if order.latitude and order.longitude:
2024-08-07 20:49:16 +00:00
tags.extend(
[Tag.parse(["g", pygeohash.encode(order.latitude, order.longitude)])]
)
2024-07-21 17:59:30 +00:00
return tags
2024-07-15 10:33:09 +00:00
def get_status_tag(self, order):
if order.status == Order.Status.PUB:
return "pending"
else:
2024-07-16 11:16:48 +00:00
return "success"
def get_layer_tag(self, order):
if order.type == Order.Types.SELL:
return ["onchain", "lightning"]
else:
return ["lightning"]