You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
215 lines
8.8 KiB
Python
215 lines
8.8 KiB
Python
import json
|
|
import ssl
|
|
import time
|
|
import sys
|
|
from nostr.relay_manager import RelayManager
|
|
from nostr.message_type import ClientMessageType
|
|
from nostr.filter import Filter, Filters
|
|
from nostr.event import EncryptedDirectMessage
|
|
from nostr.key import PrivateKey
|
|
|
|
def parse_nwc_url(nwc_url):
|
|
"""Parse Nostr Wallet Connect URL to extract pubkey, relay, secret, and lud16."""
|
|
print(f"DEBUG: Starting to parse NWC URL: {nwc_url}")
|
|
try:
|
|
# Remove 'nostr+walletconnect://' or 'nwc:' prefix
|
|
if nwc_url.startswith('nostr+walletconnect://'):
|
|
print(f"DEBUG: Removing 'nostr+walletconnect://' prefix")
|
|
nwc_url = nwc_url[22:]
|
|
elif nwc_url.startswith('nwc:'):
|
|
print(f"DEBUG: Removing 'nwc:' prefix")
|
|
nwc_url = nwc_url[4:]
|
|
else:
|
|
print(f"DEBUG: No recognized prefix found in URL")
|
|
raise ValueError("Invalid NWC URL: missing 'nostr+walletconnect://' or 'nwc:' prefix")
|
|
|
|
print(f"DEBUG: URL after prefix removal: {nwc_url}")
|
|
|
|
# Split into pubkey and query params
|
|
parts = nwc_url.split('?')
|
|
pubkey = parts[0]
|
|
print(f"DEBUG: Extracted pubkey: {pubkey}")
|
|
|
|
# Validate pubkey (should be 64 hex characters)
|
|
if len(pubkey) != 64 or not all(c in '0123456789abcdef' for c in pubkey):
|
|
raise ValueError("Invalid NWC URL: pubkey must be 64 hex characters")
|
|
|
|
# Extract relay, secret, and lud16 from query params
|
|
relay = None
|
|
secret = None
|
|
lud16 = None
|
|
if len(parts) > 1:
|
|
print(f"DEBUG: Query parameters found: {parts[1]}")
|
|
params = parts[1].split('&')
|
|
for param in params:
|
|
if param.startswith('relay='):
|
|
relay = param[6:]
|
|
print(f"DEBUG: Extracted relay: {relay}")
|
|
elif param.startswith('secret='):
|
|
secret = param[7:]
|
|
print(f"DEBUG: Extracted secret: {secret}")
|
|
elif param.startswith('lud16='):
|
|
lud16 = param[6:]
|
|
print(f"DEBUG: Extracted lud16: {lud16}")
|
|
else:
|
|
print(f"DEBUG: No query parameters found")
|
|
|
|
if not pubkey or not relay or not secret:
|
|
raise ValueError("Invalid NWC URL: missing required fields (pubkey, relay, or secret)")
|
|
|
|
# Validate secret (should be 64 hex characters)
|
|
if len(secret) != 64 or not all(c in '0123456789abcdef' for c in secret):
|
|
raise ValueError("Invalid NWC URL: secret must be 64 hex characters")
|
|
|
|
return {
|
|
'relay': relay,
|
|
'pubkey': pubkey,
|
|
'secret': secret,
|
|
'lud16': lud16
|
|
}
|
|
except Exception as e:
|
|
print(f"DEBUG: Error parsing NWC URL: {e}")
|
|
sys.exit(1)
|
|
|
|
def get_balance(nwc_url):
|
|
"""Get balance using Nostr Wallet Connect."""
|
|
print(f"DEBUG: Starting get_balance with NWC URL: {nwc_url}")
|
|
# Parse NWC URL
|
|
nwc_data = parse_nwc_url(nwc_url)
|
|
relay = nwc_data['relay']
|
|
wallet_pubkey = nwc_data['pubkey']
|
|
secret = nwc_data['secret']
|
|
lud16 = nwc_data['lud16']
|
|
print(f"DEBUG: Parsed NWC data - Relay: {relay}, Pubkey: {wallet_pubkey}, Secret: {secret}, lud16: {lud16}")
|
|
|
|
# Initialize private key from secret (assuming it's a hex key)
|
|
try:
|
|
#print(f"DEBUG: Initializing private key from secret")
|
|
private_key = PrivateKey(bytes.fromhex(secret))
|
|
print(f"DEBUG: Private key initialized, public key: {private_key.public_key.hex()}")
|
|
except Exception as e:
|
|
print(f"DEBUG: Error initializing private key: {e}")
|
|
sys.exit(1)
|
|
|
|
# Create get_balance request
|
|
balance_request = {
|
|
"method": "get_balance",
|
|
"params": {}
|
|
}
|
|
print(f"DEBUG: Created balance request: {balance_request}")
|
|
|
|
#balance_request_string = json.dumps(balance_request)
|
|
#encrypted = private_key.encrypt_message(balance_request_string, wallet_pubkey)
|
|
#print(f"\n\n\nencryption returned: {encrypted}")
|
|
#decrypted = private_key.decrypt_message(encrypted, wallet_pubkey)
|
|
#print(f"\n\n\ndecryption returned: {decrypted}\n\n\n")
|
|
|
|
#decrypted = private_key.decrypt_message(encrypted, wallet_pubkey)
|
|
#print(f"\n\n\ndecryption from nak returned: {decrypted}\n\n\n")
|
|
# padding error
|
|
|
|
|
|
# Create encrypted DM with the balance request
|
|
print(f"DEBUG: Creating encrypted DM to wallet pubkey: {wallet_pubkey}")
|
|
dm = EncryptedDirectMessage(
|
|
recipient_pubkey=wallet_pubkey,
|
|
cleartext_content=json.dumps(balance_request)
|
|
)
|
|
|
|
|
|
print(f"DEBUG: Signing DM {json.dumps(dm)} with private key")
|
|
private_key.sign_event(dm) # sign also does encryption if it's a encrypted dm
|
|
print(f"DEBUG: DM created with ID: {dm.id}")
|
|
|
|
# Set up relay manager
|
|
print(f"DEBUG: Setting up relay manager with relay: {relay}")
|
|
relay_manager = RelayManager()
|
|
relay_manager.add_relay(relay)
|
|
print(f"DEBUG: Opening relay connections")
|
|
relay_manager.open_connections({"cert_reqs": ssl.CERT_NONE})
|
|
time.sleep(2) # Allow connections to open
|
|
|
|
# Check for relay connection notices
|
|
print(f"DEBUG: Checking for relay notices")
|
|
while relay_manager.message_pool.has_notices():
|
|
notice = relay_manager.message_pool.get_notice()
|
|
print(f"DEBUG: Relay notice: {notice.content}")
|
|
|
|
# Set up subscription to receive response
|
|
subscription_id = "nwc_balance_" + str(round(time.time()))
|
|
#print(f"DEBUG: Setting up subscription with ID: {subscription_id}")
|
|
filters = Filters([Filter(
|
|
kinds=[23195], # NWC replies
|
|
authors=[wallet_pubkey],
|
|
pubkey_refs=[private_key.public_key.hex()]
|
|
)])
|
|
#print(f"DEBUG: Subscription filters: {filters.to_json_array()}")
|
|
relay_manager.add_subscription(subscription_id, filters)
|
|
|
|
# Publish request
|
|
print(f"DEBUG: Publishing subscription request")
|
|
request_message = [ClientMessageType.REQUEST, subscription_id]
|
|
request_message.extend(filters.to_json_array())
|
|
relay_manager.publish_message(json.dumps(request_message))
|
|
print(f"DEBUG: Publishing encrypted DM")
|
|
relay_manager.publish_event(dm)
|
|
# only accept events after the time it was published
|
|
after_time = time.time()
|
|
if sys.platform == "esp32":
|
|
# on esp32, it needs this correction:
|
|
after_time += 946684800
|
|
after_time -= 60 # go back a bit because server clocks might be drifting
|
|
print(f"will only consider events after {after_time}")
|
|
|
|
|
|
# Wait for response
|
|
print(f"DEBUG: Waiting for response...")
|
|
print(f"starting at {time.localtime()}")
|
|
start_time = time.time()
|
|
balance = None
|
|
while time.time() - start_time < 60 * 2:
|
|
while relay_manager.message_pool.has_events():
|
|
print(f"DEBUG: Event received from message pool")
|
|
event_msg = relay_manager.message_pool.get_event()
|
|
event_created_at = event_msg.event.created_at
|
|
print(f"Received at {time.localtime()} a message with timestamp {event_created_at}")
|
|
if event_created_at < after_time:
|
|
print("Skipping event because it's too old!")
|
|
continue
|
|
#print(f"event_msg content {event_msg.event.content}")
|
|
try:
|
|
#print(f"DEBUG: Decrypting event from public_key: {event_msg.event.public_key}")
|
|
decrypted_content = private_key.decrypt_message(
|
|
event_msg.event.content,
|
|
event_msg.event.public_key
|
|
)
|
|
print(f"DEBUG: Decrypted content: {decrypted_content}")
|
|
response = json.loads(decrypted_content)
|
|
print(f"DEBUG: Parsed response: {response}")
|
|
if response.get("method") == "get_balance":
|
|
balance = response.get("result", {}).get("balance")
|
|
print(f"DEBUG: Balance found: {balance} satoshis")
|
|
break
|
|
except Exception as e:
|
|
print(f"DEBUG: Error processing response: {e}")
|
|
if balance is not None:
|
|
break
|
|
time.sleep(1)
|
|
|
|
print(f"finished at {time.localtime()}")
|
|
|
|
# Close connections
|
|
print(f"DEBUG: Closing relay connections")
|
|
relay_manager.close_connections()
|
|
|
|
if balance is not None:
|
|
print(f"Balance: {balance} satoshis")
|
|
else:
|
|
print("No balance response received or request timed out")
|
|
|
|
# Example usage
|
|
#nwc_url = "nostr+walletconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.getalby.com/v1&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c&lud16=moritz@getalby.com"
|
|
#nwc_url = "nostr+walletconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss://relay.getalby.com/v1&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c&lud16=moritz@getalby.com"
|
|
print(f"Processing NWC URL: {nwc_url}")
|
|
get_balance(nwc_url)
|