nostrdvm/tutorials/09_nutzap_client.py
2024-11-27 22:30:32 +01:00

128 lines
5.7 KiB
Python

# 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(tags).sign_with_keys(keys)
client = Client(NostrSigner.keys(keys))
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()} ")
client = Client(NostrSigner.keys(keys))
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().to_vec():
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))