Switch to coincurve for Windows compatibility

This commit is contained in:
thePR0M3TH3AN
2025-06-29 21:25:50 -04:00
parent e48aadd9c7
commit c1d9ed8501
4 changed files with 62 additions and 5 deletions

View File

@@ -11,9 +11,15 @@ import concurrent.futures
from typing import List, Optional, Callable
from pathlib import Path
from monstr.client.client import ClientPool
from monstr.encrypt import Keys, NIP4Encrypt
from monstr.event.event import Event
try:
from monstr.client.client import ClientPool
from monstr.encrypt import Keys, NIP4Encrypt
from monstr.event.event import Event
except ImportError: # Fallback placeholders when monstr is unavailable
ClientPool = None
NIP4Encrypt = None
Event = None
from .coincurve_keys import Keys
import threading
import uuid
@@ -102,6 +108,8 @@ class NostrClient:
"""
try:
logger.debug("Initializing ClientPool with relays.")
if ClientPool is None:
raise ImportError("monstr library is required for ClientPool")
self.client_pool = ClientPool(self.relays)
# Start the ClientPool in a separate thread
@@ -256,6 +264,8 @@ class NostrClient:
content_base64 = event.content
if event.kind == Event.KIND_ENCRYPT:
if NIP4Encrypt is None:
raise ImportError("monstr library required for NIP4 encryption")
nip4_encrypt = NIP4Encrypt(self.key_manager.keys)
content_base64 = nip4_encrypt.decrypt_message(
event.content, event.pub_key
@@ -500,6 +510,8 @@ class NostrClient:
event.created_at = int(time.time())
if to_pubkey:
if NIP4Encrypt is None:
raise ImportError("monstr library required for NIP4 encryption")
nip4_encrypt = NIP4Encrypt(self.key_manager.keys)
event.content = nip4_encrypt.encrypt_message(event.content, to_pubkey)
event.kind = Event.KIND_ENCRYPT

View File

@@ -0,0 +1,45 @@
from __future__ import annotations
from bech32 import bech32_encode, bech32_decode, convertbits
from coincurve import PrivateKey, PublicKey
class Keys:
"""Minimal replacement for monstr.encrypt.Keys using coincurve."""
def __init__(self, priv_k: str | None = None, pub_k: str | None = None):
if priv_k is not None:
if priv_k.startswith("nsec"):
priv_k = self.bech32_to_hex(priv_k)
self._priv_k = priv_k
priv = PrivateKey(bytes.fromhex(priv_k))
else:
priv = PrivateKey()
self._priv_k = priv.to_hex()
pub = priv.public_key.format(compressed=True).hex()[2:]
if pub_k:
if pub_k.startswith("npub"):
pub_k = self.bech32_to_hex(pub_k)
self._pub_k = pub_k
else:
self._pub_k = pub
@staticmethod
def hex_to_bech32(key_str: str, prefix: str = "npub") -> str:
data = convertbits(bytes.fromhex(key_str), 8, 5)
return bech32_encode(prefix, data)
@staticmethod
def bech32_to_hex(key: str) -> str:
hrp, data = bech32_decode(key)
if data is None:
raise ValueError("Invalid bech32 key")
decoded = convertbits(data, 5, 8, False)
return bytes(decoded).hex()
def private_key_hex(self) -> str:
return self._priv_k
def public_key_hex(self) -> str:
return self._pub_k

View File

@@ -7,7 +7,7 @@ from bech32 import bech32_encode, convertbits
from local_bip85.bip85 import BIP85
from bip_utils import Bip39SeedGenerator
from monstr.encrypt import Keys
from .coincurve_keys import Keys
logger = logging.getLogger(__name__)

View File

@@ -3,7 +3,7 @@ termcolor>=1.1.0
cryptography>=40.0.2
bip-utils>=2.5.0
bech32==1.2.0
monstr @ git+https://github.com/monty888/monstr.git@master#egg=monstr
coincurve>=18.0.0
mnemonic
aiohttp
bcrypt