mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-21 11:04:19 +01:00
fix nostr relay and refactor nostr_send and nostr_receive (#100)
* fix nostr relay and refactor nostr_send and nostr_receive * bump to 0.8.4 * make format * check test * close nostr
This commit is contained in:
@@ -115,7 +115,7 @@ cashu info
|
||||
|
||||
Returns:
|
||||
```bash
|
||||
Version: 0.8.3
|
||||
Version: 0.8.4
|
||||
Debug: False
|
||||
Cashu dir: /home/user/.cashu
|
||||
Wallet: wallet
|
||||
|
||||
@@ -54,7 +54,16 @@ LNBITS_ENDPOINT = env.str("LNBITS_ENDPOINT", default=None)
|
||||
LNBITS_KEY = env.str("LNBITS_KEY", default=None)
|
||||
|
||||
NOSTR_PRIVATE_KEY = env.str("NOSTR_PRIVATE_KEY", default=None)
|
||||
NOSTR_RELAYS = env.list("NOSTR_RELAYS", default=["wss://nostr-pub.wellorder.net"])
|
||||
NOSTR_RELAYS = env.list(
|
||||
"NOSTR_RELAYS",
|
||||
default=[
|
||||
"wss://nostr-pub.wellorder.net",
|
||||
"wss://relay.damus.io",
|
||||
"wss://nostr.zebedee.cloud",
|
||||
"wss://relay.snort.social",
|
||||
"wss://nostr.fmt.wiz.biz",
|
||||
],
|
||||
)
|
||||
|
||||
MAX_ORDER = 64
|
||||
VERSION = "0.8.3"
|
||||
VERSION = "0.8.4"
|
||||
|
||||
Submodule cashu/nostr updated: d7fb45f6a1...c5a050f944
@@ -36,8 +36,6 @@ from cashu.core.settings import (
|
||||
VERSION,
|
||||
)
|
||||
from cashu.nostr.nostr.client.client import NostrClient
|
||||
from cashu.nostr.nostr.event import Event
|
||||
from cashu.nostr.nostr.key import PublicKey
|
||||
from cashu.tor.tor import TorProxy
|
||||
from cashu.wallet import migrations
|
||||
from cashu.wallet.crud import (
|
||||
@@ -48,11 +46,13 @@ from cashu.wallet.crud import (
|
||||
)
|
||||
from cashu.wallet.wallet import Wallet as Wallet
|
||||
|
||||
from .clihelpers import (
|
||||
from .cli_helpers import (
|
||||
get_mint_wallet,
|
||||
print_mint_balances,
|
||||
proofs_to_serialized_tokenv2,
|
||||
receive_nostr,
|
||||
redeem_multimint,
|
||||
send_nostr,
|
||||
token_from_lnbits_link,
|
||||
verify_mints,
|
||||
)
|
||||
@@ -228,38 +228,6 @@ async def balance(ctx: Context, verbose):
|
||||
print(f"Balance: {wallet.available_balance} sat")
|
||||
|
||||
|
||||
async def nostr_send(ctx: Context, amount: int, pubkey: str, verbose: bool, yes: bool):
|
||||
"""
|
||||
Sends tokens via nostr.
|
||||
"""
|
||||
wallet = await get_mint_wallet(ctx)
|
||||
await wallet.load_proofs()
|
||||
_, send_proofs = await wallet.split_to_send(
|
||||
wallet.proofs, amount, set_reserved=True
|
||||
)
|
||||
token = await wallet.serialize_proofs(send_proofs)
|
||||
|
||||
print("")
|
||||
print(token)
|
||||
|
||||
if not yes:
|
||||
print("")
|
||||
click.confirm(
|
||||
f"Send {amount} sat to nostr pubkey {pubkey}?",
|
||||
abort=True,
|
||||
default=True,
|
||||
)
|
||||
|
||||
# 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"Token sent to {pubkey}")
|
||||
client.close()
|
||||
|
||||
|
||||
async def send(ctx: Context, amount: int, lock: str, legacy: bool):
|
||||
"""
|
||||
Prints token to send to stdout.
|
||||
@@ -340,7 +308,7 @@ async def send_command(
|
||||
if nostr is None:
|
||||
await send(ctx, amount, lock, legacy)
|
||||
else:
|
||||
await nostr_send(ctx, amount, nostr, verbose, yes)
|
||||
await send_nostr(ctx, amount, nostr, verbose, yes)
|
||||
|
||||
|
||||
async def receive(ctx: Context, token: str, lock: str):
|
||||
@@ -416,44 +384,11 @@ async def receive(ctx: Context, token: str, lock: str):
|
||||
# no mint information present, we extract the proofs and use wallet's default mint
|
||||
proofs = [Proof(**p) for p in dtoken["proofs"]]
|
||||
_, _ = await wallet.redeem(proofs, script, signature)
|
||||
print(f"Received {sum_proofs(proofs)} sats")
|
||||
|
||||
wallet.status()
|
||||
|
||||
|
||||
async def receive_nostr(ctx: Context, verbose: bool):
|
||||
if NOSTR_PRIVATE_KEY is None:
|
||||
print(
|
||||
"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()}")
|
||||
if verbose:
|
||||
print(f"Your nostr private key (do not share!): {client.private_key.hex()}")
|
||||
await asyncio.sleep(2)
|
||||
|
||||
def get_token_callback(event: Event, decrypted_content):
|
||||
if verbose:
|
||||
print(
|
||||
f"From {event.public_key[:3]}..{event.public_key[-3:]}: {decrypted_content}"
|
||||
)
|
||||
try:
|
||||
# call the receive method
|
||||
asyncio.run(receive(ctx, decrypted_content, ""))
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
t = threading.Thread(
|
||||
target=client.get_dm,
|
||||
args=(
|
||||
client.public_key,
|
||||
get_token_callback,
|
||||
),
|
||||
name="Nostr DM",
|
||||
)
|
||||
t.start()
|
||||
|
||||
|
||||
@cli.command("receive", help="Receive tokens.")
|
||||
@click.argument("token", type=str, default="")
|
||||
@click.option("--lock", "-l", default=None, help="Unlock tokens.", type=str)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import asyncio
|
||||
import os
|
||||
import threading
|
||||
import urllib.parse
|
||||
from typing import List
|
||||
|
||||
@@ -7,7 +9,11 @@ from click import Context
|
||||
from loguru import logger
|
||||
|
||||
from cashu.core.base import Proof, TokenV2, TokenV2Mint, WalletKeyset
|
||||
from cashu.core.settings import CASHU_DIR, MINT_URL
|
||||
from cashu.core.helpers import sum_proofs
|
||||
from cashu.core.settings import CASHU_DIR, MINT_URL, NOSTR_PRIVATE_KEY, NOSTR_RELAYS
|
||||
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.wallet import Wallet as Wallet
|
||||
|
||||
@@ -87,6 +93,7 @@ async def redeem_multimint(ctx: Context, token: TokenV2, script, signature):
|
||||
_, _ = await keyset_wallet.redeem(
|
||||
redeem_proofs, scnd_script=script, scnd_siganture=signature
|
||||
)
|
||||
print(f"Received {sum_proofs(redeem_proofs)} sats")
|
||||
|
||||
|
||||
async def print_mint_balances(ctx: Context, wallet, show_mints=False):
|
||||
@@ -196,3 +203,72 @@ async def proofs_to_serialized_tokenv2(wallet, proofs: List[Proof], url: str):
|
||||
token.mints.append(TokenV2Mint(url=url, ids=keysets))
|
||||
token_serialized = await wallet._serialize_token_base64(token)
|
||||
return token_serialized
|
||||
|
||||
|
||||
async def send_nostr(ctx: Context, amount: int, pubkey: str, verbose: bool, yes: bool):
|
||||
"""
|
||||
Sends tokens via nostr.
|
||||
"""
|
||||
# load a wallet for the chosen mint
|
||||
wallet = await get_mint_wallet(ctx)
|
||||
await wallet.load_proofs()
|
||||
_, send_proofs = await wallet.split_to_send(
|
||||
wallet.proofs, amount, set_reserved=True
|
||||
)
|
||||
token = await wallet.serialize_proofs(send_proofs)
|
||||
|
||||
print("")
|
||||
print(token)
|
||||
|
||||
if not yes:
|
||||
print("")
|
||||
click.confirm(
|
||||
f"Send {amount} sat to nostr pubkey {pubkey}?",
|
||||
abort=True,
|
||||
default=True,
|
||||
)
|
||||
|
||||
# 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"Token sent to {pubkey}")
|
||||
client.close()
|
||||
|
||||
|
||||
async def receive_nostr(ctx: Context, verbose: bool):
|
||||
if NOSTR_PRIVATE_KEY is None:
|
||||
print(
|
||||
"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()}")
|
||||
if verbose:
|
||||
print(f"Your nostr private key (do not share!): {client.private_key.hex()}")
|
||||
await asyncio.sleep(2)
|
||||
|
||||
def get_token_callback(event: Event, decrypted_content):
|
||||
if verbose:
|
||||
print(
|
||||
f"From {event.public_key[:3]}..{event.public_key[-3:]}: {decrypted_content}"
|
||||
)
|
||||
try:
|
||||
# call the receive method
|
||||
from cashu.wallet.cli import receive
|
||||
|
||||
asyncio.run(receive(ctx, decrypted_content, ""))
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
t = threading.Thread(
|
||||
target=client.get_dm,
|
||||
args=(
|
||||
client.public_key,
|
||||
get_token_callback,
|
||||
),
|
||||
name="Nostr DM",
|
||||
)
|
||||
t.start()
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "cashu"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
description = "Ecash wallet and mint."
|
||||
authors = ["calle <callebtc@protonmail.com>"]
|
||||
license = "MIT"
|
||||
|
||||
2
setup.py
2
setup.py
@@ -13,7 +13,7 @@ entry_points = {"console_scripts": ["cashu = cashu.wallet.cli:cli"]}
|
||||
|
||||
setuptools.setup(
|
||||
name="cashu",
|
||||
version="0.8.3",
|
||||
version="0.8.4",
|
||||
description="Ecash wallet and mint for Bitcoin Lightning",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
|
||||
@@ -115,3 +115,22 @@ def test_receive_tokenv1(mint):
|
||||
|
||||
print("RECEIVE")
|
||||
print(result.output)
|
||||
|
||||
|
||||
@pytest.mark.asyncio()
|
||||
def test_nostr_send(mint):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[
|
||||
*cli_prefix,
|
||||
"send",
|
||||
"1",
|
||||
"-n",
|
||||
"aafa164a8ab54a6b6c67bbac98a5d5aec7ea4075af8928a11478ab9d74aec4ca",
|
||||
"-y",
|
||||
],
|
||||
)
|
||||
|
||||
print("NOSTR_SEND")
|
||||
print(result.output)
|
||||
|
||||
Reference in New Issue
Block a user