NAME
Net::Nostr::Nutzap - NIP-61 nutzaps (Cashu ecash payments)
SYNOPSIS
use Net::Nostr::Nutzap;
my $pubkey = 'aa' x 32;
my $p2pk_pubkey = 'cc' x 32;
# Publish nutzap info (kind 10019) - tells others how to send you ecash
my $info = Net::Nostr::Nutzap->info_event(
pubkey => $pubkey,
relays => ['wss://relay1', 'wss://relay2'],
mints => [
{ url => 'https://mint1', units => ['usd', 'sat'] },
{ url => 'https://mint2', units => ['sat'] },
],
p2pk_pubkey => $p2pk_pubkey,
);
# Send a nutzap (kind 9321)
my $proof_json = '{"amount":1,"C":"02...","id":"000a","secret":"..."}';
my $zap = Net::Nostr::Nutzap->nutzap(
pubkey => $pubkey,
recipient => 'bb' x 32,
proofs => [$proof_json],
mint_url => 'https://mint1',
unit => 'sat',
event_id => 'dd' x 32,
event_kind => '1',
content => 'Great post!',
);
# Record redemption (kind 7376)
my $nutzap_event_id = 'ee' x 32;
my $redeem = Net::Nostr::Nutzap->redemption(
pubkey => $pubkey,
nutzap_ids => [$nutzap_event_id],
sender_pubkey => 'bb' x 32,
relay_hint => 'wss://relay1',
content => $encrypted_content, # NIP-44 encrypted
);
# Parse any nutzap-related event
my $parsed = Net::Nostr::Nutzap->from_event($event);
# Validate
Net::Nostr::Nutzap->validate($event);
DESCRIPTION
Implements NIP-61 nutzaps -- peer-to-peer Cashu ecash payments over Nostr. A nutzap is a P2PK-locked Cashu token where the payment itself is the receipt.
Three event kinds are involved:
- kind 10019 - Nutzap informational event (replaceable). Lists the user's trusted mints, relay preferences, and P2PK public key for receiving nutzaps. The P2PK pubkey MUST NOT be the user's main Nostr public key.
- kind 9321 - Nutzap event. Published by the sender, containing Cashu proofs P2PK-locked to the recipient's specified public key. Includes the mint URL, unit, and optional event reference.
- kind 7376 - Nutzap redemption history. Created when claiming tokens, tagging the original nutzap event(s) with a
redeemedmarker.
CONSTRUCTOR
new
my $info = Net::Nostr::Nutzap->new(%fields);
Creates a new Net::Nostr::Nutzap object. Typically returned by "from_event"; calling new directly is useful for testing or manual construction.
my $info = Net::Nostr::Nutzap->new(
mint_url => 'https://mint1',
unit => 'sat',
recipient => $hex_pubkey,
proofs => [],
);
Accepted fields: relays (defaults to []), mints (defaults to []), p2pk_pubkey, proofs (defaults to []), mint_url, unit, recipient, event_id, event_kind, nutzap_ids (defaults to []), sender_pubkey. Croaks on unknown arguments.
CLASS METHODS
info_event
my $event = Net::Nostr::Nutzap->info_event(
pubkey => $hex_pubkey,
relays => ['wss://relay1'],
mints => [{ url => 'https://mint1', units => ['sat'] }],
p2pk_pubkey => $hex_p2pk_key,
);
Creates a kind 10019 nutzap informational Net::Nostr::Event. pubkey, relays, mints, and p2pk_pubkey are required. Each mint entry is a hashref with url and an optional units arrayref of supported base units (e.g. sat, usd).
nutzap
my $event = Net::Nostr::Nutzap->nutzap(
pubkey => $hex_pubkey, # required
recipient => $hex_pubkey, # required (p tag)
proofs => [$proof_json, ...], # required (proof tags)
mint_url => 'https://mint', # required (u tag)
unit => 'sat', # optional, default 'sat'
event_id => $hex_event_id, # optional (e tag)
event_kind => '1', # optional (k tag)
relay_hint => 'wss://relay', # optional
content => 'nice!', # optional comment
);
Creates a kind 9321 nutzap Net::Nostr::Event. pubkey, recipient, proofs, and mint_url are required. Multiple proofs create multiple proof tags.
redemption
my $event = Net::Nostr::Nutzap->redemption(
pubkey => $hex_pubkey,
nutzap_ids => [$event_id, ...],
sender_pubkey => $hex_pubkey,
relay_hint => 'wss://relay', # optional
content => $encrypted, # optional (NIP-44 encrypted)
);
Creates a kind 7376 redemption Net::Nostr::Event. Multiple nutzap IDs can be tagged in a single redemption. Each e tag includes the redeemed marker.
The content parameter accepts pre-encrypted NIP-44 data containing the redemption details (direction, amount, unit, created token reference). Defaults to empty string if not provided.
from_event
my $info = Net::Nostr::Nutzap->from_event($event);
Parses a kind 10019, 9321, or 7376 event into a Net::Nostr::Nutzap object. Returns undef for unrecognized kinds.
validate
Net::Nostr::Nutzap->validate($event);
Validates a nutzap-related event. Croaks on invalid structure.
For kind 10019: requires at least one relay tag, one mint tag, and a pubkey tag.
For kind 9321: requires at least one proof tag, a u tag (mint URL), and a p tag (recipient).
For kind 7376: requires at least one e tag.
ACCESSORS
Available on objects returned by "from_event". Which accessors contain data depends on the event kind parsed.
relays
Arrayref of relay URLs (kind 10019).
mints
Arrayref of hashrefs with url and units keys (kind 10019).
p2pk_pubkey
The P2PK public key for receiving nutzaps (kind 10019).
proofs
Arrayref of proof JSON strings (kind 9321).
mint_url
The mint URL from the u tag (kind 9321).
unit
The base unit (kind 9321), e.g. sat, usd.
recipient
The recipient's Nostr pubkey from the p tag (kind 9321).
event_id
The nutzapped event ID from the e tag (kind 9321), or undef.
event_kind
The nutzapped event kind from the k tag (kind 9321), or undef.
nutzap_ids
Arrayref of redeemed nutzap event IDs (kind 7376).
sender_pubkey
The nutzap sender's pubkey from the p tag (kind 7376).