mirror of
https://github.com/believethehype/nostrdvm.git
synced 2025-03-17 13:21:48 +01:00
add tutorials 8 and 9 - nutzaps
This commit is contained in:
parent
cffeaae62f
commit
3dd7ecad9f
@ -563,9 +563,15 @@ class NutZapWallet:
|
||||
break
|
||||
# If that's not the case, lets look or mints we both trust, take the first one.
|
||||
if not sufficent_budget:
|
||||
mint_url = next(i for i in nut_wallet.mints if i in mints)
|
||||
mint = self.get_mint(nut_wallet, mint_url)
|
||||
if mint.available_balance() < amount:
|
||||
try:
|
||||
mint_url = next(i for i in nut_wallet.mints if i in mints)
|
||||
if mint_url is not None:
|
||||
mint = self.get_mint(nut_wallet, mint_url)
|
||||
if mint.available_balance() < amount:
|
||||
await self.handle_low_balance_on_mint(nut_wallet, mint_url, mint, amount, client, keys)
|
||||
except StopIteration:
|
||||
mint = self.get_mint(nut_wallet, mints[0])
|
||||
mint_url = mint.mint_url
|
||||
await self.handle_low_balance_on_mint(nut_wallet, mint_url, mint, amount, client, keys)
|
||||
|
||||
# If that's not the case, iterate over the recipents mints and try to mint there. This might be a bit dangerous as not all mints might give cashu, so loss of ln is possible
|
||||
|
@ -5,9 +5,6 @@
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from secp256k1 import PublicKey
|
||||
|
||||
from nostr_dvm.utils.dvmconfig import DVMConfig
|
||||
from nostr_dvm.utils.print_utils import bcolors
|
||||
|
||||
|
@ -21,6 +21,7 @@ from nostr_sdk import Kind, Keys
|
||||
from nostr_dvm.utils.admin_utils import AdminConfig
|
||||
from nostr_dvm.utils.dvmconfig import build_default_config, DVMConfig
|
||||
from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag
|
||||
from nostr_dvm.utils.nut_wallet_utils import NutZapWallet
|
||||
from nostr_dvm.utils.outbox_utils import AVOID_OUTBOX_RELAY_LIST
|
||||
from nostr_dvm.utils.zap_utils import change_ln_address
|
||||
|
||||
@ -30,6 +31,7 @@ def run_dvm(identifier, announce):
|
||||
dvm_config = build_default_config(identifier)
|
||||
kind = Kind(5050)
|
||||
dvm_config.KIND = kind
|
||||
dvm_config.FIX_COST = 3
|
||||
|
||||
# Once you installed cashu, the rest is pretty staight forward:
|
||||
|
||||
@ -38,10 +40,14 @@ def run_dvm(identifier, announce):
|
||||
# Define a relay to update your balance
|
||||
dvm_config.NUTZAP_RELAYS = ["wss://relay.primal.net"]
|
||||
# Define one or more mints you would like to receive on.
|
||||
dvm_config.NUZAP_MINTS = ["https://mint.minibits.cash/Bitcoin", "https://mint.gwoq.com"]
|
||||
dvm_config.NUZAP_MINTS = ["https://mint.gwoq.com"]
|
||||
# If you want you can auto_melt cashu token to your lightning address once they pass a certain threshold.
|
||||
dvm_config.ENABLE_AUTO_MELT = False
|
||||
dvm_config.AUTO_MELT_AMOUNT = 1000
|
||||
# If you update your mints in NUTZAP_MINTS make sure to reannounce these.
|
||||
dvm_config.REANNOUNCE_MINTS = True
|
||||
|
||||
|
||||
|
||||
|
||||
options = {
|
||||
@ -67,7 +73,7 @@ def run_dvm(identifier, announce):
|
||||
return result
|
||||
|
||||
dvm.process = process
|
||||
dvm.run()
|
||||
dvm.run(True)
|
||||
|
||||
|
||||
|
131
tutorials/09_nutzap_client.py
Normal file
131
tutorials/09_nutzap_client.py
Normal file
@ -0,0 +1,131 @@
|
||||
|
||||
# This is the complementary tutorial for tutorial 08. Sending nutzaps.
|
||||
# Make sure tutorial 08 is running while testing this. Also make sure you lnbits config is set,
|
||||
# or manually change the code to access a wallet to mint tokens.
|
||||
# Check especially the code in line 76 and make sure to replace the npub with the one from
|
||||
# the dvm in tutorial 8 in line 120.
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import dotenv
|
||||
from nostr_sdk import PublicKey, Client, NostrSigner, EventBuilder, Kind, Tag, Keys, Timestamp, HandleNotification, \
|
||||
Filter, Event
|
||||
|
||||
import asyncio
|
||||
|
||||
from nostr_dvm.utils.definitions import EventDefinitions
|
||||
from nostr_dvm.utils.dvmconfig import DVMConfig
|
||||
from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key
|
||||
from nostr_dvm.utils.nut_wallet_utils import NutZapWallet
|
||||
from nostr_dvm.utils.print_utils import bcolors
|
||||
|
||||
|
||||
# You already know this from our previous test client in tutorial 03: We simply send a kind 5050 request
|
||||
# to return some text, just as before. Note: Our dvm in tutorial 08 requires a payment of 3 sats.
|
||||
async def nostr_client_generic_test(ptag):
|
||||
keys = Keys.parse(check_and_set_private_key("test_client"))
|
||||
relay_list = ["wss://nostr.oxtr.dev", "wss://relay.primal.net"]
|
||||
relaysTag = Tag.parse(["relays"] + relay_list)
|
||||
alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task"])
|
||||
paramTag = Tag.parse(["param", "some_option", "#RUNDVM - With a Nutzap."])
|
||||
pTag = Tag.parse(["p", PublicKey.parse(ptag).to_hex()])
|
||||
tags = [relaysTag, alttag, pTag, paramTag]
|
||||
event = EventBuilder(Kind(5050), "This is a test",
|
||||
tags).to_event(keys)
|
||||
|
||||
signer = NostrSigner.keys(keys)
|
||||
client = Client(signer)
|
||||
for relay in relay_list:
|
||||
await client.add_relay(relay)
|
||||
await client.connect()
|
||||
result = await send_event(event, client=client, dvm_config=DVMConfig())
|
||||
print(result)
|
||||
|
||||
|
||||
async def nostr_client(target_dvm_npub):
|
||||
|
||||
keys = Keys.parse(check_and_set_private_key("test_client"))
|
||||
pk = keys.public_key()
|
||||
print(f"Nostr Client public key: {pk.to_bech32()}, Hex: {pk.to_hex()} ")
|
||||
signer = NostrSigner.keys(keys)
|
||||
client = Client(signer)
|
||||
|
||||
dvmconfig = DVMConfig()
|
||||
for relay in dvmconfig.RELAY_LIST:
|
||||
await client.add_relay(relay)
|
||||
await client.connect()
|
||||
|
||||
kinds = [EventDefinitions.KIND_NIP90_GENERIC]
|
||||
for kind in range(6000, 7001):
|
||||
if kind not in kinds:
|
||||
kinds.append(Kind(kind))
|
||||
|
||||
dvm_filter = (Filter().kinds(kinds).since(Timestamp.now()).pubkey(pk))
|
||||
await client.subscribe([dvm_filter], None)
|
||||
|
||||
# This will send a request to the DVM
|
||||
await nostr_client_generic_test(target_dvm_npub)
|
||||
|
||||
# We listen to
|
||||
class NotificationHandler(HandleNotification):
|
||||
last_event_time = 0
|
||||
async def handle(self, relay_url, subscription_id, event: Event):
|
||||
if event.kind().as_u16() == 7000:
|
||||
print(bcolors.YELLOW + "[Nostr Client]: " + event.content() + bcolors.ENDC)
|
||||
amount_sats = 0
|
||||
status = ""
|
||||
for tag in event.tags():
|
||||
if tag.as_vec()[0] == "amount":
|
||||
amount_sats = int(int(tag.as_vec()[1]) / 1000) # millisats
|
||||
if tag.as_vec()[0] == "status":
|
||||
status = tag.as_vec()[1]
|
||||
|
||||
if status == "payment-required":
|
||||
print("do a nutzap of " + str(amount_sats) +" sats here")
|
||||
|
||||
send_zap_amount = amount_sats
|
||||
send_zap_message = "From my nutsack"
|
||||
send_receiver = event.author().to_hex()
|
||||
send_zapped_event = event.id().to_hex() # None # None, or zap an event like this: Nip19Event.from_nostr_uri("nostr:nevent1qqsxq59mhz8s6aj9jzltcmqmmv3eutsfcpkeny2x755vdu5dtq44ldqpz3mhxw309ucnydewxqhrqt338g6rsd3e9upzp75cf0tahv5z7plpdeaws7ex52nmnwgtwfr2g3m37r844evqrr6jqvzqqqqqqyqtxyr6").event_id().to_hex()
|
||||
zapped_event_id_hex = send_zapped_event
|
||||
nutzap_wallet = NutZapWallet()
|
||||
nut_wallet = await nutzap_wallet.get_nut_wallet(client, keys)
|
||||
|
||||
if nut_wallet is None:
|
||||
relays = DVMConfig().NUTZAP_RELAYS
|
||||
mints = DVMConfig().NUZAP_MINTS
|
||||
await nutzap_wallet.create_new_nut_wallet(mints, relays, client, keys, "Test", "My Nutsack")
|
||||
nut_wallet = await nutzap_wallet.get_nut_wallet(client, keys)
|
||||
if nut_wallet is not None:
|
||||
await nutzap_wallet.announce_nutzap_info_event(nut_wallet, client, keys)
|
||||
else:
|
||||
print("Couldn't fetch wallet, please restart and see if it is there")
|
||||
|
||||
await nutzap_wallet.send_nut_zap(send_zap_amount, send_zap_message, nut_wallet, zapped_event_id_hex, send_receiver, client,
|
||||
keys)
|
||||
|
||||
elif 6000 < event.kind().as_u16() < 6999:
|
||||
print(bcolors.GREEN + "[Nostr Client]: " + event.content() + bcolors.ENDC)
|
||||
|
||||
|
||||
async def handle_msg(self, relay_url, msg):
|
||||
return
|
||||
|
||||
asyncio.create_task(client.handle_notifications(NotificationHandler()))
|
||||
# await client.handle_notifications(NotificationHandler())
|
||||
while True:
|
||||
await asyncio.sleep(2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
env_path = Path('.env')
|
||||
if env_path.is_file():
|
||||
print(f'loading environment from {env_path.resolve()}')
|
||||
dotenv.load_dotenv(env_path, verbose=True, override=True)
|
||||
else:
|
||||
raise FileNotFoundError(f'.env file not found at {env_path} ')
|
||||
|
||||
# Replace this key with the one from your DVM from part 8.
|
||||
target_dvm_npub = "npub150laafgrw4dlj5pc7jk2qzhxkghtqn9pplsyg8u6jkpd9afaszzsu06p39"
|
||||
asyncio.run(nostr_client(target_dvm_npub))
|
Loading…
x
Reference in New Issue
Block a user