NAME
Net::Nostr::ClassifiedListing - NIP-99 classified listings
SYNOPSIS
use Net::Nostr::ClassifiedListing;
my $pubkey = 'aa' x 32;
# Create a classified listing (kind 30402)
my $event = Net::Nostr::ClassifiedListing->listing(
pubkey => $pubkey,
content => "# Vintage Guitar\n\nGreat condition, barely played.",
identifier => 'vintage-guitar',
title => 'Vintage Guitar',
summary => 'A beautiful vintage guitar in great condition',
published_at => 1296962229,
location => 'NYC',
price => ['500', 'USD'],
status => 'active',
hashtags => ['music', 'instruments'],
images => [
['https://example.com/guitar1.jpg', '800x600'],
['https://example.com/guitar2.jpg'],
],
);
# Create a draft/inactive listing (kind 30403, same structure)
my $draft = Net::Nostr::ClassifiedListing->draft(
pubkey => $pubkey,
content => "# WIP Listing\n\nNot ready yet.",
identifier => 'my-draft',
title => 'Work in Progress',
);
# Recurring price (e.g. monthly rent)
my $rental = Net::Nostr::ClassifiedListing->listing(
pubkey => $pubkey,
content => "Apartment for rent.",
identifier => 'apartment-rent',
title => '2BR Apartment',
price => ['1500', 'USD', 'month'],
location => 'Brooklyn',
);
# Parse listing metadata from an event
my $info = Net::Nostr::ClassifiedListing->from_event($event);
say $info->title; # 'Vintage Guitar'
say $info->location; # 'NYC'
say $info->price->[0]; # '500'
say $info->price->[1]; # 'USD'
# Generate an naddr for linking
my $naddr = Net::Nostr::ClassifiedListing->to_naddr($event,
relays => ['wss://relay.example.com'],
);
# Validate a listing event
Net::Nostr::ClassifiedListing->validate($event);
DESCRIPTION
Implements NIP-99 classified listings. Classified listings are kind 30402 addressable events that describe products, services, or other things for sale or offer. The structure is similar to NIP-23 long-form content, with additional metadata tags for pricing, location, and status.
Content should be a Markdown description of what is being offered. The pubkey field identifies the party creating the listing.
Draft or inactive listings use kind 30403, which has the same structure as kind 30402.
CONSTRUCTOR
new
my $info = Net::Nostr::ClassifiedListing->new(%fields);
Creates a new Net::Nostr::ClassifiedListing object. Typically returned by "from_event"; calling new directly is useful for testing or manual construction.
my $info = Net::Nostr::ClassifiedListing->new(
identifier => 'my-listing',
title => 'Guitar',
price => '500 USD',
location => 'NYC',
);
Accepted fields: identifier, title, summary, published_at, location, price, status, images (defaults to []), hashtags (defaults to []). Croaks on unknown arguments.
CLASS METHODS
listing
my $event = Net::Nostr::ClassifiedListing->listing(
pubkey => $hex_pubkey, # required
content => $markdown, # required
identifier => 'listing-slug', # required (d tag)
title => 'Listing Title', # optional
summary => 'Short tagline.', # optional
published_at => 1296962229, # optional (unix timestamp)
location => 'NYC', # optional
price => ['100', 'USD'], # optional
status => 'active', # optional ("active" or "sold")
hashtags => ['electronics'], # optional (t tags)
images => [['url', '256x256']],# optional (image tags)
extra_tags => [['g', 'dr5regw']], # optional (additional tags)
created_at => time(), # optional
);
Creates a kind 30402 classified listing Net::Nostr::Event. pubkey, content, and identifier are required.
The price parameter is an arrayref of [amount, currency] or [amount, currency, frequency] where currency is an ISO 4217 code (or crypto code like btc) and frequency is optional (e.g. month, year).
# One-time: $50 USD
price => ['50', 'USD']
# Recurring: 15 EUR/month
price => ['15', 'EUR', 'month']
The images parameter is an arrayref of arrayrefs. Each inner arrayref contains a URL and an optional dimensions string (WxH in pixels), per NIP-58.
images => [
['https://example.com/photo.jpg', '800x600'],
['https://example.com/detail.jpg'],
]
draft
my $event = Net::Nostr::ClassifiedListing->draft(
pubkey => $hex_pubkey,
content => $markdown,
identifier => 'draft-slug',
# same optional params as listing()
);
Creates a kind 30403 draft/inactive listing. Accepts the same parameters as "listing".
from_event
my $info = Net::Nostr::ClassifiedListing->from_event($event);
Parses listing metadata from a kind 30402 or 30403 Net::Nostr::Event. Returns a Net::Nostr::ClassifiedListing object with accessors, or undef if the event is not a listing kind.
my $info = Net::Nostr::ClassifiedListing->from_event($event);
say $info->identifier; # 'my-listing'
say $info->title; # 'Vintage Guitar' or undef
say $info->price->[1] if $info->price; # 'USD'
validate
Net::Nostr::ClassifiedListing->validate($event);
Validates that an event is a well-formed NIP-99 listing. Croaks if:
Kind is not 30402 or 30403
Missing
dtag
eval { Net::Nostr::ClassifiedListing->validate($event) };
warn "Invalid listing: $@" if $@;
to_naddr
my $naddr = Net::Nostr::ClassifiedListing->to_naddr($event,
relays => ['wss://relay.com'],
);
Generates a NIP-19 naddr bech32 string for linking to the listing. The relays parameter is optional.
ACCESSORS
These are available on objects returned by "from_event".
identifier
my $id = $info->identifier;
The d tag value identifying the listing.
title
my $title = $info->title; # or undef
The listing title, or undef if not set.
summary
my $text = $info->summary; # or undef
Short tagline or summary for the listing, or undef.
published_at
my $ts = $info->published_at; # '1296962229' or undef
The original publication timestamp (stringified unix seconds), or undef.
location
my $loc = $info->location; # 'NYC' or undef
The listing location, or undef.
price
my $price = $info->price; # ['100', 'USD'] or ['15', 'EUR', 'month'] or undef
Arrayref of [amount, currency] or [amount, currency, frequency], or undef if no price tag is present.
status
my $status = $info->status; # 'active', 'sold', or undef
The listing status, or undef.
images
my $imgs = $info->images; # [['url', '256x256'], ['url2']]
Arrayref of arrayrefs, each containing a URL and optional dimensions. Empty arrayref if no image tags are present.
hashtags
my $tags = $info->hashtags; # ['electronics', 'gadgets']
Arrayref of hashtag strings from t tags. Empty arrayref if none.