mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-20 02:24:20 +01:00
Nostr bech32 dm (#109)
* nostr: bech32 keys and remember last DM check * cump to 0.9.2 * make format
This commit is contained in:
@@ -33,6 +33,6 @@ LNBITS_KEY=yourkeyasdasdasd
|
|||||||
|
|
||||||
# NOSTR
|
# NOSTR
|
||||||
# nostr private key to which to receive tokens to
|
# 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 (comma separated list)
|
||||||
NOSTR_RELAYS="wss://nostr-pub.wellorder.net"
|
NOSTR_RELAYS="wss://nostr-pub.wellorder.net"
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ cashu info
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
```bash
|
```bash
|
||||||
Version: 0.9.1
|
Version: 0.9.2
|
||||||
Debug: False
|
Debug: False
|
||||||
Cashu dir: /home/user/.cashu
|
Cashu dir: /home/user/.cashu
|
||||||
Wallet: wallet
|
Wallet: wallet
|
||||||
|
|||||||
@@ -66,4 +66,4 @@ NOSTR_RELAYS = env.list(
|
|||||||
)
|
)
|
||||||
|
|
||||||
MAX_ORDER = 64
|
MAX_ORDER = 64
|
||||||
VERSION = "0.9.1"
|
VERSION = "0.9.2"
|
||||||
|
|||||||
Submodule cashu/nostr updated: c5a050f944...2872fe3c24
@@ -41,8 +41,10 @@ from cashu.wallet import migrations
|
|||||||
from cashu.wallet.crud import (
|
from cashu.wallet.crud import (
|
||||||
get_keyset,
|
get_keyset,
|
||||||
get_lightning_invoices,
|
get_lightning_invoices,
|
||||||
|
get_nostr_last_check_timestamp,
|
||||||
get_reserved_proofs,
|
get_reserved_proofs,
|
||||||
get_unused_locks,
|
get_unused_locks,
|
||||||
|
set_nostr_last_check_timestamp,
|
||||||
)
|
)
|
||||||
from cashu.wallet.wallet import Wallet as Wallet
|
from cashu.wallet.wallet import Wallet as Wallet
|
||||||
|
|
||||||
@@ -609,8 +611,8 @@ async def info(ctx: Context):
|
|||||||
if TOR:
|
if TOR:
|
||||||
print(f"Tor enabled: {TOR}")
|
print(f"Tor enabled: {TOR}")
|
||||||
if NOSTR_PRIVATE_KEY:
|
if NOSTR_PRIVATE_KEY:
|
||||||
client = NostrClient(privatekey_hex=NOSTR_PRIVATE_KEY, connect=False)
|
client = NostrClient(private_key=NOSTR_PRIVATE_KEY, connect=False)
|
||||||
print(f"Nostr public key: {client.public_key.hex()}")
|
print(f"Nostr public key: {client.public_key.bech32()}")
|
||||||
print(f"Nostr relays: {NOSTR_RELAYS}")
|
print(f"Nostr relays: {NOSTR_RELAYS}")
|
||||||
if SOCKS_HOST:
|
if SOCKS_HOST:
|
||||||
print(f"Socks proxy: {SOCKS_HOST}:{SOCKS_PORT}")
|
print(f"Socks proxy: {SOCKS_HOST}:{SOCKS_PORT}")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from typing import List
|
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.client.client import NostrClient
|
||||||
from cashu.nostr.nostr.event import Event
|
from cashu.nostr.nostr.event import Event
|
||||||
from cashu.nostr.nostr.key import PublicKey
|
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
|
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
|
# we only use ephemeral private keys for sending
|
||||||
client = NostrClient(relays=NOSTR_RELAYS)
|
client = NostrClient(relays=NOSTR_RELAYS)
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f"Your ephemeral nostr private key: {client.private_key.hex()}")
|
print(f"Your ephemeral nostr private key: {client.private_key.bech32()}")
|
||||||
await asyncio.sleep(1)
|
|
||||||
client.dm(token, PublicKey(bytes.fromhex(pubkey)))
|
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}")
|
print(f"Token sent to {pubkey}")
|
||||||
client.close()
|
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."
|
"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("")
|
print("")
|
||||||
client = NostrClient(privatekey_hex=NOSTR_PRIVATE_KEY, relays=NOSTR_RELAYS)
|
client = NostrClient(private_key=NOSTR_PRIVATE_KEY, relays=NOSTR_RELAYS)
|
||||||
print(f"Your nostr public key: {client.public_key.hex()}")
|
print(f"Your nostr public key: {client.public_key.bech32()}")
|
||||||
if verbose:
|
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)
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
def get_token_callback(event: Event, decrypted_content):
|
def get_token_callback(event: Event, decrypted_content):
|
||||||
@@ -267,12 +277,16 @@ async def receive_nostr(ctx: Context, verbose: bool):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
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(
|
t = threading.Thread(
|
||||||
target=client.get_dm,
|
target=client.get_dm,
|
||||||
args=(
|
args=(client.public_key, get_token_callback, {"since": last_check}),
|
||||||
client.public_key,
|
|
||||||
get_token_callback,
|
|
||||||
),
|
|
||||||
name="Nostr DM",
|
name="Nostr DM",
|
||||||
)
|
)
|
||||||
t.start()
|
t.start()
|
||||||
|
|||||||
@@ -334,3 +334,27 @@ async def update_lightning_invoice(
|
|||||||
hash,
|
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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "cashu"
|
name = "cashu"
|
||||||
version = "0.9.1"
|
version = "0.9.2"
|
||||||
description = "Ecash wallet and mint."
|
description = "Ecash wallet and mint."
|
||||||
authors = ["calle <callebtc@protonmail.com>"]
|
authors = ["calle <callebtc@protonmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -13,7 +13,7 @@ entry_points = {"console_scripts": ["cashu = cashu.wallet.cli:cli"]}
|
|||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name="cashu",
|
name="cashu",
|
||||||
version="0.9.1",
|
version="0.9.2",
|
||||||
description="Ecash wallet and mint for Bitcoin Lightning",
|
description="Ecash wallet and mint for Bitcoin Lightning",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
|||||||
Reference in New Issue
Block a user