From 5ec2c3604ec2a19a811ccbaa40b25dd917d4395f Mon Sep 17 00:00:00 2001 From: calle <93376500+callebtc@users.noreply.github.com> Date: Mon, 13 Feb 2023 23:19:19 +0100 Subject: [PATCH] Nostr bech32 dm (#109) * nostr: bech32 keys and remember last DM check * cump to 0.9.2 * make format --- .env.example | 2 +- README.md | 2 +- cashu/core/settings.py | 2 +- cashu/nostr | 2 +- cashu/wallet/cli.py | 6 ++++-- cashu/wallet/cli_helpers.py | 36 +++++++++++++++++++++++++----------- cashu/wallet/crud.py | 24 ++++++++++++++++++++++++ cashu/wallet/migrations.py | 25 +++++++++++++++++++++++++ pyproject.toml | 2 +- setup.py | 2 +- 10 files changed, 84 insertions(+), 19 deletions(-) diff --git a/.env.example b/.env.example index 281171b..e8f8e87 100644 --- a/.env.example +++ b/.env.example @@ -33,6 +33,6 @@ LNBITS_KEY=yourkeyasdasdasd # NOSTR # nostr private key to which to receive tokens to -NOSTR_PRIVATE_KEY=hex_nostrprivatekey_here +NOSTR_PRIVATE_KEY=nostr_privatekey_here_hex_or_bech32 # nostr relays (comma separated list) NOSTR_RELAYS="wss://nostr-pub.wellorder.net" diff --git a/README.md b/README.md index b86301d..3de4f50 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ cashu info Returns: ```bash -Version: 0.9.1 +Version: 0.9.2 Debug: False Cashu dir: /home/user/.cashu Wallet: wallet diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 2613ec8..e2062a0 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -66,4 +66,4 @@ NOSTR_RELAYS = env.list( ) MAX_ORDER = 64 -VERSION = "0.9.1" +VERSION = "0.9.2" diff --git a/cashu/nostr b/cashu/nostr index c5a050f..2872fe3 160000 --- a/cashu/nostr +++ b/cashu/nostr @@ -1 +1 @@ -Subproject commit c5a050f944439a8ffada64fd9218f8433cd20372 +Subproject commit 2872fe3c24ad0036e1bcf262790930d9a1e65d70 diff --git a/cashu/wallet/cli.py b/cashu/wallet/cli.py index c1bafdf..edc723f 100644 --- a/cashu/wallet/cli.py +++ b/cashu/wallet/cli.py @@ -41,8 +41,10 @@ from cashu.wallet import migrations from cashu.wallet.crud import ( get_keyset, get_lightning_invoices, + get_nostr_last_check_timestamp, get_reserved_proofs, get_unused_locks, + set_nostr_last_check_timestamp, ) from cashu.wallet.wallet import Wallet as Wallet @@ -609,8 +611,8 @@ async def info(ctx: Context): if TOR: print(f"Tor enabled: {TOR}") if NOSTR_PRIVATE_KEY: - client = NostrClient(privatekey_hex=NOSTR_PRIVATE_KEY, connect=False) - print(f"Nostr public key: {client.public_key.hex()}") + client = NostrClient(private_key=NOSTR_PRIVATE_KEY, connect=False) + print(f"Nostr public key: {client.public_key.bech32()}") print(f"Nostr relays: {NOSTR_RELAYS}") if SOCKS_HOST: print(f"Socks proxy: {SOCKS_HOST}:{SOCKS_PORT}") diff --git a/cashu/wallet/cli_helpers.py b/cashu/wallet/cli_helpers.py index ef03fce..81a6dfb 100644 --- a/cashu/wallet/cli_helpers.py +++ b/cashu/wallet/cli_helpers.py @@ -1,6 +1,7 @@ import asyncio import os import threading +import time import urllib.parse from typing import List @@ -14,7 +15,11 @@ from cashu.core.settings import CASHU_DIR, MINT_URL, NOSTR_PRIVATE_KEY, NOSTR_RE from cashu.nostr.nostr.client.client import NostrClient from cashu.nostr.nostr.event import Event from cashu.nostr.nostr.key import PublicKey -from cashu.wallet.crud import get_keyset +from cashu.wallet.crud import ( + get_keyset, + get_nostr_last_check_timestamp, + set_nostr_last_check_timestamp, +) from cashu.wallet.wallet import Wallet as Wallet @@ -235,9 +240,14 @@ async def send_nostr(ctx: Context, amount: int, pubkey: str, verbose: bool, yes: # we only use ephemeral private keys for sending client = NostrClient(relays=NOSTR_RELAYS) if verbose: - print(f"Your ephemeral nostr private key: {client.private_key.hex()}") - await asyncio.sleep(1) - client.dm(token, PublicKey(bytes.fromhex(pubkey))) + print(f"Your ephemeral nostr private key: {client.private_key.bech32()}") + + if pubkey.startswith("npub"): + pubkey_to = PublicKey().from_npub(pubkey) + else: + pubkey_to = PublicKey(bytes.fromhex(pubkey)) + + client.dm(token, pubkey_to) print(f"Token sent to {pubkey}") client.close() @@ -248,10 +258,10 @@ async def receive_nostr(ctx: Context, verbose: bool): "Warning: No nostr private key set! You don't have NOSTR_PRIVATE_KEY set in your .env file. I will create a random private key for this session but I will not remember it." ) print("") - client = NostrClient(privatekey_hex=NOSTR_PRIVATE_KEY, relays=NOSTR_RELAYS) - print(f"Your nostr public key: {client.public_key.hex()}") + client = NostrClient(private_key=NOSTR_PRIVATE_KEY, relays=NOSTR_RELAYS) + print(f"Your nostr public key: {client.public_key.bech32()}") if verbose: - print(f"Your nostr private key (do not share!): {client.private_key.hex()}") + print(f"Your nostr private key (do not share!): {client.private_key.bech32()}") await asyncio.sleep(2) def get_token_callback(event: Event, decrypted_content): @@ -267,12 +277,16 @@ async def receive_nostr(ctx: Context, verbose: bool): except Exception as e: pass + # determine timestamp of last check so we don't scan all historical DMs + wallet: Wallet = ctx.obj["WALLET"] + last_check = await get_nostr_last_check_timestamp(db=wallet.db) + if last_check: + last_check -= 60 * 60 # 1 hour tolerance + await set_nostr_last_check_timestamp(timestamp=int(time.time()), db=wallet.db) + t = threading.Thread( target=client.get_dm, - args=( - client.public_key, - get_token_callback, - ), + args=(client.public_key, get_token_callback, {"since": last_check}), name="Nostr DM", ) t.start() diff --git a/cashu/wallet/crud.py b/cashu/wallet/crud.py index 3c1c883..0109838 100644 --- a/cashu/wallet/crud.py +++ b/cashu/wallet/crud.py @@ -334,3 +334,27 @@ async def update_lightning_invoice( hash, ), ) + + +async def set_nostr_last_check_timestamp( + db: Database, + timestamp: int, + conn: Optional[Connection] = None, +): + await (conn or db).execute( + f"UPDATE nostr SET last = ? WHERE type = ?", + (timestamp, "dm"), + ) + + +async def get_nostr_last_check_timestamp( + db: Database, + conn: Optional[Connection] = None, +): + row = await (conn or db).fetchone( + f""" + SELECT last from nostr WHERE type = ? + """, + ("dm",), + ) + return row[0] if row else None diff --git a/cashu/wallet/migrations.py b/cashu/wallet/migrations.py index bdb3c36..6b124ae 100644 --- a/cashu/wallet/migrations.py +++ b/cashu/wallet/migrations.py @@ -144,3 +144,28 @@ async def m006_invoices(db: Database): ); """ ) + + +async def m007_nostr(db: Database): + """ + Stores timestamps of nostr operations. + """ + await db.execute( + f""" + CREATE TABLE IF NOT EXISTS nostr ( + type TEXT NOT NULL, + last TIMESTAMP DEFAULT NULL + ) + """ + ) + await db.execute( + f""" + INSERT INTO nostr + (type, last) + VALUES (?, ?) + """, + ( + "dm", + None, + ), + ) diff --git a/pyproject.toml b/pyproject.toml index e2d60e7..7bd5c58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cashu" -version = "0.9.1" +version = "0.9.2" description = "Ecash wallet and mint." authors = ["calle "] license = "MIT" diff --git a/setup.py b/setup.py index 815f539..92bb73d 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ entry_points = {"console_scripts": ["cashu = cashu.wallet.cli:cli"]} setuptools.setup( name="cashu", - version="0.9.1", + version="0.9.2", description="Ecash wallet and mint for Bitcoin Lightning", long_description=long_description, long_description_content_type="text/markdown",